PingOne Platform APIs

Token (refresh_token) (CLIENT_SECRET_JWT)

POST {{authPath}}/{{envID}}/as/token

The token endpoint can be used by the client to obtain an access token by exchanging its refresh token. Note that authentication requirements to this endpoint are configured by the application’s tokenEndpointAuthMethod property. For refresh_token grants, the application calls the POST /{{envID}}/as/token endpoint to exchange the refresh token for an access token.

For a refresh_token grant type in which the application’s tokenEndpointAuthMethod is set to 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.

To obtain a refresh token along with an access token, the application must be either:

  • Configured with the refresh_token grant type and the authorization_code grant type.

  • Configured with the authorization_code grant type, and include offline_access in the scope parameter.

A refresh token is then generated along with the access token. When obtaining the original access token, a refresh token is included in the response, which is tied to the client and the user session. As long as the session exists and it is not expired (30 days since the last sign on), the /{{envID}}/as/token endpoint can be used to exchange the refresh token for a new access token and refresh token. If the openid scope is granted, an ID token is also included.

When a new refresh token is issued, the previous refresh token is rotated to prevent token abuse, which is useful when client authentication is disabled. In addition, when a refresh token is exchanged, the activeAt property of the corresponding session is updated. This does not extend the duration of the session, but can be used to indicate that there is activity.

To revoke a refresh token, the corresponding session must be deleted. Session termination is supported only by the resource owner using the /{{envID}}/as/signoff endpoint or by disabling the user.

For more information about access token claims, refer to Access token claims.

Request Model
Property Type Required?

client_id

String

Required

client_secret

String

Required

refresh_token

String

Optional

grant_type

String

Optional

client_assertion

String

Required

client_assertion_type

String

Required

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

Headers

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

Body

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

Key Value

grant_type

refresh_token

refresh_token

{{refreshToken}}

client_assertion

{{clientSecretJWT}}

client_assertion_type

urn:ietf:params:oauth:client-assertion-type:jwt-bearer

Example Request

  • cURL

  • C#

  • Go

  • HTTP

  • Java

  • jQuery

  • NodeJS

  • Python

  • PHP

  • Ruby

  • Swift

curl --location --globoff '{{authPath}}/{{envID}}/as/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token={{refreshToken}}' \
--data-urlencode 'client_assertion={{clientSecretJWT}}' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
var options = new RestClientOptions("{{authPath}}/{{envID}}/as/token")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Post);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "refresh_token");
request.AddParameter("refresh_token", "{{refreshToken}}");
request.AddParameter("client_assertion", "{{clientSecretJWT}}");
request.AddParameter("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);
package main

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

func main() {

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

  payload := strings.NewReader("grant_type=refresh_token&refresh_token=%7B%7BrefreshToken%7D%7D&client_assertion=%7B%7BclientSecretJWT%7D%7D&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer")

  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")

  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/token HTTP/1.1
Host: {{authPath}}
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=%7B%7BrefreshToken%7D%7D&client_assertion=%7B%7BclientSecretJWT%7D%7D&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "grant_type=refresh_token&refresh_token={{refreshToken}}&client_assertion={{clientSecretJWT}}&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
Request request = new Request.Builder()
  .url("{{authPath}}/{{envID}}/as/token")
  .method("POST", body)
  .addHeader("Content-Type", "application/x-www-form-urlencoded")
  .build();
Response response = client.newCall(request).execute();
var settings = {
  "url": "{{authPath}}/{{envID}}/as/token",
  "method": "POST",
  "timeout": 0,
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  "data": {
    "grant_type": "refresh_token",
    "refresh_token": "{{refreshToken}}",
    "client_assertion": "{{clientSecretJWT}}",
    "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
  }
};

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require('request');
var options = {
  'method': 'POST',
  'url': '{{authPath}}/{{envID}}/as/token',
  'headers': {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  form: {
    'grant_type': 'refresh_token',
    'refresh_token': '{{refreshToken}}',
    'client_assertion': '{{clientSecretJWT}}',
    'client_assertion_type': 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
import requests

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

payload = 'grant_type=refresh_token&refresh_token=%7B%7BrefreshToken%7D%7D&client_assertion=%7B%7BclientSecretJWT%7D%7D&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer'
headers = {
  'Content-Type': 'application/x-www-form-urlencoded'
}

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/token');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/x-www-form-urlencoded'
));
$request->addPostParameter(array(
  'grant_type' => 'refresh_token',
  'refresh_token' => '{{refreshToken}}',
  'client_assertion' => '{{clientSecretJWT}}',
  'client_assertion_type' => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
));
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/token")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/x-www-form-urlencoded"
request.body = "grant_type=refresh_token&refresh_token=%7B%7BrefreshToken%7D%7D&client_assertion=%7B%7BclientSecretJWT%7D%7D&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer"

response = http.request(request)
puts response.read_body
let parameters = "grant_type=refresh_token&refresh_token=%7B%7BrefreshToken%7D%7D&client_assertion=%7B%7BclientSecretJWT%7D%7D&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer"
let postData =  parameters.data(using: .utf8)

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

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()