PingOne Platform APIs

Step 1: Create a custom application

 

POST {{apiPath}}/environments/{{envID}}/applications

You can use the POST {{apiPath}}/environments/{{envID}}/applications endpoint to create the new application.

The app config must specify the DEVICE_CODE value on the grantTypes property (and optionally the REFRESH_TOKEN value). Applications configured with the device code grant type use the /{{envID}}/as/device_authorization endpoint to initiate authorization.

The deviceTimeout and devicePollingInterval OIDC properties are required when DEVICE_CODE is specified on the grantTypes property.

The response data returns information about the new application, including its id property, which identifies the UUID for this application resource. You will need the application’s UUID property value in Step 5 to send the authorization request and in Step 11 for the token request.

Headers

Authorization      Bearer {{accessToken}}

Content-Type      application/json

Body

raw ( application/json )

{
    "enabled": true,
    "name": "Device-App{{$timestamp}}",
    "description": "App for Device Auth Grant",
    "type": "CUSTOM_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
        "DEVICE_CODE",
        "REFRESH_TOKEN"
    ],
    "deviceTimeout": 600,
    "devicePollingInterval": 5,
    "tokenEndpointAuthMethod": "NONE"
}

Example Request

  • cURL

  • C#

  • Go

  • HTTP

  • Java

  • jQuery

  • NodeJS

  • Python

  • PHP

  • Ruby

  • Swift

curl --location --globoff '{{apiPath}}/environments/{{envID}}/applications' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{accessToken}}' \
--data '{
    "enabled": true,
    "name": "Device-App{{$timestamp}}",
    "description": "App for Device Auth Grant",
    "type": "CUSTOM_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
        "DEVICE_CODE",
        "REFRESH_TOKEN"
    ],
    "deviceTimeout": 600,
    "devicePollingInterval": 5,
    "tokenEndpointAuthMethod": "NONE"
}'
var options = new RestClientOptions("{{apiPath}}/environments/{{envID}}/applications")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("", Method.Post);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Bearer {{accessToken}}");
var body = @"{" + "\n" +
@"    ""enabled"": true," + "\n" +
@"    ""name"": ""Device-App{{$timestamp}}""," + "\n" +
@"    ""description"": ""App for Device Auth Grant""," + "\n" +
@"    ""type"": ""CUSTOM_APP""," + "\n" +
@"    ""protocol"": ""OPENID_CONNECT""," + "\n" +
@"    ""grantTypes"": [" + "\n" +
@"        ""DEVICE_CODE""," + "\n" +
@"        ""REFRESH_TOKEN""" + "\n" +
@"    ]," + "\n" +
@"    ""deviceTimeout"": 600," + "\n" +
@"    ""devicePollingInterval"": 5," + "\n" +
@"    ""tokenEndpointAuthMethod"": ""NONE""" + "\n" +
@"}";
request.AddStringBody(body, DataFormat.Json);
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);
package main

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

func main() {

  url := "{{apiPath}}/environments/{{envID}}/applications"
  method := "POST"

  payload := strings.NewReader(`{
    "enabled": true,
    "name": "Device-App{{$timestamp}}",
    "description": "App for Device Auth Grant",
    "type": "CUSTOM_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
        "DEVICE_CODE",
        "REFRESH_TOKEN"
    ],
    "deviceTimeout": 600,
    "devicePollingInterval": 5,
    "tokenEndpointAuthMethod": "NONE"
}`)

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

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Authorization", "Bearer {{accessToken}}")

  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 /environments/{{envID}}/applications HTTP/1.1
Host: {{apiPath}}
Content-Type: application/json
Authorization: Bearer {{accessToken}}

{
    "enabled": true,
    "name": "Device-App{{$timestamp}}",
    "description": "App for Device Auth Grant",
    "type": "CUSTOM_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
        "DEVICE_CODE",
        "REFRESH_TOKEN"
    ],
    "deviceTimeout": 600,
    "devicePollingInterval": 5,
    "tokenEndpointAuthMethod": "NONE"
}
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n    \"enabled\": true,\n    \"name\": \"Device-App{{$timestamp}}\",\n    \"description\": \"App for Device Auth Grant\",\n    \"type\": \"CUSTOM_APP\",\n    \"protocol\": \"OPENID_CONNECT\",\n    \"grantTypes\": [\n        \"DEVICE_CODE\",\n        \"REFRESH_TOKEN\"\n    ],\n    \"deviceTimeout\": 600,\n    \"devicePollingInterval\": 5,\n    \"tokenEndpointAuthMethod\": \"NONE\"\n}");
Request request = new Request.Builder()
  .url("{{apiPath}}/environments/{{envID}}/applications")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Authorization", "Bearer {{accessToken}}")
  .build();
