PingOne Platform APIs

Step 4: Exchange code for token (POST AUTH)

 

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

The token endpoint is used by the client to obtain an access token by presenting the client’s authorization grant. For authorization_code grants, the application calls the POST {{authPath}}/{{envID}}/as/token endpoint to acquire the access token. The request body must include values for the following properties:

  • grant_type

    A string that specifies the grant type of the token request. In this example, the value is authorization_code.

  • code

    A string that specifies the authorization code value returned by the authorization request.

  • redirect_uri

    A string that specifies the URL that specifies the return entry point of the application.

  • client_id

    A string that specifies the application ID.

  • client_secret

    A string that specifies the application’s secret property.

The application ID and the application secret are set as properties in the request body and authenticate the token request.

The response data contains the access token and the ID token.

Usage summary

This sample demonstrates authentication with credentials in the POST body. Here are the key factors:

Token request

  • Authentication: None in the Authorization tab (set to "No Auth")

  • Request body: Includes client credentials as parameters:

    • grant_type is authorization_code

    • code (authorization code)

    • redirect_uri

    • client_id={{postAuthAppID}} includes credential in request body

    • client_secret={{postAuthAppSecret}} includes credential in request body

Comparison to CLIENT_SECRET_BASIC

  • BASIC: Credentials in header (base64 encoded)

  • POST: Credentials in body (plaintext parameters)

  • Both require HTTPS for security

When to use

  • Systems where manipulating HTTP headers is difficult, or frameworks that work better with form parameters.

Headers

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

Body

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

Key Value

grant_type

authorization_code

code

{{postAuthCode}}

redirect_uri

http://localhost:3000/callback

client_id

{{sharedWebAppID}}

client_secret

{{sharedWebAppSecret}}

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=authorization_code' \
--data-urlencode 'code={{postAuthCode}}' \
--data-urlencode 'redirect_uri=http://localhost:3000/callback' \
--data-urlencode 'client_id={{sharedWebAppID}}' \
--data-urlencode 'client_secret={{sharedWebAppSecret}}'
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", "authorization_code");
request.AddParameter("code", "{{postAuthCode}}");
request.AddParameter("redirect_uri", "http://localhost:3000/callback");
request.AddParameter("client_id", "{{sharedWebAppID}}");
request.AddParameter("client_secret", "{{sharedWebAppSecret}}");
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=authorization_code&code=%7B%7BpostAuthCode%7D%7D&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&client_id=%7B%7BsharedWebAppID%7D%7D&client_secret=%7B%7BsharedWebAppSecret%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")

  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=authorization_code&code=%7B%7BpostAuthCode%7D%7D&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&client_id=%7B%7BsharedWebAppID%7D%7D&client_secret=%7B%7BsharedWebAppSecret%7D%7D
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "grant_type=authorization_code&code={{postAuthCode}}&redirect_uri=http://localhost:3000/callback&client_id={{sharedWebAppID}}&client_secret={{sharedWebAppSecret}}");
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": "authorization_code",
    "code": "{{postAuthCode}}",
    "redirect_uri": "http://localhost:3000/callback",
    "client_id": "{{sharedWebAppID}}",
    "client_secret": "{{sharedWebAppSecret}}"
  }
};

$.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': 'authorization_code',
    'code': '{{postAuthCode}}',
    'redirect_uri': 'http://localhost:3000/callback',
    'client_id': '{{sharedWebAppID}}',
    'client_secret': '{{sharedWebAppSecret}}'
  }
};
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=authorization_code&code=%7B%7BpostAuthCode%7D%7D&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&client_id=%7B%7BsharedWebAppID%7D%7D&client_secret=%7B%7BsharedWebAppSecret%7D%7D'
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' => 'authorization_code',
  'code' => '{{postAuthCode}}',
  'redirect_uri' => 'http://localhost:3000/callback',
  'client_id' => '{{sharedWebAppID}}',
  'client_secret' => '{{sharedWebAppSecret}}'
));
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=authorization_code&code=%7B%7BpostAuthCode%7D%7D&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&client_id=%7B%7BsharedWebAppID%7D%7D&client_secret=%7B%7BsharedWebAppSecret%7D%7D"

response = http.request(request)
puts response.read_body
let parameters = "grant_type=authorization_code&code=%7B%7BpostAuthCode%7D%7D&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&client_id=%7B%7BsharedWebAppID%7D%7D&client_secret=%7B%7BsharedWebAppSecret%7D%7D"
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()

Example Response

200 OK

{
    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImRlZmF1bHQifQ",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "openid",
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImRlZmF1bHQifQ"
}