1 using Microsoft.IdentityModel.Tokens;
4 using System.IdentityModel.Tokens.Jwt;
5 using System.Security.Claims;
7 using System.Threading.Tasks;
20 const uint TokenExpiryMinutes = 15;
25 const uint TokenClockSkewMinutes = 1;
30 const uint TokenSigningKeyByteAmount = 256;
33 public TokenValidationParameters ValidationParameters {
get; }
51 ValidationParameters =
new TokenValidationParameters
53 ValidateIssuerSigningKey =
true,
54 IssuerSigningKey =
new SymmetricSecurityKey(cryptographySuite.
GetSecureBytes(TokenSigningKeyByteAmount)),
56 ValidateIssuer =
true,
57 ValidIssuer = assemblyInformationProvider.
Name.Name,
59 ValidateLifetime =
true,
60 ValidateAudience =
true,
61 ValidAudience = typeof(
Token).Assembly.GetName().Name,
63 ClockSkew = TimeSpan.FromMinutes(TokenClockSkewMinutes),
65 RequireSignedTokens =
true,
67 RequireExpirationTime =
true 70 this.asyncDelayer = asyncDelayer ??
throw new ArgumentNullException(nameof(asyncDelayer));
74 public async Task<Token>
CreateToken(Models.User user, CancellationToken cancellationToken)
77 throw new ArgumentNullException(nameof(user));
79 var now = DateTimeOffset.Now;
80 var nowUnix = now.ToUnixTimeSeconds();
87 var lpuUnix = user.LastPasswordUpdate?.ToUnixTimeSeconds();
88 if (nowUnix == lpuUnix)
89 await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(
false);
91 var expiry = now.AddMinutes(TokenExpiryMinutes);
92 var claims =
new Claim[]
94 new Claim(JwtRegisteredClaimNames.Sub, user.Id.Value.ToString(CultureInfo.InvariantCulture)),
95 new Claim(JwtRegisteredClaimNames.Exp, expiry.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture)),
96 new Claim(JwtRegisteredClaimNames.Nbf, nowUnix.ToString(CultureInfo.InvariantCulture)),
97 new Claim(JwtRegisteredClaimNames.Iss, ValidationParameters.ValidIssuer),
98 new Claim(JwtRegisteredClaimNames.Aud, ValidationParameters.ValidAudience)
101 var token =
new JwtSecurityToken(
new JwtHeader(
new SigningCredentials(ValidationParameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256)),
new JwtPayload(claims));
104 Bearer =
new JwtSecurityTokenHandler().WriteToken(token),
Use server authentication
byte[] GetSecureBytes(uint amount)
Generates a secure set of bytes
For waiting asynchronously
Contains various cryptographic functions
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the TokenFactory
Represents a JWT returned by the API
async Task< Token > CreateToken(Models.User user, CancellationToken cancellationToken)
Create a Token for a given user
TokenFactory(IAsyncDelayer asyncDelayer, ICryptographySuite cryptographySuite, IAssemblyInformationProvider assemblyInformationProvider)
Construct a TokenFactory