78 IOptions<SwarmConfiguration> swarmConfigurationOptions,
79 ILogger<AuthenticationContextFactory>
logger)
83 ArgumentNullException.ThrowIfNull(apiHeadersProvider);
86 swarmConfiguration = swarmConfigurationOptions?.Value ??
throw new ArgumentNullException(nameof(swarmConfigurationOptions));
87 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
97 public async Task
ValidateToken(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken)
98 #pragma warning restore CA1506
100 ArgumentNullException.ThrowIfNull(tokenValidatedContext);
102 if (tokenValidatedContext.SecurityToken is not JsonWebToken jwt)
103 throw new ArgumentException($
"Expected {nameof(tokenValidatedContext)} to contain a {nameof(JsonWebToken)}!", nameof(tokenValidatedContext));
106 throw new InvalidOperationException(
"Authentication context has already been loaded");
108 var principal =
new ClaimsPrincipal(
new ClaimsIdentity(jwt.Claims));
110 var userIdClaim = principal.FindFirst(JwtRegisteredClaimNames.Sub);
111 if (userIdClaim ==
default)
112 throw new InvalidOperationException($
"Missing '{JwtRegisteredClaimNames.Sub}' claim!");
117 userId = Int64.Parse(userIdClaim.Value, CultureInfo.InvariantCulture);
121 throw new InvalidOperationException(
"Failed to parse user ID!", e);
124 DateTimeOffset ParseTime(
string key)
126 var claim = principal.FindFirst(key);
127 if (claim ==
default)
128 throw new InvalidOperationException($
"Missing '{key}' claim!");
132 return new DateTimeOffset(
134 Int64.Parse(claim.Value, CultureInfo.InvariantCulture)));
138 throw new InvalidOperationException($
"Failed to parse '{key}'!", ex);
142 var notBefore = ParseTime(JwtRegisteredClaimNames.Nbf);
143 var expires = ParseTime(JwtRegisteredClaimNames.Exp);
148 .Where(x => x.Id == userId)
149 .Include(x => x.CreatedBy)
150 .Include(x => x.PermissionSet)
151 .Include(x => x.Group)
153 .Include(x => x.OAuthConnections)
154 .FirstOrDefaultAsync(cancellationToken);
157 tokenValidatedContext.Fail($
"Unable to find user with ID {userId}!");
162 if (user.SystemIdentifier !=
null)
166 if (user.LastPasswordUpdate.HasValue && user.LastPasswordUpdate >= notBefore)
168 tokenValidatedContext.Fail($
"Rejecting token for user {userId} created before last modification: {user.LastPasswordUpdate.Value}");
172 systemIdentity =
null;
175 var userPermissionSet = user.PermissionSet ?? user.Group!.PermissionSet;
180 if (instanceId.HasValue)
182 instancePermissionSet = await databaseContext.InstancePermissionSets
184 .Where(x => x.PermissionSetId == userPermissionSet!.Id && x.InstanceId == instanceId && x.Instance!.SwarmIdentifer ==
swarmConfiguration.
Identifier)
185 .Include(x => x.Instance)
186 .FirstOrDefaultAsync(cancellationToken);
188 if (instancePermissionSet ==
null)
189 logger.LogDebug(
"User {userId} does not have permissions on instance {instanceId}!", userId, instanceId.Value);
195 jwt.EncodedSignature,
196 instancePermissionSet,
201 systemIdentity?.Dispose();