Response response = client.newCall(request).execute();
var settings = {
  "url": "{{apiPath}}/environments/{{envID}}/applications",
  "method": "POST",
  "timeout": 0,
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Bearer {{accessToken}}"
  },
  "data": JSON.stringify({
    "enabled": true,
    "name": "Device-App{{$timestamp}}",
    "description": "App for Device Auth Grant",
    "type": "CUSTOM_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
      "DEVICE_CODE",
      "REFRESH_TOKEN"
    ],
    "deviceTimeout": 600,
    "devicePollingInterval": 5,
    "tokenEndpointAuthMethod": "NONE"
  }),
};

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require('request');
var options = {
  'method': 'POST',
  'url': '{{apiPath}}/environments/{{envID}}/applications',
  'headers': {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer {{accessToken}}'
  },
  body: JSON.stringify({
    "enabled": true,
    "name": "Device-App{{$timestamp}}",
    "description": "App for Device Auth Grant",
    "type": "CUSTOM_APP",
    "protocol": "OPENID_CONNECT",
    "grantTypes": [
      "DEVICE_CODE",
      "REFRESH_TOKEN"
    ],
    "deviceTimeout": 600,
    "devicePollingInterval": 5,
    "tokenEndpointAuthMethod": "NONE"
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
import requests
import json

url = "{{apiPath}}/environments/{{envID}}/applications"

payload = json.dumps({
  "enabled": True,
  "name": "Device-App{{$timestamp}}",
  "description": "App for Device Auth Grant",
  "type": "CUSTOM_APP",
  "protocol": "OPENID_CONNECT",
  "grantTypes": [
    "DEVICE_CODE",
    "REFRESH_TOKEN"
  ],
  "deviceTimeout": 600,
  "devicePollingInterval": 5,
  "tokenEndpointAuthMethod": "NONE"
})
headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {{accessToken}}'
}

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

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('{{apiPath}}/environments/{{envID}}/applications');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Content-Type' => 'application/json',
  'Authorization' => 'Bearer {{accessToken}}'
));
$request->setBody('{\n    "enabled": true,\n    "name": "Device-App{{$timestamp}}",\n    "description": "App for Device Auth Grant",\n    "type": "CUSTOM_APP",\n    "protocol": "OPENID_CONNECT",\n    "grantTypes": [\n        "DEVICE_CODE",\n        "REFRESH_TOKEN"\n    ],\n    "deviceTimeout": 600,\n    "devicePollingInterval": 5,\n    "tokenEndpointAuthMethod": "NONE"\n}');
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 "json"
require "net/http"

url = URI("{{apiPath}}/environments/{{envID}}/applications")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["Authorization"] = "Bearer {{accessToken}}"
request.body = JSON.dump({
  "enabled": true,
  "name": "Device-App{{\$timestamp}}",
  "description": "App for Device Auth Grant",
  "type": "CUSTOM_APP",
  "protocol": "OPENID_CONNECT",
  "grantTypes": [
    "DEVICE_CODE",
    "REFRESH_TOKEN"
  ],
  "deviceTimeout": 600,
  "devicePollingInterval": 5,
  "tokenEndpointAuthMethod": "NONE"
})

response = http.request(request)
puts response.read_body
let parameters = "{\n    \"enabled\": true,\n    \"name\": \"Device-App{{$timestamp}}\",\n    \"description\": \"App for Device Auth Grant\",\n    \"type\": \"CUSTOM_APP\",\n    \"protocol\": \"OPENID_CONNECT\",\n    \"grantTypes\": [\n        \"DEVICE_CODE\",\n        \"REFRESH_TOKEN\"\n    ],\n    \"deviceTimeout\": 600,\n    \"devicePollingInterval\": 5,\n    \"tokenEndpointAuthMethod\": \"NONE\"\n}"
let postData = parameters.data(using: .utf8)

var request = URLRequest(url: URL(string: "{{apiPath}}/environments/{{envID}}/applications")!,timeoutInterval: Double.infinity)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer {{accessToken}}", 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

201 Created

{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/fa6d9bac-5928-4cdf-8810-f25e4e0af968"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
        },
        "attributes": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/fa6d9bac-5928-4cdf-8810-f25e4e0af968/attributes"
        },
        "pushCredentials": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/fa6d9bac-5928-4cdf-8810-f25e4e0af968/pushCredentials"
        },
        "secret": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/fa6d9bac-5928-4cdf-8810-f25e4e0af968/secret"
        },
        "grants": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/fa6d9bac-5928-4cdf-8810-f25e4e0af968/grants"
        }
    },
    "environment": {
        "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
    },
    "id": "fa6d9bac-5928-4cdf-8810-f25e4e0af968",
    "name": "Device-App1676502708",
    "description": "App for Device Auth Grant",
    "enabled": true,
    "hiddenFromAppPortal": false,
    "type": "CUSTOM_APP",
    "protocol": "OPENID_CONNECT",
    "createdAt": "2023-02-15T23:11:48.152Z",
    "updatedAt": "2023-02-15T23:11:48.152Z",
    "assignActorRoles": false,
    "grantTypes": [
        "REFRESH_TOKEN",
        "DEVICE_CODE"
    ],
    "tokenEndpointAuthMethod": "NONE",
    "pkceEnforcement": "OPTIONAL",
    "devicePollingInterval": 5,
    "signing": {
        "keyRotationPolicy": {
            "id": "38c6ccb0-bfd9-4e6b-ace7-4651c52a3c2c"
        }
    },
    "deviceTimeout": 600
}