4using System.Threading.Tasks;
6using Microsoft.EntityFrameworkCore;
7using Microsoft.Extensions.Logging;
71 AdditionalData = headersException.
Message,
74 ? HttpFailureResponse.NotAcceptable
85 var users = await query
86 .ToListAsync(cancellationToken);
90 .OrderByDescending(dbUser => dbUser.SystemIdentifier ==
null)
112 ILogger<LoginAuthority> logger,
121 authenticationContext,
135 public async ValueTask<AuthorityResponse<LoginResult>>
AttemptLogin(CancellationToken cancellationToken)
141 if (headers.IsTokenAuthentication)
142 return BadRequest<LoginResult>(
ErrorCode.TokenWithToken);
144 var oAuthLogin = headers.OAuthProvider.HasValue;
153 catch (NotImplementedException)
158 using (systemIdentity)
164 var oAuthProvider = headers.OAuthProvider!.Value;
165 var (errorResponse, oauthResult) = await TryOAuthenticate<LoginResult>(headers, oAuthProvider,
true, cancellationToken);
166 if (errorResponse !=
null)
167 return errorResponse;
170 x => x.OAuthConnections!.Any(
171 y => y.Provider == oAuthProvider
172 && y.ExternalUserId == oauthResult!.Value.UserID));
178 return Unauthorized<LoginResult>();
180 if (systemIdentity ==
null)
181 query = query.Where(x => x.CanonicalName == canonicalUserName);
183 query = query.Where(x => x.CanonicalName == canonicalUserName || x.SystemIdentifier == systemIdentity.
Uid);
190 return Unauthorized<LoginResult>();
197 var originalHash = user.PasswordHash;
198 var isLikelyDbUser = originalHash !=
null;
199 var usingSystemIdentity = systemIdentity !=
null && !isLikelyDbUser;
201 if (!usingSystemIdentity)
205 return Unauthorized<LoginResult>();
206 if (user.PasswordHash != originalHash)
208 Logger.LogDebug(
"User ID {userId}'s password hash needs a refresh, updating database.", user.Id);
209 var updatedUser =
new User
214 updatedUser.PasswordHash = user.PasswordHash;
220 var usernameMismatch = systemIdentity!.
Username != user.Name;
221 if (isLikelyDbUser || usernameMismatch)
224 if (usernameMismatch)
227 Logger.LogDebug(
"User ID {userId}'s system identity needs a refresh, updating database.", user.Id);
228 user.Name = systemIdentity.
Username;
235 Logger.LogDebug(
"System user ID {userId}'s PasswordHash is polluted, updating database.", user.Id);
236 user.PasswordHash =
null;
245 if (!user.Enabled!.Value)
247 Logger.LogTrace(
"Not logging in disabled user {userId}.", user.Id);
248 return Forbid<LoginResult>();
258 if (usingSystemIdentity)
261 Logger.LogDebug(
"Successfully logged in user {userId}!", user.Id);
274 var oAuthProvider = headers.OAuthProvider;
275 if (!oAuthProvider.HasValue)
276 return BadRequest<OAuthGatewayLoginResult>(
ErrorCode.BadHeaders);
278 var (errorResponse, oAuthResult) = await TryOAuthenticate<OAuthGatewayLoginResult>(headers, oAuthProvider.Value,
false, cancellationToken);
279 if (errorResponse !=
null)
280 return errorResponse;
282 Logger.LogDebug(
"Generated {provider} OAuth AccessCode", oAuthProvider.Value);
303 identExpiry += TimeSpan.FromSeconds(15);
318 (
string? UserID,
string AccessCode)? oauthResult;
324 if (validator ==
null)
326 oauthResult = await validator
329 Logger.LogTrace(
"External {oAuthProvider} UID: {externalUserId}", oAuthProvider, oauthResult);
331 catch (Octokit.RateLimitExceededException ex)
336 if (!oauthResult.HasValue)
339 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.
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.
LoginAuthority(IAuthenticationContext authenticationContext, IDatabaseContext databaseContext, ILogger< LoginAuthority > logger, IApiHeadersProvider apiHeadersProvider, ISystemIdentityFactory systemIdentityFactory, IOAuthProviders oAuthProviders, ITokenFactory tokenFactory, ICryptographySuite cryptographySuite, IIdentityCache identityCache, ISessionInvalidationTracker sessionInvalidationTracker)
Initializes a new instance of the LoginAuthority class.
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 .
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.
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.
TokenValidationParameters ValidationParameters
The TokenValidationParameters for the ITokenFactory.
string CreateToken(Models.User user, bool oAuth)
Create a TokenResponse for a given user .
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 OAuth providers supported by TGS.
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.