/// <summary> /// Creates the revocation endpoint response and processes the revocation request. /// </summary> /// <param name="validationResult">The userinfo request validation result.</param> /// <returns></returns> public virtual async Task <TokenRevocationResponse> ProcessAsync(TokenRevocationRequestValidationResult validationResult) { if (validationResult.TokenTypeHint == Constants.TokenTypeHints.Subject) { var response = new TokenRevocationResponse { Success = false, TokenType = validationResult.TokenTypeHint }; var client = validationResult.Client as ClientExtra; if (client.AllowGlobalSubjectRevocation) { Logger.LogInformation($"TokenRevocation: client={client.ClientId},subject={validationResult.Token}"); response.Success = await RevokeSubjectAsync(validationResult); } else { Logger.LogError($"client={client.ClientId},AllowGlobalSubjectRevocation={client.AllowGlobalSubjectRevocation}"); } return(response); } else { return(await _idsTokenRevocationResponseGenerator.ProcessAsync(validationResult)); } }
/// <summary> /// Revoke refresh token only if it belongs to client doing the request /// </summary> protected virtual async Task <bool> RevokeRefreshTokenAsync(TokenRevocationRequestValidationResult validationResult) { var token = await RefreshTokenStore.GetRefreshTokenAsync(validationResult.Token); if (token != null) { if (token.ClientId == validationResult.Client.ClientId) { Logger.LogDebug("Refresh token revoked"); var rt = await RefreshTokenStore.GetRefreshTokenAsync(validationResult.Token); var rts = RefreshTokenStore as IRefreshTokenStore2; await RefreshTokenStore.RemoveRefreshTokenAsync(validationResult.Token); await rts.RemoveRefreshTokensAsync(token.SubjectId, token.ClientId); await ReferenceTokenStore.RemoveReferenceTokensAsync(token.SubjectId, token.ClientId); var clientExtra = validationResult.Client as ClientExtra; await _tokenRevocationEventHandler.TokenRevokedAsync(clientExtra, token.SubjectId); } else { Logger.LogWarning("Client {clientId} tried to revoke a refresh token belonging to a different client: {clientId}", validationResult.Client.ClientId, token.ClientId); } return(true); } return(false); }
public TokenRevokedSuccessEvent(TokenRevocationRequestValidationResult requestResult, Client client) : base(EventCategories.Token, "Token Revoked Success", EventTypes.Success, EventIds.TokenRevokedSuccess) { ClientId = client.ClientId; ClientName = client.ClientName; TokenType = requestResult.TokenTypeHint; Token = ObfuscateToken(requestResult.Token); }
/// <summary> /// Revoke access token only if it belongs to client doing the request. /// </summary> protected virtual async Task <bool> RevokeAccessTokenAsync(TokenRevocationRequestValidationResult validationResult) { try { var token = await ReferenceTokenStore.GetReferenceTokenAsync(validationResult.Token); string subject; if (token != null) { subject = token.SubjectId; if (token.ClientId == validationResult.Client.ClientId) { Logger.LogDebug("Access token revoked"); await ReferenceTokenStore.RemoveReferenceTokenAsync(validationResult.Token); } else { Logger.LogWarning("Client {clientId} tried to revoke an access token belonging to a different client: {clientId}", validationResult.Client.ClientId, token.ClientId); } } else { var validateAccessToken = await _tokenValidator.ValidateAccessTokenAsync(validationResult.Token); if (validateAccessToken.IsError) { Logger.LogWarning("Client {clientId} access_token not valid: {clientId}", validationResult.Client.ClientId, token.ClientId); return(false); } var queryClaims = from item in validateAccessToken.Claims where item.Type == JwtClaimTypes.Subject select item.Value; subject = queryClaims.FirstOrDefault(); } // now we need to revoke this subject var rts = RefreshTokenStore as IRefreshTokenStore2; await rts.RemoveRefreshTokensAsync(subject, validationResult.Client.ClientId); var clientExtra = validationResult.Client as ClientExtra; await _tokenRevocationEventHandler.TokenRevokedAsync(clientExtra, subject); return(true); } catch (Exception e) { Logger.LogError(e, "unexpected error in revocation"); } return(false); }
/// <summary> /// Revoke Every token associated with this subject. /// </summary> protected virtual async Task <bool> RevokeSubjectAsync(TokenRevocationRequestValidationResult validationResult) { try { DeferRemoveSubjectTokensAsync(validationResult.Token); return(true); } catch (Exception ex) { Logger.LogError(ex.Message); } return(false); }
/// <summary> /// Creates the revocation endpoint response and processes the revocation request. /// </summary> /// <param name="validationResult">The userinfo request validation result.</param> /// <returns></returns> public virtual async Task <TokenRevocationResponse> ProcessAsync(TokenRevocationRequestValidationResult validationResult) { var response = new TokenRevocationResponse { Success = false, TokenType = validationResult.TokenTypeHint }; // revoke tokens if (validationResult.TokenTypeHint == TokenTypeHints.AccessToken) { Logger.LogTrace("Hint was for access token"); response.Success = await RevokeAccessTokenAsync(validationResult); } else if (validationResult.TokenTypeHint == TokenTypeHints.RefreshToken) { Logger.LogTrace("Hint was for refresh token"); response.Success = await RevokeRefreshTokenAsync(validationResult); } else if (validationResult.TokenTypeHint == IdentityServer4Extras.Constants.TokenTypeHints.Subject) { Logger.LogTrace("Hint was for subject"); response.Success = await RevokeSubjectAsync(validationResult); } else { Logger.LogTrace("No hint for token type"); response.Success = await RevokeAccessTokenAsync(validationResult); if (!response.Success) { response.Success = await RevokeRefreshTokenAsync(validationResult); response.TokenType = TokenTypeHints.RefreshToken; } else { response.TokenType = TokenTypeHints.AccessToken; } } return(response); }
/// <summary> /// Creates the revocation endpoint response and processes the revocation request. /// </summary> /// <param name="validationResult">The userinfo request validation result.</param> /// <returns></returns> public virtual async Task <TokenRevocationResponse> ProcessAsync(TokenRevocationRequestValidationResult validationResult) { using var activity = Tracing.BasicActivitySource.StartActivity("TokenRevocationResponseGenerator.Process"); var response = new TokenRevocationResponse { Success = false, TokenType = validationResult.TokenTypeHint }; // revoke tokens if (validationResult.TokenTypeHint == Constants.TokenTypeHints.AccessToken) { Logger.LogTrace("Hint was for access token"); response.Success = await RevokeAccessTokenAsync(validationResult); } else if (validationResult.TokenTypeHint == Constants.TokenTypeHints.RefreshToken) { Logger.LogTrace("Hint was for refresh token"); response.Success = await RevokeRefreshTokenAsync(validationResult); } else { Logger.LogTrace("No hint for token type"); response.Success = await RevokeAccessTokenAsync(validationResult); if (!response.Success) { response.Success = await RevokeRefreshTokenAsync(validationResult); response.TokenType = Constants.TokenTypeHints.RefreshToken; } else { response.TokenType = Constants.TokenTypeHints.AccessToken; } } return(response); }
/// <summary> /// Revoke refresh token only if it belongs to client doing the request /// </summary> protected virtual async Task <bool> RevokeRefreshTokenAsync(TokenRevocationRequestValidationResult validationResult) { var token = await RefreshTokenStore.GetRefreshTokenAsync(validationResult.Token); if (token != null) { if (token.ClientId == validationResult.Client.ClientId) { var validationResultExtra = validationResult as TokenRevocationRequestValidationResultExtra; var clientExtra = validationResult.Client as ClientExtra; Logger.LogDebug("Refresh token revoked"); var refreshTokenStore2 = RefreshTokenStore as IRefreshTokenStore2; await RefreshTokenStore.RemoveRefreshTokenAsync(validationResult.Token); if (validationResultExtra.RevokeAllAssociatedSubjects) { var clientExtras = await _clientStoreExtra.GetAllClientsAsync(); var queryClientIds = from item in clientExtras where item.Namespace == clientExtra.Namespace select item.ClientId; foreach (var clientId in queryClientIds) { await ReferenceTokenStore.RemoveReferenceTokensAsync(token.SubjectId, clientId); await refreshTokenStore2.RemoveRefreshTokensAsync(token.SubjectId, clientId); } } await _tokenRevocationEventHandler.TokenRevokedAsync(clientExtra, token.SubjectId); } else { Logger.LogWarning("Client {clientId} tried to revoke a refresh token belonging to a different client: {clientId}", validationResult.Client.ClientId, token.ClientId); } return(true); } return(false); }
/// <summary> /// Revoke access token only if it belongs to client doing the request. /// </summary> protected virtual async Task <bool> RevokeAccessTokenAsync(TokenRevocationRequestValidationResult validationResult) { var token = await ReferenceTokenStore.GetReferenceTokenAsync(validationResult.Token); if (token != null) { if (token.ClientId == validationResult.Client.ClientId) { Logger.LogDebug("Access token revoked"); await ReferenceTokenStore.RemoveReferenceTokenAsync(validationResult.Token); } else { Logger.LogWarning("Client {clientId} tried to revoke an access token belonging to a different client: {clientId}", validationResult.Client.ClientId, token.ClientId); } return(true); } return(false); }
/// <summary> /// Revoke access token only if it belongs to client doing the request. /// </summary> protected virtual async Task <bool> RevokeSubjectAsync(TokenRevocationRequestValidationResult validationResult) { try { // Token is the subject in this case string subject = validationResult.Token; if (!string.IsNullOrEmpty(subject)) { var validationResultExtra = validationResult as TokenRevocationRequestValidationResultExtra; var clientExtra = validationResult.Client as ClientExtra; // now we need to revoke this subject var rts = RefreshTokenStore as IRefreshTokenStore2; if (validationResultExtra.RevokeAllAssociatedSubjects) { var clientExtras = await _clientStoreExtra.GetAllClientsAsync(); var queryClientIds = from item in clientExtras where item.Namespace == clientExtra.Namespace select item.ClientId; foreach (var clienId in queryClientIds) { await rts.RemoveRefreshTokensAsync(subject, clienId); } } else { await rts.RemoveRefreshTokensAsync(subject, clientExtra.ClientId); } await _tokenRevocationEventHandler.TokenRevokedAsync(clientExtra, subject); } return(true); } catch (Exception e) { Logger.LogError(e, "unexpected error in revocation"); } return(false); }
// revoke refresh token only if it belongs to client doing the request private async Task <bool> RevokeRefreshTokenAsync(TokenRevocationRequestValidationResult validationResult) { var token = await RefreshTokenStore.GetRefreshTokenAsync(validationResult.Token); if (token != null) { if (token.ClientId == validationResult.Client.ClientId) { Logger.LogDebug("Refresh token revoked"); await RefreshTokenStore.RemoveRefreshTokensAsync(token.SubjectId, token.ClientId); await ReferenceTokenStore.RemoveReferenceTokensAsync(token.SubjectId, token.ClientId); } else { Logger.LogWarning("Client {clientId} tried to revoke a refresh token belonging to a different client: {clientId}", validationResult.Client.ClientId, token.ClientId); } return(true); } return(false); }
/// <summary> /// Revoke refresh token only if it belongs to client doing the request /// </summary> protected virtual async Task <bool> RevokeRefreshTokenAsync(TokenRevocationRequestValidationResult validationResult) { var token = await RefreshTokenStore.GetRefreshTokenAsync(validationResult.Token); if (token != null) { if (token.ClientId == validationResult.Client.ClientId) { Logger.LogDebug("Refresh token revoked"); await RefreshTokenStore.RemoveRefreshTokenAsync(validationResult.Token); await ReferenceTokenStore.RemoveReferenceTokensAsync(token.SubjectId, token.ClientId); } else { Logger.LogWarning("Client {clientId} denied from revoking a refresh token belonging to Client {tokenClientId}", validationResult.Client.ClientId, token.ClientId); } return(true); } return(false); }
/// <summary> /// Validates the request. /// </summary> /// <param name="parameters">The parameters.</param> /// <param name="client">The client.</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException"> /// parameters /// or /// client /// </exception> public Task <TokenRevocationRequestValidationResult> ValidateRequestAsync(NameValueCollection parameters, Client client) { using var activity = Tracing.BasicActivitySource.StartActivity("TokenRevocationRequestValidator.ValidateRequest"); _logger.LogTrace("ValidateRequestAsync called"); if (parameters == null) { _logger.LogError("no parameters passed"); throw new ArgumentNullException(nameof(parameters)); } if (client == null) { _logger.LogError("no client passed"); throw new ArgumentNullException(nameof(client)); } //////////////////////////// // make sure token is present /////////////////////////// var token = parameters.Get("token"); if (token.IsMissing()) { _logger.LogError("No token found in request"); return(Task.FromResult(new TokenRevocationRequestValidationResult { IsError = true, Error = OidcConstants.TokenErrors.InvalidRequest })); } var result = new TokenRevocationRequestValidationResult { IsError = false, Token = token, Client = client }; //////////////////////////// // check token type hint /////////////////////////// var hint = parameters.Get("token_type_hint"); if (hint.IsPresent()) { if (Constants.SupportedTokenTypeHints.Contains(hint)) { _logger.LogDebug("Token type hint found in request: {tokenTypeHint}", hint); result.TokenTypeHint = hint; } else { _logger.LogError("Invalid token type hint: {tokenTypeHint}", hint); result.IsError = true; result.Error = Constants.RevocationErrors.UnsupportedTokenType; } } _logger.LogDebug("ValidateRequestAsync result: {validateRequestResult}", result); return(Task.FromResult(result)); }