Skip to content

OIDC discovery advertises revocation_endpoint at /oauth2/revoke, but token revocation is routed at /oauth2/token/revoke #1195

Open

Description

@vharseko

Describe the bug

Since #1058, the OpenID Connect discovery document (/oauth2/.well-known/openid-configuration) has advertised revocation_endpoint at <base>/revoke, but the token revocation resource is routed only at <base>/token/revoke. A client that takes the revocation URL from discovery calls an address that has no route, so token revocation fails.

The discovery URL is built in OAuth2UrisFactory:

public String getRevocationEndpoint() {
return baseUrl + "/revoke";
}

public String getRevocationEndpoint() {
    return baseUrl + "/revoke";
}

The only route for TokenRevocationResource is in OAuth2RouterProvider:

router.attach("/token/revoke", auditWithOAuthFilter(wrap(TokenRevocationResource.class)));

router.attach("/token/revoke", auditWithOAuthFilter(wrap(TokenRevocationResource.class)));

Nothing is attached at /revoke. The #1058 description assumed the endpoint already lived at /oauth2/revoke, but the admin guide (chap-oauth2.adoc, "/oauth2/token/revoke") and the developer guide (chap-client-dev.adoc) both document /oauth2/token/revoke, as did ForgeRock AM, and as PingAM still does. The same mismatch applies to subrealms, since both the discovery base URL and the router are realm-relative.

Affected releases: 16.1.2, 16.1.3 and 16.1.4. 16.1.1 does not advertise revocation_endpoint at all.

To Reproduce

  1. Get an access or refresh token for any OAuth 2.0 client.
  2. GET https://openam.example.com:8443/openam/oauth2/.well-known/openid-configuration. The document contains "revocation_endpoint": "https://openam.example.com:8443/openam/oauth2/revoke".
  3. POST the token with the client credentials to that revocation_endpoint URL. No route matches, and the token is not revoked.
  4. POST the same request to https://openam.example.com:8443/openam/oauth2/token/revoke. The token is revoked.

Expected behavior

revocation_endpoint in the discovery document points to the URL that actually revokes tokens: <base>/token/revoke, matching the documentation and PingAM. Clients and libraries that discover endpoints automatically then revoke tokens without extra configuration.

Suggested fix

Return the routed path from OAuth2UrisImpl:

public String getRevocationEndpoint() {
    return baseUrl + "/token/revoke";
}

Then add a test that compares revocation_endpoint (and ideally every other endpoint in the discovery document) with a path that OAuth2RouterProvider attaches. There are no tests for getRevocationEndpoint today. Attaching a second route at /revoke is not needed: the advertised URL has never worked, so no client can depend on it.

Found during the review of OpenIdentityPlatform/OpenIdentityPlatform.org#247, the PingAM 7.5 to OpenAM migration guide. The guide says the main OAuth 2.0 endpoints match PingAM when the context path is kept, and discovery-driven clients break on exactly this difference.

Activity

  1. added
    oauth2OAuth2 / OpenID Connect
    javaPull requests that update java code
    on Oct 22, 2026
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

    bugjavaPull requests that update java codeoauth2OAuth2 / OpenID Connect

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions