Token Introspection (Resource ID and Secret)
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). The |
For introspection as the resource server, use the custom resource’s ID and secret (or a JWT) according to the resource’s introspectEndpointAuthMethod value. The introspectEndpointAuthMethod property supports these options to authenticate the request: CLIENT_SECRET_BASIC, CLIENT_SECRET_POST, CLIENT_SECRET_JWT, PRIVATE_KEY_JWT, and NONE.
In the sample request shown here, the resource’s introspectEndpointAuthMethod 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 (the client_id) is the {{resourceID}} for the custom resource and the password (the client_secret) is the {{resourceSecret}} associated with the custom resource.
If the resource’s introspectEndpointAuthMethod value is CLIENT_SECRET_POST, the request does not need an Authorization header, and the client_id and client_secret property values are the {{resourceID}} and {{resourceSecret}}, respectively, and these properties 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={{resourceID}}' \
--data-urlencode 'client_secret={{resourceSecret}}'\
--data-urlencode 'token={{accessToken}}'
If the resource’s introspectEndpointAuthMethod value is NONE, the request requires the client_id property in the request body, and this property value is the {{resourceID}}. This request 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={{resourceID}}' \
--data-urlencode 'token={{accessToken}}'
If the resource’s introspectEndpointAuthMethod 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 resource’s introspectEndpointAuthMethod 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}}'
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
-
Refer to OpenID Connect/OAuth 2 and Token for important overview information.
Request Model
| Property | Type | Required? |
|---|---|---|
|
String |
Required |
|
String |
Required |
|
String |
Required |
Refer to the OpenID Connect/OAuth2 data model for full property descriptions.
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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19' \
--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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19");
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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19")
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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19
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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19")
.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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19"
},
"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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19'
},
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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19'
}
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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19'
));
$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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19"
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 e3tyZXNvdXJjZUlEfX06e3tyZXNvdXJjZVNlY3JldH19", 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": "CustomScope_1666376234",
"client_id": "9bd74a2e-4ecd-44cd-abe7-62b288a9a8c9",
"token_type": "Bearer",
"exp": 1666383500,
"iat": 1666376300,
"sub": "13e04105-df5f-47e7-ada7-62af8701bad8",
"aud": [
"https://api.custom-resource.com"
],
"iss": "https://auth.pingone.com/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/as",
"sid": "3aa55365-7677-4a14-90d5-b34f5297618d"
}