Unable to get /revoke to work

Hi all,

I’m using okta-react and okta-signin-widget in a classic engine account to build my app. Login works great, but I am having trouble revoking the access token.

calling await this.props.oktaAuth.signOut(); from my component, it generates 2 requests.

  • GET https://<company>.okta.com/oauth2/v1/userinfo successfully returns user info, then
  • POST https://<company>.okta.com/oauth2/v1/revoke fails with 401 {"error":"invalid_client","error_description":"Client authentication failed. Either the client or the client credentials are invalid."}

the POST request looks like this:

curl 'https://<company>.okta.com/oauth2/v1/revoke' \
  -H 'accept: application/json' \
  -H 'authorization: Basic MG9....' \
  -H 'content-type: application/x-www-form-urlencoded' \
  -H 'origin: http://localhost:8080' \
  -H 'referer: http://localhost:8080/' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/ Safari/537.36' \
  -H 'x-okta-user-agent-extended: okta-auth-js/7.2.0 @okta/okta-react/6.7.0' \
  --data-raw 'token_type_hint=access_token&token=eyJra....' \

Reading through posts, i confirmed that my app is setup as a web app (not SPA) on okta console, and tried fiddling with the auth header and body, but the endpoint always returns 401.

Any insight would be much appreciated.
Thanks in advance!


You have a Web app, you said? That means that, in order to make the /token or /revoke requests, it needs to use Client ID/Client Secret as Client Authentication. Our SDKs are designed to be used by SPAs that use PKCE and do not have a Client Secret (Client ID instead is the client authentication used for those calls).

How were you able to get tokens in the first place? Are you just using implicit flow to avoid this?

Thanks for your response!

Confirming that i’m not using PKCE, but i’m not super clear on the various terminologies. Here’s my app setup on admin console:

On the login page, I’m using the okta-signin-widget to login, which i think means i’m using the implicit flow? Do I need to switch to SPA application type for this to work?

    this.widget = new OktaSignIn({
      baseUrl: oktaConfig.baseUrl,
      clientId: oktaConfig.clientId,
      redirectUri: oktaConfig.redirectUri,
      useClassicEngine: true,
      authParams: {
        pkce: false,
        issuer: oktaConfig.baseUrl,
        responseType: ['token', 'id_token'],
        scopes: ['openid', 'offline_access', 'email', 'profile'],
        display: 'page'
      {el: this.wrapper.current},

Once user is logged in I can access the api via the okta-react SDK

import { withOktaAuth } from '@okta/okta-react';

export default withOktaAuth(class LoginButton extends Component<any, any> {

  componentDidMount() {
    const authenticated = await this.props.oktaAuth.isAuthenticated();
    const user = await this.props.oktaAuth.getUser()

  logout = async () => {
    await this.props.oktaAuth.signOut(); // doesn't work!

If you want to use a Web type app with the Widget and where the Widget/front-end application is the one that should be receiving/storing the tokens, then, yes, you can use Implicit flow, as per your config above. However, you will not be able to revoke these tokens as the Widget (or any front end) is unable to safely store and use a Client Secret.

If you wanted to use Authorization Code flow with PKCE (for example, so that you can request and use Refresh Tokens via the offline_access scope), you would need to remake this application as a SPA and set pkce:true and remove the responseType setting (pkce:true handles that for you). With a SPA, there is no Client Secret and the /revoke call made by the Widget should work.

Hi Andrea,

Confirming that following your instruction I’m able to sign out by setting up a new SPA app on Okta console - thanks!

Just so I understand though, are you saying that if I use the widget with pkce= false and a web app, I cannot logout via the widget? In my case it was simple to switch to a SPA flow, but if you don’t have that option, would you just call GET https://${baseUrl}/logout?id_token_hint=${id_token} instead? Trying to wrap my head around the asymmetry of the design =/

Thanks much,


1 Like

If you use an app with a Client Secret and tokens are handled by the widget, you won’t be able to revoke the tokens and you won’t be able to use Authorization Code flow as you won’t be able to successfully authorize those POST requests.

The /logout endpoint will still work to end the Okta session though, as that’s a redirect that only requires the ID Token be sent, no additional client auth. If that works for you, you may want to set revokeAccessToken to false for signOut

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.