private async Task <bool> TryRevokeTokensAsync([NotNull] AuthenticationTicket ticket) { // Note: if the authorization identifier is null, return true as no tokens need to be revoked. var identifier = ticket.GetInternalAuthorizationId(); if (string.IsNullOrEmpty(identifier)) { return(true); } var result = true; foreach (var token in await _tokenManager.FindByAuthorizationIdAsync(identifier)) { // Don't change the status of the token used in the token request. if (string.Equals(ticket.GetInternalTokenId(), await _tokenManager.GetIdAsync(token), StringComparison.Ordinal)) { continue; } result &= await TryRevokeTokenAsync(token); } return(result); }
private async Task <bool> TryRevokeAuthorizationAsync([NotNull] AuthenticationTicket ticket) { // Note: if the authorization identifier or the authorization itself // cannot be found, return true as the authorization doesn't need // to be revoked if it doesn't exist or is already invalid. var identifier = ticket.GetInternalAuthorizationId(); if (string.IsNullOrEmpty(identifier)) { return(true); } var authorization = await _authorizationManager.FindByIdAsync(identifier); if (authorization == null) { return(true); } try { // Note: the request cancellation token is deliberately not used here to ensure the caller // cannot prevent this operation from being executed by resetting the TCP connection. await _authorizationManager.RevokeAsync(authorization); _logger.LogInformation("The authorization '{Identifier}' was automatically revoked.", identifier); return(true); } catch (OpenIddictExceptions.ConcurrencyException exception) { _logger.LogDebug(exception, "A concurrency exception occurred while trying to revoke the authorization " + "associated with the token '{Identifier}'.", identifier); return(false); } catch (Exception exception) { _logger.LogWarning(exception, "An exception occurred while trying to revoke the authorization " + "associated with the token '{Identifier}'.", identifier); return(false); } }
public static async Task <AuthenticationTicket> CreateAuthenticationTicket( OpenIddictApplicationManager <BTCPayOpenIdClient> applicationManager, OpenIddictAuthorizationManager <BTCPayOpenIdAuthorization> authorizationManager, IdentityOptions identityOptions, SignInManager <ApplicationUser> signInManager, OpenIdConnectRequest request, ApplicationUser user, AuthenticationProperties properties = null) { // Create a new ClaimsPrincipal containing the claims that // will be used to create an id_token, a token or a code. var principal = await signInManager.CreateUserPrincipalAsync(user); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket(principal, properties, OpenIddictServerDefaults.AuthenticationScheme); if (!request.IsAuthorizationCodeGrantType() && !request.IsRefreshTokenGrantType()) { ticket.SetScopes(request.GetScopes()); } else if (request.IsAuthorizationCodeGrantType() && string.IsNullOrEmpty(ticket.GetInternalAuthorizationId())) { var app = await applicationManager.FindByClientIdAsync(request.ClientId); var authorizationId = await IsUserAuthorized(authorizationManager, request, user.Id, app.Id); if (!string.IsNullOrEmpty(authorizationId)) { ticket.SetInternalAuthorizationId(authorizationId); } } foreach (var claim in ticket.Principal.Claims) { claim.SetDestinations(GetDestinations(identityOptions, claim, ticket)); } return(ticket); }
private async Task <string> CreateTokenAsync( [NotNull] string type, [NotNull] AuthenticationTicket ticket, [NotNull] OpenIddictServerOptions options, [NotNull] OpenIdConnectRequest request, [NotNull] ISecureDataFormat <AuthenticationTicket> format) { Debug.Assert(!(options.DisableTokenStorage && options.UseReferenceTokens), "Token storage cannot be disabled when using reference tokens."); Debug.Assert(type == OpenIdConnectConstants.TokenUsages.AccessToken || type == OpenIdConnectConstants.TokenUsages.AuthorizationCode || type == OpenIdConnectConstants.TokenUsages.RefreshToken, "Only authorization codes, access and refresh tokens should be created using this method."); // When sliding expiration is disabled, the expiration date of generated refresh tokens is fixed // and must exactly match the expiration date of the refresh token used in the token request. if (request.IsTokenRequest() && request.IsRefreshTokenGrantType() && !options.UseSlidingExpiration && type == OpenIdConnectConstants.TokenUsages.RefreshToken) { var properties = request.GetProperty <AuthenticationTicket>( OpenIddictConstants.Properties.AuthenticationTicket)?.Properties; Debug.Assert(properties != null, "The authentication properties shouldn't be null."); ticket.Properties.ExpiresUtc = properties.ExpiresUtc; } if (options.DisableTokenStorage) { return(null); } var descriptor = new OpenIddictTokenDescriptor { AuthorizationId = ticket.GetInternalAuthorizationId(), CreationDate = ticket.Properties.IssuedUtc, ExpirationDate = ticket.Properties.ExpiresUtc, Principal = ticket.Principal, Status = OpenIddictConstants.Statuses.Valid, Subject = ticket.Principal.GetClaim(OpenIddictConstants.Claims.Subject), Type = type }; foreach (var property in ticket.Properties.Items) { descriptor.Properties.Add(property); } // When reference tokens are enabled or when the token is an authorization code or a // refresh token, remove the unnecessary properties from the authentication ticket. if (options.UseReferenceTokens || (type == OpenIdConnectConstants.TokenUsages.AuthorizationCode || type == OpenIdConnectConstants.TokenUsages.RefreshToken)) { ticket.Properties.IssuedUtc = ticket.Properties.ExpiresUtc = null; ticket.RemoveProperty(OpenIddictConstants.Properties.InternalAuthorizationId) .RemoveProperty(OpenIddictConstants.Properties.InternalTokenId); } // If reference tokens are enabled, create a new entry for // authorization codes, refresh tokens and access tokens. if (options.UseReferenceTokens) { // Note: the data format is automatically replaced at startup time to ensure // that encrypted tokens stored in the database cannot be considered as // valid tokens if the developer decides to disable reference tokens support. descriptor.Payload = format.Protect(ticket); // Generate a new crypto-secure random identifier that will be // substituted to the ciphertext returned by the data format. var bytes = new byte[256 / 8]; options.RandomNumberGenerator.GetBytes(bytes); // Note: the default token manager automatically obfuscates the // reference identifier so it can be safely stored in the databse. descriptor.ReferenceId = Base64UrlEncoder.Encode(bytes); } // Otherwise, only create a token metadata entry for authorization codes and refresh tokens. else if (type != OpenIdConnectConstants.TokenUsages.AuthorizationCode && type != OpenIdConnectConstants.TokenUsages.RefreshToken) { return(null); } // If the client application is known, associate it with the token. if (!string.IsNullOrEmpty(request.ClientId)) { var application = await _applicationManager.FindByClientIdAsync(request.ClientId); if (application == null) { throw new InvalidOperationException("The application entry cannot be found in the database."); } descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); } // If a null value was returned by CreateAsync(), return immediately. // Note: the request cancellation token is deliberately not used here to ensure the caller // cannot prevent this operation from being executed by resetting the TCP connection. var token = await _tokenManager.CreateAsync(descriptor); if (token == null) { return(null); } // Throw an exception if the token identifier can't be resolved. var identifier = await _tokenManager.GetIdAsync(token); if (string.IsNullOrEmpty(identifier)) { throw new InvalidOperationException("The unique key associated with a refresh token cannot be null or empty."); } // Dynamically set the creation and expiration dates. ticket.Properties.IssuedUtc = descriptor.CreationDate; ticket.Properties.ExpiresUtc = descriptor.ExpirationDate; // Restore the token/authorization identifiers using the identifiers attached with the database entry. ticket.SetInternalAuthorizationId(descriptor.AuthorizationId) .SetInternalTokenId(identifier); if (options.UseReferenceTokens) { _logger.LogTrace("A new reference token was successfully generated and persisted " + "in the database: {Token} ; {Claims} ; {Properties}.", descriptor.ReferenceId, ticket.Principal.Claims, ticket.Properties.Items); return(descriptor.ReferenceId); } return(null); }