tgstation-server 6.8.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
TokenFactory.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Globalization;
4using System.IdentityModel.Tokens.Jwt;
5using System.Linq;
6using System.Security.Claims;
7
8using Microsoft.Extensions.Options;
9using Microsoft.IdentityModel.Tokens;
10
15
17{
20 {
22 public TokenValidationParameters ValidationParameters { get; }
23
28
32 readonly JwtHeader tokenHeader;
33
37 readonly JwtSecurityTokenHandler tokenHandler;
38
46 ICryptographySuite cryptographySuite,
47 IAssemblyInformationProvider assemblyInformationProvider,
48 IOptions<SecurityConfiguration> securityConfigurationOptions)
49 {
50 ArgumentNullException.ThrowIfNull(cryptographySuite);
51 ArgumentNullException.ThrowIfNull(assemblyInformationProvider);
52
53 securityConfiguration = securityConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(securityConfigurationOptions));
54
55 var signingKeyBytes = String.IsNullOrWhiteSpace(securityConfiguration.CustomTokenSigningKeyBase64)
57 : Convert.FromBase64String(securityConfiguration.CustomTokenSigningKeyBase64);
58
59 ValidationParameters = new TokenValidationParameters
60 {
61 ValidateIssuerSigningKey = true,
62 IssuerSigningKey = new SymmetricSecurityKey(signingKeyBytes),
63
64 ValidateIssuer = true,
65 ValidIssuer = assemblyInformationProvider.AssemblyName.Name,
66
67 ValidateLifetime = true,
68 ValidateAudience = true,
69 ValidAudience = typeof(TokenResponse).Assembly.GetName().Name,
70
71 ClockSkew = TimeSpan.FromMinutes(securityConfiguration.TokenClockSkewMinutes),
72
73 RequireSignedTokens = true,
74
75 RequireExpirationTime = true,
76 };
77
78 tokenHeader = new JwtHeader(
79 new SigningCredentials(
80 ValidationParameters.IssuerSigningKey,
81 SecurityAlgorithms.HmacSha256));
82 tokenHandler = new JwtSecurityTokenHandler();
83 }
84
86 public TokenResponse CreateToken(User user, bool oAuth)
87 {
88 ArgumentNullException.ThrowIfNull(user);
89
90 var uid = user.Require(x => x.Id);
91 var now = DateTimeOffset.UtcNow;
92 var nowUnix = now.ToUnixTimeSeconds();
93
94 // this prevents validation conflicts down the line
95 // tldr we can (theoretically) receive a token the same second after we generate it
96 // since unix time rounds down, it looks like it came from before the user changed their password
97 // this happens occasionally in unit tests
98 // just delay a second so we can force a round up
99 var userLastPassworUpdateUnix = user.LastPasswordUpdate?.ToUnixTimeSeconds();
100 DateTimeOffset notBefore;
101 if (nowUnix == userLastPassworUpdateUnix)
102 notBefore = now.AddSeconds(1);
103 else
104 notBefore = now;
105
106 var expiry = now.AddMinutes(oAuth
109
110 var securityToken = new JwtSecurityToken(
112 new JwtPayload(
113 ValidationParameters.ValidIssuer,
114 ValidationParameters.ValidAudience,
115 Enumerable.Empty<Claim>(),
116 new Dictionary<string, object>
117 {
118 { JwtRegisteredClaimNames.Sub, uid.ToString(CultureInfo.InvariantCulture) },
119 },
120 notBefore.UtcDateTime,
121 expiry.UtcDateTime,
122 now.UtcDateTime));
123
124 var tokenResponse = new TokenResponse
125 {
126 Bearer = tokenHandler.WriteToken(securityToken),
127 };
128
129 return tokenResponse;
130 }
131 }
132}
Represents a JWT returned by the API.
Definition: TokenResponse.cs:9
Configuration options pertaining to user security.
uint TokenSigningKeyByteCount
Amount of bytes to use in the Microsoft.IdentityModel.Tokens.TokenValidationParameters....
string? CustomTokenSigningKeyBase64
A custom token signing key. Overrides TokenSigningKeyByteCount.
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.
DateTimeOffset? LastPasswordUpdate
When PasswordHash was last changed.
Definition: User.cs:54
TokenValidationParameters ValidationParameters
The TokenValidationParameters for the ITokenFactory.
Definition: TokenFactory.cs:22
readonly JwtHeader tokenHeader
The JwtHeader for generating tokens.
Definition: TokenFactory.cs:32
readonly JwtSecurityTokenHandler tokenHandler
The JwtSecurityTokenHandler used to generate TokenResponse.Bearer strings.
Definition: TokenFactory.cs:37
readonly SecurityConfiguration securityConfiguration
The SecurityConfiguration for the TokenFactory.
Definition: TokenFactory.cs:27
TokenFactory(ICryptographySuite cryptographySuite, IAssemblyInformationProvider assemblyInformationProvider, IOptions< SecurityConfiguration > securityConfigurationOptions)
Initializes a new instance of the TokenFactory class.
Definition: TokenFactory.cs:45
TokenResponse CreateToken(User user, bool oAuth)
Definition: TokenFactory.cs:86
Contains various cryptographic functions.
byte[] GetSecureBytes(uint amount)
Generates a secure set of bytes.
AssemblyName AssemblyName
Gets the global::System.Reflection.AssemblyName.