Merge authentication into Questions API
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using QuestionsApi.Models;
|
||||
using QuestionsApi.Services;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using Xunit;
|
||||
|
||||
namespace QuestionsApi.Tests;
|
||||
|
||||
public sealed class AuthTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("valid_user", "[email protected]", "password1", null)]
|
||||
[InlineData("ab", "[email protected]", "password1", "Username")]
|
||||
[InlineData("invalid-user", "[email protected]", "password1", "Username")]
|
||||
[InlineData("valid_user", "not-an-email", "password1", "email")]
|
||||
[InlineData("valid_user", "[email protected]", "short", "Password")]
|
||||
public void NewAccountValidationRejectsInvalidInput(
|
||||
string username, string email, string password, string? expectedError)
|
||||
{
|
||||
var result = AuthValidation.ValidateNewAccount(username, email, password);
|
||||
if (expectedError is null) Assert.Null(result);
|
||||
else Assert.Contains(expectedError, result!, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PasswordResetCodesAreSixDigitsAndBoundToTheirRequest()
|
||||
{
|
||||
var service = new PasswordResetCodeService(Configuration(new Dictionary<string, string?>
|
||||
{
|
||||
["PasswordReset:HmacKey"] = "A-test-only-key-that-is-longer-than-thirty-two-bytes"
|
||||
}));
|
||||
var code = service.GenerateCode();
|
||||
var hash = service.Hash("request-one", code);
|
||||
|
||||
Assert.Matches("^[0-9]{6}$", code);
|
||||
Assert.True(service.Verify("request-one", code, hash));
|
||||
Assert.False(service.Verify("request-two", code, hash));
|
||||
Assert.False(service.Verify("request-one", "000000", hash));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PasswordResetCanRemainUnconfiguredWithoutBreakingAuthentication()
|
||||
{
|
||||
var service = new PasswordResetCodeService(Configuration([]));
|
||||
Assert.False(service.IsConfigured);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JwtContainsCompatibleIdentityRoleAndAuthVersionClaims()
|
||||
{
|
||||
var service = new JwtTokenService(Configuration(new Dictionary<string, string?>
|
||||
{
|
||||
["Jwt:Key"] = "A-test-only-jwt-key-that-is-longer-than-thirty-two-bytes",
|
||||
["Jwt:Issuer"] = "promiscuity",
|
||||
["Jwt:Audience"] = "promiscuity-auth-api"
|
||||
}));
|
||||
var user = new AuthUser
|
||||
{
|
||||
Id = "507f1f77bcf86cd799439011",
|
||||
Username = "doctor",
|
||||
Role = "SUPER",
|
||||
AuthVersion = 4
|
||||
};
|
||||
|
||||
var generated = service.Generate(user);
|
||||
var token = new JwtSecurityTokenHandler().ReadJwtToken(generated.Token);
|
||||
|
||||
Assert.Equal("promiscuity", token.Issuer);
|
||||
Assert.Contains("promiscuity-auth-api", token.Audiences);
|
||||
Assert.Equal("4", token.Claims.Single(claim => claim.Type == "auth_ver").Value);
|
||||
Assert.Equal(generated.Jti, token.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LegacyUsersDefaultToAuthVersionZero()
|
||||
{
|
||||
Assert.Equal(0, new AuthUser().AuthVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SteamClaimedIdExtractionRejectsUnexpectedHostsAndLengths()
|
||||
{
|
||||
Assert.Equal("76561198000000000",
|
||||
SteamOpenIdService.ExtractSteamId("https://steamcommunity.com/openid/id/76561198000000000"));
|
||||
Assert.Null(SteamOpenIdService.ExtractSteamId("https://example.com/openid/id/76561198000000000"));
|
||||
Assert.Null(SteamOpenIdService.ExtractSteamId("https://steamcommunity.com/openid/id/123"));
|
||||
}
|
||||
|
||||
private static IConfiguration Configuration(Dictionary<string, string?> values) =>
|
||||
new ConfigurationBuilder().AddInMemoryCollection(values).Build();
|
||||
}
|
||||
Reference in New Issue
Block a user