Skip to content

Refresh token grant fails with "Bad credentials" after original client secret is deleted during rotation #4086

Description

@deepeshuniyal

Summary

When rotating a UAA client secret (adding a new secret, then deleting the original one), subsequent refresh_token grant calls fail with invalid_client: Bad credentials, even though client_id remains unchanged throughout. refresh_token is bound to the client's identity (client_id), and client authentication should be validated independently at each /oauth/token call using whatever secret is currently valid for that client — the secret rotation itself should not invalidate previously issued refresh tokens. This forces users to be re-authenticated (effectively logged out) after every completed secret rotation, defeating the purpose of zero-downtime rotation.

Environment

  • UAA version: 78.2.0

Steps to Reproduce

  • Generate an access_token and refresh_token via /oauth/token using grant_type=password (or authorization_code), passing client_id and client_secret (Secret A).
  • Add a new secret to the same client: POST /oauth/clients/{client_id}/secret?changeMode=ADD (Secret B)
  • Remove the original secret: POST /oauth/clients/{client_id}/secret?changeMode=DELETE (removing Secret A) (This happens on next secret rotation)
  • Call the token endpoint using the refresh token from step 1, authenticating with the new secret (Secret B): POST /oauth/token grant_type=refresh_token&refresh_token=...&client_id=...&client_secret=

Expected Behavior

Since client_id has not changed and the caller is authenticating with a currently valid secret for that client, the refresh_token grant should succeed and return a new access_token/refresh_token pair.

Actual Behavior

The request fails with:

json
{
"error": "invalid_client",
"error_description": "Bad credentials"
}

This happens even though the client authentication itself (client_id + current secret) is valid — it appears the refresh_token is internally tied to the specific secret value active at the time of issuance, rather than to the client's identity alone.

Related

This is related to #4047, which reports a similar failure during the ADD phase of rotation (before the old secret is deleted). Together these suggest refresh_token validation in UAA may be coupling client authentication to a specific secret value rather than re-validating client identity independently on each call.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions