Introspection endpoint does not work with service integration token

I’m working on creating a service API integration using private key and would like to use the introspection endpoint to check that the generated token is valid. When I call it I get an invalid client error:

	"error": "invalid_client",
	"error_description": "Client authentication failed. Either the client or the client credentials are invalid."

This is how I generate the token:

curl --location --request POST 'https://{oktaDomain}/oauth2/v1/token'\
--header 'Accept: application/json'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'grant_type=client_credentials'
--data-urlencode ''
--data-urlencode 'client_id={clientId}'
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
--data-urlencode 'client_assertion={signedAssertion}'

This is how I’m calling the introspect endpoint

curl --location --request POST 'https://{oktaDomain}/oauth2/v1/introspect'\
--header 'Accept: application/json'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'token={token}'
--data-urlencode 'token_type_hint=access_token'
--data-urlencode 'client_id={clientId}'

If I try to get user data using the same token it works, so the token is valid:

curl -X GET "https://{oktaDomain}/api/v1/users"
-H "Accept: application/json"
-H "Content-Type: application/json"
-H "Authorization: Bearer {token}"

Introspect endpoint needs authentication based on the client settings. If you are using a SPA client, you can send the request with client id in query string parameter as mentioned in our docs.

Typically resources servers use client_id/client_secret which can be sent as basic auth header which could be set up as a web application OIDC app in Okta.

For complete reference, here are the different authentication types which can be used.

I tried adding the client_id as a query parameter and I’m getting the same result. Is there any way to find out more information about why the request failed? I don’t see the introspect request in the System Logs, just the token generation.

As the error indicates, your application in Okta is not having token_endpoint_auth_methods_supported: ['none'] which means you did not create your app as Single Page Application(SPA) or Native App.

Two ways to check this,

  • Application page in Okta admin console will have Client authentication field which will tell you what your application supports.
  • Alternatively use https://{oktaDomain}/.well-known/openid-configuration?client_id={clientId} to find out what is listed under token_endpoint_auth_methods_supported property.

Once you determine this make sure you use the correct auth method to send introspection request.

1 Like

The integration I am using is an API Services integration set up with Public key / Private key client authentication. We have other integrations as well. But I’m trying to get this one to work, and we use the introspection endpoint to verify that the generated token is valid. Unfortunately, this does not work for this integration and there is no indication to why this is.

Here’s what I get for supported auth methods from the API:

"token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post", "client_secret_jwt", "private_key_jwt", "none"]

I gather that private_key_jwt is the authentication method that I’m using. The question is, why isn’t it working?

If your application in Okta is configured to require Private Kwy JWT auth, then you will need to include the same sort of client assertion to any other OAuth endpoint that require client auth, including Introspect.

Does the call work if you include a JWT as client_assertion within the body?

@andrea it worked, but I had to add both client_assertion and client_assertion_type in order for it to work. Thank you very much.

Is this documented anywhere?

Also, I’m a bit confused with regards to how this is supposed to work. We’re using the /introspect endpoint to validate that the token we receive with each request. If we need to add a new self signed JWT token with each request, as well as the one we got from the /token endpoint, what is the point of doing all this? I mean it’s easier to just validate our self signed tokens at this point. What I missing?

Why do you need to validate these tokens yourself?

The API Services application while using the Org Authorization Server is designed to support getting tokens that can be used against Okta’s APIs, not your own endpoints. Okta’s endpoints will be the ones that validate the token when the Access Token received is used as bearer auth.

If you are validating tokens as they are being used to protect a resource of yours, you could look to use a custom authorization server instead. When using a custom authorization server, you are not limited to using the Public key / Private key Client authentication and could instead use Client ID / Client Secret auth to both request tokens and to introspect them.

Mind you, you would not be able to use/receive Okta API scopes (, etc) when requesting tokens from a custom server, you would instead be making your own custom scopes related to your resources.

I am looking to protect our own resources that are accessed by both users and 3rd party services (machine to machine). For user access we use OIDC integrations, but for the machine to machine access we thought we could use the API Service integration. I just noticed in the Okta admin dashboard that it says “Interact with Okta APIs” in the description of the API Service integration, so I guess I was just using it wrong.

Thank you for the clarification.

1 Like

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