Announcing the Saviynt Knowledge Exchange unifying the Saviynt forums, documentation, training,
and more in a single search tool across platforms. Read the announcement here.

JWT in REST connection

fy
New Contributor
New Contributor

Hi all,

Have you ever worked on JWT in REST connection? We have a requirement to integrate PingIdentity with Saviynt through PingIdentity APIs. To make a call to the PingID API, we must construct an API request token. 

The request token is a JSON Web Token (JWT) signed with a JSON Web Signature (JWS) which is sent to the PingID API endpoint.

A JWS consists of three components:

  • Header{ "alg": "HS256", "org_alias": "aaaaaaaa-a1b2-123a-b456-1234abcd5678", "token": "1a2b3c4d5e6f" }
  • Request payload{ "reqHeader": { "locale":"en", "orgAlias":"aaaaaaaa-a1b2-123a-b456-1234abcd5678", "secretKey":"1a2b3c4d5e6f", "timestamp":"2015-09-03 11:57:25.229", "version":"4.9" }, "reqBody": { "activateUser":false, "clientData":null, "email":"marcher@pingdevelopers.com", "fName":"Meredith", "lname":"Archer", "picUrl":null, "role":"REGULAR", "username":"marcher" } }
  • Digital signature - Before sending the request token to the API endpoint, the contents must be signed using the use_base64_key

The reqHeader object is identical for all API calls while the reqBody object will vary for each API operation.

How do we implement this logic in Saviynt REST connection?

According to some posts here, Saviynt supports JWT from v2021 onwards. We attempted to configure the connection string a REST connector based on the link REST Connector Guide : Customer Portal (freshdesk.com). PingID endpoints failed the token validation...

connectionJSON: 

{
"authentications":{
"acctAuth":{
"authType":"Jwt",
"httpParamsName":"assertion",
"jwtConfig":{
"jwtHeader":{
"alg":"HS256",
"typ":"JWT",
"kid":"c12544012ad6a3f5bf102c22236f2aeb"
},
"jwtPayload":{
"iss":"pingid",
"sub":"pingidapi",
"aud":"f16eb696-a29b-4d3e-9812-c215b052347e",
"scope":"https://idpxnyl3m.pingidentity.com/pingid/rest/4"
},
"signedAlgorithm":"HS256",
"key":"n2avMKYoEe28STp0R3+kyjlaoDczoVLY3T0+gteDm6M=",
"jwtExpiryDuration":120
},
"url":"https://idpxnyl3m.pingidentity.com/pingid",
"httpMethod":"POST",
"httpParams":{
"grant_type":"urn:ietf:params:oauth:grant-type:jwt-bearer"
},
"httpContentType":"application/x-www-form-urlencoded",
"retryFailureStatusCode":[
401,
500,
400
],
"authError":[
"SESSION_NOT_VALID",
"AuthenticationFailed",
"ExpiredJwtException",
"401 Unauthorized",
"401",
"You couldn't be authenticated"
],
"errorPath":"code",
"maxRefreshTryCount":5,
"tokenResponsePath":"access_token",
"tokenType":"Bearer",
"accessToken":""
}
}
}

createAccountJSON:

{
"accountIdPath":"call1.message.id",
"dateFormat":"yyyy-MM-dd'T'HH:mm:ssXXX",
"responseColsToPropsMap":{
"name":"call1.message.username~#~char",
"updatedate":"call1.message.meta.created~#~date",
"comments":"PingID~#~char"
},
"call":[
{
"name":"call1",
"connection":"acctAuth",
"url":"https://idpxnyl3m.pingidentity.com/pingid/rest/4/deleteuser/do",
"httpMethod":"POST",
"httpParams":"{\"userName\":\"${user.email==null?user.email:''}\"}",
"httpHeaders":{
"Authorization":"${access_token}"
},
"httpContentType":"application/json",
"successResponses":{
"statusCode":[
201,
200
]
},
"unsuccessResponses":{
"statusCode":[
400,
500
]
}
}
]
}

