PingOne Platform APIs

Authorize (Transaction Approval)

GET {{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}

PingOne supports transaction approval when strong authentication is required for elevated security for a high-value transaction, or high-risk resource or service. The sample shows the GET /{{envID}}/as/authorize operation, which includes the response_mode and request parameters in the authorization request.

The response_mode property is the mechanism for returning authorization response parameters from the authorization endpoint. Options are query, fragment, form_post, and pi.flow. The pi.flow option is a Ping Identity custom response mode to specify that the redirect_uri parameter is not required and authorization response parameters are encoded as a JSON object wrapped in a flow response and returned directly to the client with a 200 status. For more information about the query, fragment, and form_post options, refer to the ResponseModes section of the OAuth 2.0 Multiple Response Type Encoding Practices specification. For non-redirect use case information, refer to Redirect and non-redirect authentication flows.

The request property contains request parameters from the application. If the application’s supportUnsignedRequestObject property value is set to false, the JWT must be signed using the HS256 algorithm and the app’s client secret as the key. Using a JWT enables integrity protection of parameters that are required for risk based authentication or privacy and consent use cases.

The request property JWT should be constructed according to the following example:

JWT: "header" :
{
  "alg": "HS256",
  "typ": "JWT"
},
"body" :
{
  "aud": "https://auth.pingone.com/{{envID}}/as",
  "iss": "{{appID}}",
  "pi.template": {
    "name": "{{templateName}}",
    "variant": "{{variantName}}",
    "variables": {
      "key1": "value1"
    }
  },
  "pi.clientContext": {
    "key2": "value2"
  }
}

The request property specifies a JWT that enables OIDC/OAuth2 request parameters to be passed as a single, self-contained parameter. Using a JWT enables integrity protection of parameters that are required for risk-based authentication or privacy and consent use cases. Specifically, (1) passing in the user agent’s original IP address when the PingOne platform is used behind a server side application that is functioning as an authentication gateway or PingFederate, and (2) passing in a purpose or usage description string that could be displayed to the user on the authentication UI prompt, SMS or voice message, push notification, or email message. For details on how to construct the JWT, refer to Create a request property JWT. For information on pi.template refer to Notifications Templates. For information on pi.clientContext refer to Device Authentication.

Query parameters
Property Type Required?

acr_values

String

Optional

client_id

String

Required

code_challenge_method

String

Optional

login_hint

String

Optional

login_hint_token

String

Optional

mobilePayload

String

Optional

max_age

String

Optional

nonce

String

Optional

prompt

String

Optional

redirect_uri

String

Required

request

String

Optional

response_mode

String

Optional

response_type

String

Required

scope

String

Optional

state

String

Optional

Example Request

  • cURL

  • C#

  • Go

  • HTTP

  • Java

  • jQuery

  • NodeJS

  • Python

  • PHP

  • Ruby

  • Swift

curl --location --globoff '{{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}'
var options = new RestClientOptions("{{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Get);
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);
package main

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

func main() {

  url := "{{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}"
  method := "GET"

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

  if err != nil {
    fmt.Println(err)
    return
  }
  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))
}
GET /{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}} HTTP/1.1
Host: {{authPath}}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
  .url("{{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}")
  .method("GET", body)
  .build();
Response response = client.newCall(request).execute();
var settings = {
  "url": "{{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}",
  "method": "GET",
  "timeout": 0,
};

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require('request');
var options = {
  'method': 'GET',
  'url': '{{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}',
  'headers': {
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
import requests

url = "{{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}"

payload = {}
headers = {}

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

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
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/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var request = URLRequest(url: URL(string: "{{authPath}}/{{envID}}/as/authorize?state={{state}}&response_type=token%20id_token&response_mode=pi.flow&scope=openid&request={{requestString}}&client_id={{clientID}}")!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"

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

{
    "_links": {
        "otp.check": {
            "href": "https://auth.pingone.com/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/flows/0392192e-8616-4d70-af9d-10631b3fd2ca"
        },
        "device.select": {
            "href": "https://auth.pingone.com/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/flows/0392192e-8616-4d70-af9d-10631b3fd2ca"
        },
        "self": {
            "href": "https://auth.pingone.com/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/flows/0392192e-8616-4d70-af9d-10631b3fd2ca"
        },
        "signOnPage": {
            "href": "https://apps.pingone.com/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/signon/?flowId=0392192e-8616-4d70-af9d-10631b3fd2ca"
        }
    },
    "_embedded": {
        "devices": [
            {
                "id": "1237625c-12f9-4ab1-8656-351142b6c100",
                "type": "SMS",
                "status": "ACTIVE",
                "phone": "*******01"
            }
        ],
        "application": {
            "name": "WebAppWithMFA_1628117875"
        }
    },
    "id": "0392192e-8616-4d70-af9d-10631b3fd2ca",
    "environment": {
        "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
    },
    "resumeUrl": "https://auth.pingone.com/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/as/resume?flowId=0392192e-8616-4d70-af9d-10631b3fd2ca",
    "status": "OTP_REQUIRED",
    "createdAt": "2021-08-04T23:00:02.383Z",
    "expiresAt": "2021-08-04T23:15:02.666Z",
    "bypassAllowed": false,
    "selectedDevice": {
        "id": "1237625c-12f9-4ab1-8656-351142b6c100"
    }
}