Exemple #1
0
 /// <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);
        }
Exemple #3
0
 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);
        }
Exemple #5
0
        /// <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);
        }
Exemple #6
0
        /// <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);
        }
Exemple #7
0
    /// <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);
        }
Exemple #10
0
        /// <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);
        }
Exemple #11
0
        // 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));
    }