{
"accountIdPath":"call1.message.id",
"dateFormat":"yyyy-MM-dd'T'HH:mm:ssXXX",
"responseColsToPropsMap":{
"name":"call1.message.username~#~char",
"updatedate":"call1.message.meta.created~#~date",
"comments":"PingID~#~char"
},
"call":[
{
"name":"call1",
"connection":"acctAuth",
"url":"https://idpxnyl3m.pingidentity.com/pingid/rest/4/adduser/do",
"httpMethod":"POST",
"httpParams":"{\"userName\":\"${user.email==null?user.email:''}\",\"activateUser\":false,\"fName\":\"${user.firstname}\",\"lname\":\"${user.lastname}\",\"email\":\"${user.email}\",\"role\":\"REGULAR\"}",
"httpHeaders":{
"Authorization":"${access_token}"
},
"httpContentType":"application/json",
"successResponses":{
"statusCode":[
201,
200
]
},
"unsuccessResponses":{
"statusCode":[
400,
500
]
}
},
{
"name":"call2",
"connection":"acctAuth",
"url":"https://idpxnyl3m.pingidentity.com/pingid/rest/4/offlinepairing/do",
"httpMethod":"POST",
"httpParams":"{\"userName\":\"${user.email==null?user.email:''}\",\"type\":\"EMAIL\",\"pairingData\":\"${user.email==null?user.email:''}\",\"validateUniqueDevice\":false}",
"httpHeaders":{
"Authorization":"${access_token}"
},
"httpContentType":"application/json",
"successResponses":{
"statusCode":[
201,
200
]
},
"unsuccessResponses":{
"statusCode":[
400,
500
]
}
}

]

}

 

The error we got from Saviynt is below.

saviynt log

{"log":"2023-03-14 21:38:09,342 [quartzScheduler_Worker-4] DEBUG rest.RestProvisioningService - Task Response: {\"call1\":{\"headers\":{\"date\":\"Tue, 14 Mar 2023 21:38:08 GMT\",\"server\":\"\",\"set-cookie\":\"AccellsSessionID=webs__tba-sfv6_jsHrHRsZIqJuAiuvUpEP4kCYjwFnTKt0Q; Path=/AccellServer\",\"transfer-encoding\":\"chunked\",\"x-content-type-options\":\"nosniff\",\"x-ping-pingid-jwtvalidationpassfail\":\"webs__tba-sfv6_jsHrHRsZIqJuAiuvUpEP4kCYjwFnTKt0Q\",\"content-type\":\"application/json\",\"connection\":\"close\",\"strict-transport-security\":\"max-age=15768000; includeSubDomains; preload;\"},\"message\":{\"responseBody\":{\"clientData\":null,\"errorId\":403,\"errorMsg\":\"Could not read the http header of the request\",\"uniqueMsgId\":null}},\"statusCode\":403,\"description\":null,\"status\":\"Success\"},\"call2\":{\"headers\":{\"date\":\"Tue, 14 Mar 2023 21:38:08 GMT\",\"server\":\"\",\"set-cookie\":\"AccellsSessionID=webs_QRHBirFX-ZLmWbY_mamGCHB0aLwNtAD23B1tZlkfPe0; Path=/AccellServer\",\"transfer-encoding\":\"chunked\",\"x-content-type-options\":\"nosniff\",\"x-ping-pingid-jwtvalidationpassfail\":\"webs_QRHBirFX-ZLmWbY_mamGCHB0aLwNtAD23B1tZlkfPe0\",\"content-type\":\"application/json\",\"connection\":\"close\",\"strict-transport-security\":\"max-age=15768000; includeSubDomains; preload;\"},\"message\":{\"responseBody\":{\"clientData\":null,\"errorId\":403,\"errorMsg\":\"Could not read the http header of the request\",\"uniqueMsgId\":null}},\"statusCode\":403,\"description\":null,\"status\":\"Success\"}}\n","stream":"stdout","time":"2023-03-14T21:38:09.343009784Z"}

 

I am looking forward to hearing from you. Thanks

 

-Fran

1 REPLY 1

SB
Saviynt Employee
Saviynt Employee

Can you run your token call in postman. Click on Console at bottom left and then expand the url you ran for auth token. You should see a headers section.

sahil_1-1679074135255.png

Can you verify if you see a value similar to above screenshot under headers. In case you do, can you update your Connection json and include this value in the headers.

ex: 

"httpHeaders": {
              "Authorization": "Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }

 

 


Regards,
Sahil