Create Credential Verification Session (OPENID4VP)
POST {{apiPath}}/environments/{{envId}}/presentationSessions
Use the POST {{apiPath}}/environments/{{envId}}/presentationSessions to initiate verification of a user credential using the OpenID for Verifiable Presentations (OPENID4VP) protocol of JSON Web Token Verifiable Credentials (JWT-VC). Each credential verification session silently times out after 5 minutes.
Prerequisites
-
Refer to Credential Verifications for important overview information.
Request Model
Refer to Credential Verifications session data model for full property descriptions.
| Property | Type | Required |
|---|---|---|
|
String |
Optional |
|
String[] |
Optional |
|
String[] |
Optional |
|
String |
Optional |
|
String |
Optional |
|
String |
Optional |
|
Object[] |
Required |
|
String[] |
Optional |
|
String |
Required |
|
Integer |
Optional |
|
Content of |
Using the PingOne Wallet Native SDKs, a wallet app retrieves verification information from the returned _links.appOpenURL.href. The information retrieved varies depending on the didMethod in the request.
If issuerFilter.dids is submitted and protocol is OPENID4VP, the service searches all listed decentralized identifiers for the issuer of the presented credential. If the user presents a credential that is not from one of these issuers, the verification fails with status of VERIFICATION_FAILED.
This issuerFilter.dids typically contains decentralized identifiers for issuers that are not using PingOne Credentials for JWT-VC issuance. The service supports these three DID methods:
-
did:jwk - https://github.com/quartzjer/did-jwk/blob/main/spec.md
-
did:ion - https://identity.foundation/ion/ (The service supports only long-form URIs for this method)
If issuerFilter.environmentIds is submitted, the service searches all listed environments for the issuer of the presented credential. If the user presents a credential that is not from one of these issuers, the verification fails with status of VERIFICATION_FAILED.
Body
raw ( application/json )
{
"message": "Some custom message for the user.",
"protocol": "OPENID4VP",
"requestedCredentials": [
{
"type": "Driver License",
"keys": [
"First Name",
"Last Name"
]
}
],
"timeoutSeconds" : 30,
"issuerFilter": {
"dids": [
"did:web:auth.pingone.com:{{envId}}:issuer"
]
}
}
Example Request
-
cURL
-
C#
-
Go
-
HTTP
-
Java
-
jQuery
-
NodeJS
-
Python
-
PHP
-
Ruby
-
Swift
curl --location --globoff '{{apiPath}}/environments/{{envId}}/presentationSessions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{accessToken}}' \
--data '{
"message": "Some custom message for the user.",
"protocol": "OPENID4VP",
"requestedCredentials": [
{
"type": "Driver License",
"keys": [
"First Name",
"Last Name"
]
}
],
"timeoutSeconds" : 30,
"issuerFilter": {
"dids": [
"did:web:auth.pingone.com:{{envId}}:issuer"
]
}
}'
var options = new RestClientOptions("{{apiPath}}/environments/{{envId}}/presentationSessions")
{
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" +
@" ""message"": ""Some custom message for the user.""," + "\n" +
@" ""protocol"": ""OPENID4VP""," + "\n" +
@" ""requestedCredentials"": [" + "\n" +
@" {" + "\n" +
@" ""type"": ""Driver License""," + "\n" +
@" ""keys"": [" + "\n" +
@" ""First Name""," + "\n" +
@" ""Last Name""" + "\n" +
@" ]" + "\n" +
@" }" + "\n" +
@" ]," + "\n" +
@" ""timeoutSeconds"" : 30," + "\n" +
@" ""issuerFilter"": {" + "\n" +
@" ""dids"": [" + "\n" +
@" ""did:web:auth.pingone.com:{{envId}}:issuer""" + "\n" +
@" ]" + "\n" +
@" }" + "\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}}/presentationSessions"
method := "POST"
payload := strings.NewReader(`{
"message": "Some custom message for the user.",
"protocol": "OPENID4VP",
"requestedCredentials": [
{
"type": "Driver License",
"keys": [
"First Name",
"Last Name"
]
}
],
"timeoutSeconds" : 30,
"issuerFilter": {
"dids": [
"did:web:auth.pingone.com:{{envId}}:issuer"
]
}
}`)
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}}/presentationSessions HTTP/1.1
Host: {{apiPath}}
Content-Type: application/json
Authorization: Bearer {{accessToken}}
{
"message": "Some custom message for the user.",
"protocol": "OPENID4VP",
"requestedCredentials": [
{
"type": "Driver License",
"keys": [
"First Name",
"Last Name"
]
}
],
"timeoutSeconds" : 30,
"issuerFilter": {
"dids": [
"did:web:auth.pingone.com:{{envId}}:issuer"
]
}
}
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"message\": \"Some custom message for the user.\",\n \"protocol\": \"OPENID4VP\",\n \"requestedCredentials\": [\n {\n \"type\": \"Driver License\",\n \"keys\": [\n \"First Name\",\n \"Last Name\"\n ]\n }\n ],\n \"timeoutSeconds\" : 30,\n \"issuerFilter\": {\n \"dids\": [\n \"did:web:auth.pingone.com:{{envId}}:issuer\"\n ]\n }\n}");
Request request = new Request.Builder()
.url("{{apiPath}}/environments/{{envId}}/presentationSessions")
.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}}/presentationSessions",
"method": "POST",
"timeout": 0,
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {{accessToken}}"
},
"data": JSON.stringify({
"message": "Some custom message for the user.",
"protocol": "OPENID4VP",
"requestedCredentials": [
{
"type": "Driver License",
"keys": [
"First Name",
"Last Name"
]
}
],
"timeoutSeconds": 30,
"issuerFilter": {
"dids": [
"did:web:auth.pingone.com:{{envId}}:issuer"
]
}
}),
};
$.ajax(settings).done(function (response) {
console.log(response);
});
var request = require('request');
var options = {
'method': 'POST',
'url': '{{apiPath}}/environments/{{envId}}/presentationSessions',
'headers': {
'Content-Type': 'application/json',
'Authorization': 'Bearer {{accessToken}}'
},
body: JSON.stringify({
"message": "Some custom message for the user.",
"protocol": "OPENID4VP",
"requestedCredentials": [
{
"type": "Driver License",
"keys": [
"First Name",
"Last Name"
]
}
],
"timeoutSeconds": 30,
"issuerFilter": {
"dids": [
"did:web:auth.pingone.com:{{envId}}:issuer"
]
}
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{{apiPath}}/environments/{{envId}}/presentationSessions"
payload = json.dumps({
"message": "Some custom message for the user.",
"protocol": "OPENID4VP",
"requestedCredentials": [
{
"type": "Driver License",
"keys": [
"First Name",
"Last Name"
]
}
],
"timeoutSeconds": 30,
"issuerFilter": {
"dids": [
"did:web:auth.pingone.com:{{envId}}:issuer"
]
}
})
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}}/presentationSessions');
$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 "message": "Some custom message for the user.",\n "protocol": "OPENID4VP",\n "requestedCredentials": [\n {\n "type": "Driver License",\n "keys": [\n "First Name",\n "Last Name"\n ]\n }\n ],\n "timeoutSeconds" : 30,\n "issuerFilter": {\n "dids": [\n "did:web:auth.pingone.com:{{envId}}:issuer"\n ]\n }\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}}/presentationSessions")
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({
"message": "Some custom message for the user.",
"protocol": "OPENID4VP",
"requestedCredentials": [
{
"type": "Driver License",
"keys": [
"First Name",
"Last Name"
]
}
],
"timeoutSeconds": 30,
"issuerFilter": {
"dids": [
"did:web:auth.pingone.com:{{envId}}:issuer"
]
}
})
response = http.request(request)
puts response.read_body
let parameters = "{\n \"message\": \"Some custom message for the user.\",\n \"protocol\": \"OPENID4VP\",\n \"requestedCredentials\": [\n {\n \"type\": \"Driver License\",\n \"keys\": [\n \"First Name\",\n \"Last Name\"\n ]\n }\n ],\n \"timeoutSeconds\" : 30,\n \"issuerFilter\": {\n \"dids\": [\n \"did:web:auth.pingone.com:{{envId}}:issuer\"\n ]\n }\n}"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "{{apiPath}}/environments/{{envId}}/presentationSessions")!,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
202 Accepted
{
"_links": {
"self": {
"href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/presentationSessions/ac18c46b-03b8-4293-a9c9-ef4877c84d5c"
},
"qr": {
"href": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAIAAAAiOjnJAAAE5ElEQVR42u3dwXEbMQwFUBeSMtKC+y/JaSAHScAHIOthfNJkNivyaQYLkNyvHyEC8WUIBFgCLAGWEGAJsARYQoAlwBJg/Tf+/P1u/3vktp69zrP/17PXfPaeE2N44R4evx+wwAILLLDAAuuVG302KpNX+ZKTk10Zq8r1K+PQNY9ggQUWWGCBBVYPrMSgJ5LWrkhcPzFuF+YRLLDAAgsssMDah1UpeCaKh13F267vlbgmWGCBBRZYYIElea82ZdP3kG54p4u3YIEFFlhggQXWLViJJnQ6+U0n8l0PDeli7MetbgALLLDAAgus47AmF8f5PPf5R+zS8TlYYIEFls+Pw5qMdEO6a7NruvhZGbf0gsfHAyywwAILLLDASiXvlUJo1yCmG8/pzbTpucgVbMECCyywwAILrCtNzQTK9AEeW8349ANEfX7BAgsssMACC6zqQHRNxtahapWB3nooSYxtb3EVLLDAAgsssMBKwdo68CN9aFu6Ud2VvO++0AAssMACCyywwKoWMycBJSYvgSaRyE8uKqwXS8ECCyywwAILrM4GagJE7xfeTfYvFIHTPwywwAILLLDAAqsH1haaCxsW0k30O03l5iY0WGCBBRZYYIEVTd4TSWsC2YUfXvpBZPQFAmCBBRZYYIEFVkth7domha2i4mSBtJLsjxZIwQILLLDAAusDYW0t7ptMxtMHaVxYoPeWb6YACyywwAILrA+E1TUoW4l/ItGeLMxu3T9YYIEFFlhggbVzKEhi4tON8AsHyN5sJFca7WCBBRZYYIEFVhXWhQT8pykS9791P/NFUbDAAgsssMAC61FYuQJabxEvMUm9yexu4zz9QwILLLDAAgsssOaS98mBuHb/ic0L6fvs/RmDBRZYYIEFFlipRDjdAJ48qK3r36cfYrZ+qGCBBRZYYIEF1uuwJjcyTBZjrzXRry0qHH2BAFhggQUWWGB9IKzJxDOxmG4SQeJgt8ki8NuvbgALLLDAAgus47Amv1gitjbHpjd6TF5zdJcOWGCBBRZYYH0IrHTDNd2oTkCZTK4nD0zrXQwIFlhggQUWWGBNFC23GqvplwMkCsWTyfjaQj+wwAILLLDAAuvUBtQE+gsPCumXG6TBgQUWWGCBBRZYPbAqA51e5D9zeGs9oU78ALYWS4IFFlhggQUWWP0F0snNApMvHkpvLk0XV9PXBAsssMACCyywXofV9QUmF68lkt90A7s+kbmi6OlDQcACCyywwALrTWFNLna7dv2uYmbXeE5ep57sgwUWWGCBBRZYnXFhYq41obvGarKoW3+AAAsssMACCyywqsXJmRutJ5sXIE5ulN09UA4ssMACCyywwJooWk4WMy8k/tcWJyZekgUWWGCBBRZYYM0VSLcKqokXEiUeaCZfFJV4GAILLLDAAgsssPY3rKaT3K1rbk3q/aIoWGCBBRZYYIHVWSBNFDwnD2pLF10TDzG/KnkHCyywwAILLLDGksfJZHProSRdWN69f7DAAgsssMAC6zqs9IK19KaJaygTBVuwwAILLLDAAuu9YSWKrlsQ0xtPdhGDBRZYYIEFFlibTej05oiuCUg3tidf0jSz2QQssMACCyywwJpo0CYSzPQ1J//SReP0hguwwAILLLDAAus5WEJECqRCgCXAEmAJAZYAS4AlBFgCLPF74x/OB65c5GBm8gAAAABJRU5ErkJggg=="
},
"appOpenUrl": {
"href": "openid-vc://?request_uri=https://api.pingone.com/v1/distributedid/verifications/presentation_sessions/ac18c46b-03b8-4293-a9c9-ef4877c84d5c/request"
}
},
"id": "ac18c46b-03b8-4293-a9c9-ef4877c84d5c",
"createdAt": "2024-10-24T16:39:52.991303314Z",
"expiresAt": "2024-10-24T16:40:22.991301494Z",
"status": "INITIAL"
}