4using System.Threading.Tasks;
6using Microsoft.EntityFrameworkCore;
7using Microsoft.Extensions.Logging;
8using Microsoft.Extensions.Options;
78 AdditionalData = headersException.
Message,
81 ? HttpFailureResponse.NotAcceptable
92 var users = await query
93 .ToListAsync(cancellationToken);
97 .OrderByDescending(dbUser => dbUser.SystemIdentifier ==
null)
120 ILogger<LoginAuthority> logger,
128 IOptions<SecurityConfiguration> securityConfigurationOptions)
130 authenticationContext,
141 securityConfiguration = securityConfigurationOptions?.Value ??
throw new ArgumentNullException(nameof(securityConfigurationOptions));
145 public async ValueTask<AuthorityResponse<LoginResult>>
AttemptLogin(CancellationToken cancellationToken)
149 return Unauthorized<LoginResult>();
155 if (headers.IsTokenAuthentication)
156 return BadRequest<LoginResult>(
ErrorCode.TokenWithToken);
158 var oAuthLogin = headers.OAuthProvider.HasValue;
167 catch (NotImplementedException)
172 using (systemIdentity)
178 var oAuthProvider = headers.OAuthProvider!.Value;
179 var (errorResponse, oauthResult) = await TryOAuthenticate<LoginResult>(headers, oAuthProvider,
true, cancellationToken);
180 if (errorResponse !=
null)
181 return errorResponse;
184 x => x.OAuthConnections!.Any(
185 y => y.Provider == oAuthProvider
186 && y.ExternalUserId == oauthResult!.Value.UserID));
192 return Unauthorized<LoginResult>();
194 if (systemIdentity ==
null)
195 query = query.Where(x => x.CanonicalName == canonicalUserName);
197 query = query.Where(x => x.CanonicalName == canonicalUserName || x.SystemIdentifier == systemIdentity.
Uid);
204 return Unauthorized<LoginResult>();
211 var originalHash = user.PasswordHash;
212 var isLikelyDbUser = originalHash !=
null;
213 var usingSystemIdentity = systemIdentity !=
null && !isLikelyDbUser;
215 if (!usingSystemIdentity)
219 return Unauthorized<LoginResult>();
220 if (user.PasswordHash != originalHash)
222 Logger.LogDebug(
"User ID {userId}'s password hash needs a refresh, updating database.", user.Id);
223 var updatedUser =
new User
228 updatedUser.PasswordHash = user.PasswordHash;
234 var usernameMismatch = systemIdentity!.
Username != user.Name;
235 if (isLikelyDbUser || usernameMismatch)
238 if (usernameMismatch)
241 Logger.LogDebug(
"User ID {userId}'s system identity needs a refresh, updating database.", user.Id);
242 user.Name = systemIdentity.
Username;
249 Logger.LogDebug(
"System user ID {userId}'s PasswordHash is polluted, updating database.", user.Id);
250 user.PasswordHash =
null;
259 if (!user.Enabled!.Value)
261 Logger.LogTrace(
"Not logging in disabled user {userId}.", user.Id);
262 return Forbid<LoginResult>();
272 if (usingSystemIdentity)
275 Logger.LogDebug(
"Successfully logged in user {userId}!", user.Id);
288 var oAuthProvider = headers.OAuthProvider;
289 if (!oAuthProvider.HasValue)
290 return BadRequest<OAuthGatewayLoginResult>(
ErrorCode.BadHeaders);
292 var (errorResponse, oAuthResult) = await TryOAuthenticate<OAuthGatewayLoginResult>(headers, oAuthProvider.Value,
false, cancellationToken);
293 if (errorResponse !=
null)
294 return errorResponse;
296 Logger.LogDebug(
"Generated {provider} OAuth AccessCode", oAuthProvider.Value);
317 identExpiry += TimeSpan.FromSeconds(15);
332 (
string? UserID,
string AccessCode)? oauthResult;
336#pragma warning disable CS0618
338#pragma warning restore CS0618
344 if (validator ==
null)
346 oauthResult = await validator
349 Logger.LogTrace(
"External {oAuthProvider} UID: {externalUserId}", oAuthProvider, oauthResult);
351 catch (Octokit.RateLimitExceededException ex)
356 if (!oauthResult.HasValue)
359 return (
null, OAuthResult: oauthResult);
virtual ? long Id
The ID of the entity.
Represents an error message returned by the server.
string? Message
A human-readable description of the error.
JsonWebToken ParseJwt()
Parses the Bearer as a JsonWebToken.
Base implementation of IAuthority.
static AuthorityResponse< TResult > Unauthorized< TResult >()
Generates a HttpFailureResponse.Unauthorized type AuthorityResponse<TResult>.
AuthorityResponse< TResult > RateLimit< TResult >(RateLimitExceededException rateLimitException)
Generates a HttpFailureResponse.RateLimited type AuthorityResponse.
ILogger< AuthorityBase > Logger
Gets the ILogger for the AuthorityBase.
static AuthorityResponse< TResult > BadRequest< TResult >(ErrorCode errorCode)
Generates a HttpFailureResponse.BadRequest type AuthorityResponse<TResult>.
Represents a response from an authority.
readonly IApiHeadersProvider apiHeadersProvider
The IApiHeadersProvider for the LoginAuthority.
LoginAuthority(IAuthenticationContext authenticationContext, IDatabaseContext databaseContext, ILogger< LoginAuthority > logger, IApiHeadersProvider apiHeadersProvider, ISystemIdentityFactory systemIdentityFactory, IOAuthProviders oAuthProviders, ITokenFactory tokenFactory, ICryptographySuite cryptographySuite, IIdentityCache identityCache, ISessionInvalidationTracker sessionInvalidationTracker, IOptions< SecurityConfiguration > securityConfigurationOptions)
Initializes a new instance of the LoginAuthority class.
async ValueTask< AuthorityResponse< LoginResult > > AttemptLogin(CancellationToken cancellationToken)
Attempt to login to the server with the current Basic or OAuth credentials.A ValueTask<TResult> resul...
readonly IOAuthProviders oAuthProviders
The IOAuthProviders for the LoginAuthority.
async ValueTask CacheSystemIdentity(ISystemIdentity systemIdentity, User user, LoginResult loginPayload)
Add a given systemIdentity to the identityCache.
readonly IIdentityCache identityCache
The IIdentityCache for the LoginAuthority.
async ValueTask<(AuthorityResponse< TResult >? ErrorResponse,(string? UserID, string AccessCode)? OAuthResult)> TryOAuthenticate< TResult >(ApiHeaders headers, OAuthProvider oAuthProvider, bool forLogin, CancellationToken cancellationToken)
Attempt OAuth authentication.
readonly ISystemIdentityFactory systemIdentityFactory
The ISystemIdentityFactory for the LoginAuthority.
static async ValueTask< User?> SelectUserInfoFromQuery(IQueryable< User > query, CancellationToken cancellationToken)
Select the details needed to generate a TokenResponse from a given query .
readonly SecurityConfiguration securityConfiguration
The SecurityConfiguration for the LoginAuthority.
static AuthorityResponse< TResult > GenerateHeadersExceptionResponse< TResult >(HeadersException headersException)
Generate an AuthorityResponse<TResult> for a given headersException .
async ValueTask< AuthorityResponse< OAuthGatewayLoginResult > > AttemptOAuthGatewayLogin(CancellationToken cancellationToken)
Attempt to login to an OAuth service with the current OAuth credentials.A ValueTask<TResult> resultin...
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the LoginAuthority.
readonly ISessionInvalidationTracker sessionInvalidationTracker
The ISessionInvalidationTracker for the LoginAuthority.
readonly ITokenFactory tokenFactory
The ITokenFactory for the LoginAuthority.
Configuration options pertaining to user security.
bool OidcStrictMode
If OIDC strict mode should be enabled. This mode enforces the existence of at least one OpenIDConnect...
Backend abstract implementation of IDatabaseContext.
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext.A Task representing the running operation.
DbSet< User > Users
The Users in the DatabaseContext.
Success response for a login attempt.
Success result for an OAuth gateway login attempt.
required string AccessCode
The user's access token for the requested OAuth service.
const string TgsSystemUserName
Username used when creating jobs automatically.
static string CanonicalizeName(string name)
Change a UserName.Name into a CanonicalName.
IAuthority for authenticating with the server.
For creating and accessing authentication contexts.
Contains various cryptographic functions.
bool CheckUserPassword(User user, string password)
Checks a given password matches a given user 's User.PasswordHash. This may result in User....
For caching ISystemIdentitys.
ValueTask CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry)
Keep a user 's systemIdentity alive until an expiry time.
Handles invalidating user sessions.
void UserModifiedInvalidateSessions(User user)
Invalidate all sessions for a given user .
Factory for ISystemIdentitys.
Task< ISystemIdentity?> CreateSystemIdentity(User user, CancellationToken cancellationToken)
Create a ISystemIdentity for a given user .
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform.
string Uid
A unique identifier for the user.
string Username
The user's name.
For creating TokenResponses.
string CreateToken(Models.User user, bool serviceLogin)
Create a TokenResponse for a given user .
TokenValidationParameters ValidationParameters
The TokenValidationParameters for the ITokenFactory.
Contains IOAuthValidators.
IOAuthValidator? GetValidator(OAuthProvider oAuthProvider, bool forLogin)
Gets the IOAuthValidator for a given oAuthProvider .
ValueTask<(string? UserID, string AccessCode)?> ValidateResponseCode(string code, bool requireUserID, CancellationToken cancellationToken)
Validate a given OAuth response code .
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.
OAuthProvider
List of OAuth2.0 providers supported by TGS that do not support OIDC.
HeaderErrorTypes
Types of individual ApiHeaders errors.
HttpFailureResponse
Indicates the type of HTTP status code an failing AuthorityResponse should generate.
@ Id
Lookup the Api.Models.EntityId.Id of the Models.PermissionSet.