PingOne Platform APIs

Token Introspection (Access Token)

POST {{authPath}}/{{envID}}/as/introspect

The POST /{{envID}}/as/introspect endpoint returns the active state of an OAuth 2.0 token and the claims specified in RFC 7662 Section 2.2. The request requires the token parameter, which is the token string.

The response includes only core oauth claims and any optional claims specified in OAuth 2.0 Token Introspection (RFC7662).

You need to authenticate using the client credentials for the client that was issued the token. If you are introspecting an application, the application’s tokenEndpointAuthMethod property value determines how you authenticate. The tokenEndpointAuthMethod property supports these options: CLIENT_SECRET_BASIC, CLIENT_SECRET_JWT, CLIENT_SECRET_POST, PRIVATE_KEY_JWT, and NONE.

In the sample request shown here, the application’s tokenEndpointAuthMethod value is CLIENT_SECRET_BASIC, which requires the Authorization: Basic HTTP header and a Base64-encoded representation of "username:password" in the request, in which the username is the client_id and the password is the client_secret.

If the application’s tokenEndpointAuthMethod value is CLIENT_SECRET_JWT, the token endpoint uses a JWT signed by the application’s client secret to authenticate the request. For information about creating the JWT and the claims in the JWT, refer to Create a client secret JWT. Token requests that use this auth method require the client_assertion and client_assertion_type OAuth properties to specify the JWT:

curl --location --request POST '{{authPath}}/{{envID}}/as/introspect' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_assertion={{clientSecretJWT}}' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
--data-urlencode 'token={{accessToken}}'

If the application’s tokenEndpointAuthMethod value is PRIVATE_KEY_JWT, the token endpoint uses a JWT signed by an external private key file to authenticate the request. For information about creating the JWT and the claims in the JWT, refer to Create a private key JWT. Token requests that use this auth method require the client_assertion and client_assertion_type OAuth properties to specify the JWT:

curl --location --request POST '{{authPath}}/{{envID}}/as/introspect' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_assertion={{privateKeyJWT}}' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
--data-urlencode 'token={{accessToken}}'

If the application’s tokenEndpointAuthMethod value is CLIENT_SECRET_POST, the request does not need an Authorization header, and the client_id and client_secret property values are submitted in the request body:

curl --location --request POST '{{authPath}}/{{envID}}/as/introspect' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={{appID}}' \
--data-urlencode 'client_secret={{appSecret}}'\
--data-urlencode 'token={{accessToken}}'

If the application’s tokenEndpointAuthMethod value is NONE, the request requires the client_id property value in the request body and does not require an Authorization header:

curl --location --request POST '{{authPath}}/{{envID}}/as/introspect' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={{appID}}' \
--data-urlencode 'token={{accessToken}}'

The response always shows the active attribute, which is a boolean that indicates whether the token is currently active. For active tokens, the response also shows the token_type attribute, and this property always returns a value of Bearer.

For more information about token claims, refer to Token claims.

Related topics

Prerequisites

  • Use the Token endpoint to create an accessToken.

Request Model
Property Type Required?

client_id

String

Optional

client_secret

String

Optional

client_assertion

String

Optional

client_assertion_type

String

Optional

token

String

Required

Refer to the OpenID Connect/OAuth2 data model for full property descriptions.

Headers

Authorization

Content-Type      application/x-www-form-urlencoded

Body

urlencoded ( application/x-www-form-urlencoded )

Key Value

token

{{accessToken}}

Example Request

  • cURL

  • C#

  • Go

  • HTTP

  • Java

  • jQuery

  • NodeJS

  • Python

  • PHP

  • Ruby

  • Swift

curl --location --globoff '{{authPath}}/{{envID}}/as/introspect' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0=' \
--data-urlencode 'token={{accessToken}}'
var options = new RestClientOptions("{{authPath}}/{{envID}}/as/introspect")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Post);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Authorization", "Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0=");
request.AddParameter("token", "{{accessToken}}");
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io"
)

func main() {

  url := "{{authPath}}/{{envID}}/as/introspect"
  method := "POST"

  payload := strings.NewReader("token=%7B%7BaccessToken%7D%7D")

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
  req.Header.Add("Authorization", "Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0=")

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := io.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
POST /{{envID}}/as/introspect HTTP/1.1
Host: {{authPath}}
Content-Type: application/x-www-form-urlencoded
Authorization: Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0=

token=%7B%7BaccessToken%7D%7D
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "token={{accessToken}}");
Request request = new Request.Builder()
  .url("{{authPath}}/{{envID}}/as/introspect")
  .method("POST", body)
  .addHeader("Content-Type", "application/x-www-form-urlencoded")
  .addHeader("Authorization", "Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0=")
  .build();
Response response = client.newCall(request).execute();
var settings = {
  "url": "{{authPath}}/{{envID}}/as/introspect",
  "method": "POST",
  "timeout": 0,
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded",
    "Authorization": "Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0="
  },
  "data": {
    "token": "{{accessToken}}"
  }
};

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require('request');
var options = {
  'method': 'POST',
  'url': '{{authPath}}/{{envID}}/as/introspect',
  'headers': {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0='
  },
  form: {
    'token': '{{accessToken}}'
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
import requests

url = "{{authPath}}/{{envID}}/as/introspect"

payload = 'token=%7B%7BaccessToken%7D%7D'
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Authorization': 'Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0='
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{authPath}}/{{envID}}/as/introspect');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Authorization' => 'Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0='
));
$request->addPostParameter(array(
  'token' => '{{accessToken}}'
));
try {
  $response = $request->send();
  if ($response->getStatus() == 200) {
    echo $response->getBody();
  }
  else {
    echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
    $response->getReasonPhrase();
  }
}
catch(HTTP_Request2_Exception $e) {
  echo 'Error: ' . $e->getMessage();
}
require "uri"
require "net/http"

url = URI("{{authPath}}/{{envID}}/as/introspect")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/x-www-form-urlencoded"
request["Authorization"] = "Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0="
request.body = "token=%7B%7BaccessToken%7D%7D"

response = http.request(request)
puts response.read_body
let parameters = "token=%7B%7BaccessToken%7D%7D"
let postData =  parameters.data(using: .utf8)

var request = URLRequest(url: URL(string: "{{authPath}}/{{envID}}/as/introspect")!,timeoutInterval: Double.infinity)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue("Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0=", forHTTPHeaderField: "Authorization")

request.httpMethod = "POST"
request.httpBody = postData

let task = URLSession.shared.dataTask(with: request) { data, response, error in
  guard let data = data else {
    print(String(describing: error))
    return
  }
  print(String(data: data, encoding: .utf8)!)
}

task.resume()

Example Response

200 OK

{
    "active": true,
    "scope": "openid",
    "client_id": "4bbd0709-1486-4000-8655-746135d877ce",
    "token_type": "Bearer",
    "exp": 1580330483,
    "iat": 1580326883,
    "sub": "b6c0d311-3e7e-4862-a280-a766d2b48a2f",
    "aud": [
        "https://api.pingone.com"
    ],
    "iss": "https://auth.pingone.com/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/as",
    "sid": "a7069f40-3b43-41e6-9703-6fd4621504cf"
}