tgstation-server 5.12.7
The /tg/station 13 server suite
Loading...
Searching...
No Matches
TokenFactory.cs
Go to the documentation of this file.
1using System;
2using System.Globalization;
3using System.IdentityModel.Tokens.Jwt;
4using System.Security.Claims;
5using System.Threading;
6using System.Threading.Tasks;
7
8using Microsoft.Extensions.Options;
9using Microsoft.IdentityModel.Tokens;
10
15
17{
20 {
22 public TokenValidationParameters ValidationParameters { get; }
23
28
33
43 ICryptographySuite cryptographySuite,
44 IAssemblyInformationProvider assemblyInformationProvider,
45 IOptions<SecurityConfiguration> securityConfigurationOptions)
46 {
47 this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
48
49 ArgumentNullException.ThrowIfNull(cryptographySuite);
50 ArgumentNullException.ThrowIfNull(assemblyInformationProvider);
51
52 securityConfiguration = securityConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(securityConfigurationOptions));
53
54 var signingKeyBytes = String.IsNullOrWhiteSpace(securityConfiguration.CustomTokenSigningKeyBase64)
56 : Convert.FromBase64String(securityConfiguration.CustomTokenSigningKeyBase64);
57
58 ValidationParameters = new TokenValidationParameters
59 {
60 ValidateIssuerSigningKey = true,
61 IssuerSigningKey = new SymmetricSecurityKey(signingKeyBytes),
62
63 ValidateIssuer = true,
64 ValidIssuer = assemblyInformationProvider.AssemblyName.Name,
65
66 ValidateLifetime = true,
67 ValidateAudience = true,
68 ValidAudience = typeof(TokenResponse).Assembly.GetName().Name,
69
70 ClockSkew = TimeSpan.FromMinutes(securityConfiguration.TokenClockSkewMinutes),
71
72 RequireSignedTokens = true,
73
74 RequireExpirationTime = true,
75 };
76 }
77
79 public async Task<TokenResponse> CreateToken(Models.User user, bool oAuth, CancellationToken cancellationToken)
80 {
81 ArgumentNullException.ThrowIfNull(user);
82
83 var now = DateTimeOffset.UtcNow;
84 var nowUnix = now.ToUnixTimeSeconds();
85
86 // this prevents validation conflicts down the line
87 // tldr we can (theoretically) send a token the same second we receive it
88 // since unix time rounds down, it looks like it came from before the user changed their password
89 // this happens occasionally in unit tests
90 // just delay a second so we can force a round up
91 var lpuUnix = user.LastPasswordUpdate?.ToUnixTimeSeconds();
92 if (nowUnix == lpuUnix)
93 await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken);
94
95 var expiry = now.AddMinutes(oAuth
98 var claims = new Claim[]
99 {
100 new Claim(JwtRegisteredClaimNames.Sub, user.Id.Value.ToString(CultureInfo.InvariantCulture)),
101 new Claim(JwtRegisteredClaimNames.Exp, expiry.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture)),
102 new Claim(JwtRegisteredClaimNames.Nbf, nowUnix.ToString(CultureInfo.InvariantCulture)),
103 new Claim(JwtRegisteredClaimNames.Iss, ValidationParameters.ValidIssuer),
104 new Claim(JwtRegisteredClaimNames.Aud, ValidationParameters.ValidAudience),
105 };
106
107 var token = new JwtSecurityToken(new JwtHeader(new SigningCredentials(ValidationParameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256)), new JwtPayload(claims));
108 return new TokenResponse
109 {
110 Bearer = new JwtSecurityTokenHandler().WriteToken(token),
111 ExpiresAt = expiry,
112 };
113 }
114 }
115}
Represents a JWT returned by the API.
Definition: TokenResponse.cs:9
Configuration options pertaining to user security.
string CustomTokenSigningKeyBase64
A custom token signing key. Overrides TokenSigningKeyByteCount.
uint TokenSigningKeyByteCount
Amount of bytes to use in the Microsoft.IdentityModel.Tokens.TokenValidationParameters....
uint TokenClockSkewMinutes
Amount of minutes to skew the clock for Api.Models.Response.TokenResponse validation.
uint OAuthTokenExpiryMinutes
Amount of minutes until Api.Models.Response.TokenResponses generated from OAuth logins expire.
uint TokenExpiryMinutes
Amount of minutes until Api.Models.Response.TokenResponses generated from passwords expire.
async Task< TokenResponse > CreateToken(Models.User user, bool oAuth, CancellationToken cancellationToken)
Create a TokenResponse for a given user . A Task<TResult> resulting in a new TokenResponse.
Definition: TokenFactory.cs:79
TokenValidationParameters ValidationParameters
The TokenValidationParameters for the ITokenFactory.
Definition: TokenFactory.cs:22
TokenFactory(IAsyncDelayer asyncDelayer, ICryptographySuite cryptographySuite, IAssemblyInformationProvider assemblyInformationProvider, IOptions< SecurityConfiguration > securityConfigurationOptions)
Initializes a new instance of the TokenFactory class.
Definition: TokenFactory.cs:41
readonly SecurityConfiguration securityConfiguration
The SecurityConfiguration for the TokenFactory.
Definition: TokenFactory.cs:27
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the TokenFactory.
Definition: TokenFactory.cs:32
Contains various cryptographic functions.
byte[] GetSecureBytes(uint amount)
Generates a secure set of bytes.
AssemblyName AssemblyName
Gets the global::System.Reflection.AssemblyName.
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan .