Using JWT User Assertion

You must generate a signed, encoded JWT user assertion using the private key which corresponds to the public certificate uploaded to the confidential application.

To enable and use signed user assertions, you must:

  1. Generate a JWT user assertion.
  2. Generate the access token.

Requirements for the JWT header and payload are outlined in Oracle Cloud Platform REST Adapter documentation at 2 REST Adapter Concepts, Authentication Support, in the Use OAuth 2.0 Grants in Identity Domain Environments section. You can shortcut to the correct section by clicking the Prerequisites for JWT User Assertion link.

A user assertion includes a header, body, and signature.

The header must include the following attributes:

Name

Value

kid

The key identifier identifies the trusted, third-party certificate for validating the assertion signature. The KID must match the certificateAlias of the public certificate.

Choose either to use a KID or x5t. You do not need to use both.

x5t

Base64 URL encoded X.509 certificate sha1 thumbprint. Used to identify the trusted third-party certificate to validate the assertion signature.

Choose either to use a x5t or KID. You do not need to use both.

type

The type identifies the type of assertion. For this process, use JWT.

alg

The algorithm identifies the specific type of JWT signing algorithm being used. For this process, use RS256.

The body must include the following claims:

Name

Value

sub

The subject is the Primavera Cloud account username.

iss

The issuer is the client ID of the confidential application.

See: Prerequisite Setup

aud

The audience defines the recipients for which the JWT is intended. For this process, use https://identity.oraclecloud.com.

exp

The expiration time of the JWT assertion, specified in UNIX epoch time.

iat

The date the assertion was issued, in UNIX epoch time.

jti

The unique identifier for the JWT. A JWT ID can only be used once.

Here is an example JSON header and body:

{"kid":"MyCertificateAlias","type":"JWT","alg":"RS256"}
{"sub":"P6WS_UserName","iss":"MyClientID","aud":"https://identity.oraclecloud.com/","exp":1708778535,"iat":1708774935,"jti":12345}

The header and body are Base64-encoded and concatenated by a dot then signed in the RS256 algorithm, using your private key.

The result is three Base64 strings separated by dots in the format of Header.Body.Signature

Here is an example signed user assertion:

eyJraWQiOiJNeUNlcnRpZmljYXRlQWxpYXMiLCJ0eXBlIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJQNldTX1VzZXJOYW1lIiwiaXNzIjoiTXlDbGllbnRJRCIsImF1ZCI6Imh0dHBzOi8vaWRlbnRpdHkub3JhY2xlY2xvdWQuY29tLyIsImV4cCI6MTcwODc3ODUzNSwiaWF0IjoxNzA4Nzc0OTM1LCJqdGkiOjEyMzQ1fQ.jaQ2NyGk8wOWWHMGi2QJTsYlKGcHrfqkvP2Gb8AlBbJDQy7NDonXh6YMcAe17iIVaOfH7lDgJyF95xPv3nPHdIezbqobHBck34yct6I6a_xpKcV5kmJfXLHeb9LenqZTbdMMQ95vlUL8R914AmE2TbwGqjl4XkIoADHDez7PVM2MwyIDSfEaQ6o7J05ES7wIgI9gGspQ5w-2Xem4GOare25FBo-LrgVADDiAhKUhSLNT6XISCMAHZ3L2J86cnRhU1fekr-DJYFyfDcgAZeQPSPETHGokBWYtC1K-2qIouODKBKBcooABYEh6YTkC7bdax5KqFFbvJmSfDEjyN3tZ4w

There are several libraries available to generate/sign the JWT, here: https://jwt.io/libraries

Example using Python

import requests, base64, uuid, sys, hashlib
from datetime import datetime, timezone ##timezone only available in python 3.2+
import jwt ##jwt requires "pip install pyjwt"
from OpenSSL.crypto import load_pkcs12, dump_privatekey, dump_certificate, FILETYPE_PEM, FILETYPE_ASN1

#script can be executed as follows:
#python3 getOAuthToken_example.py <username> <expiry>
#Ex: python3 getOAuthToken_example.py JonesE 86400
# where 'JonesE' is the username and 86400 is the expiry in seconds

#This python script example includes both the JWT user assertion generation and
#OAuth access token generation using base64-encoded client ID and secret

#MISC VARIABLE CREATION
userName = sys.argv[1]
expiryDuration = int(sys.argv[2])
tokenIssued = int(datetime.now(tz=timezone.utc).timestamp())
tokenExpiry = tokenIssued + expiryDuration
tokenJti = str(uuid.uuid4()) #generates random UUID
tokenEndpoint = '/oauth2/v1/token'
idcs_url = 'https://<idcs_tenant_url>' + tokenEndpoint
clientId = '<clientid_from_confidential_application>'
clientSecret = '<clientsecret_from_confidential_application>'
audience = 'https://identity.oraclecloud.com/'
signing_alg = 'RS256'

#SCOPE VARIABLE CREATION
#scope = 'urn:opc:idm:__myscopes__' #allows an expiry range between 60s to 3600s
scope = 'urn:opc:idm:__myscopes__ urn:opc:resource:expiry=' + str(expiryDuration) #allows an expiry range between 60s to 31556952s

#LOAD PKCS12 AND READ PRIVATE KEY IN PEM FORMAT
p12_file = open('/home/oracle/jwt.p12', 'rb').read() #path is relative to location of P12 file
p12_pwd_bytes = "password1".encode('utf8') #password is relative to p12 file
p12 = load_pkcs12(p12_file, p12_pwd_bytes)
private_key = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())

#GENERATE KID FOR JWT USER ASSERTION
#Equal to the public certificate alias uploaded to your IDCS confidential application
certAlias = 'jwtkey' #alias is relative to the alias of private key

#GENERATE X5T FOR JWT USER ASSERTION
#Equal to the base64, url-encoded X.509 certificate sha1 thumbprint
cert = p12.get_certificate()
cert_der = dump_certificate(FILETYPE_ASN1, cert)
sha1_hash = hashlib.sha1(cert_der).digest()
x5t = base64.urlsafe_b64encode(sha1_hash).decode('utf8').rstrip('=')

#BASE64 ENCODE CLIENTID:CLIENTSECRET
clientIdSecret = clientId + ':' + clientSecret
clientIdSecret_bytes = clientIdSecret.encode("ascii")
clientIdSecret_base64_bytes = base64.b64encode(clientIdSecret_bytes)
clientIdSecret_base64_string = clientIdSecret_base64_bytes.decode("ascii")

#JWT CREATION
#Either the x5t or kid claim must be present in the JWT assertion header (no need for both)
#but this example will include both for demonstration purpose header = {
"alg":signing_alg,
"typ":"JWT",
"kid":certAlias,
"x5t":x5t
}
user_payload = {
"sub":userName,
"iss":clientId,
"aud":audience,
"iat":tokenIssued,
"exp":tokenExpiry,
"jti":tokenJti
}
encoded_user_assertion = jwt.encode(
payload=user_payload,
headers=header,
key=private_key,
algorithm=signing_alg)

#IDCS OAUTH REQUEST HEADER AND PAYLOAD CREATION USING CLIENT ID AND CLIENT SECRET
headers = {
'Content-Type':'application/x-www-form-urlencoded',
'Authorization':'Basic ' + clientIdSecret_base64_string
}
payload = {
'grant_type':'urn:ietf:params:oauth:grant-type:jwt-bearer',
'scope':scope,
'assertion':encoded_user_assertion
}

#IDCS OAUTH TOKEN REQUEST EXECUTION
response = requests.request("POST", idcs_url, headers=headers, data=payload)

#SCRIPT OUTPUT
print()
print()
print()
print('***************************************************************')
print('JWT OAUTH TOKEN GENERATION TEST')
print('***************************************************************')
print()
print('******************************')
print('ENVIRONMENT')
print('******************************')
print('OAUTH TOKEN GENERATION FOR USER:')
print(userName)
print()
print('******************************')
print('VARIABLES')
print('******************************')
print('TOKEN EXPIRY DURATION:')
print(str(expiryDuration) + ' seconds')
print()
print('TOKEN JTI:')
print(tokenJti)
print()
print('ENCODED CLIENTID:SECRET:')
print(clientIdSecret_base64_string)
print()
print('IDCS OAUTH TOKEN ENDPOINT:')
print(idcs_url)
print()
print('P12 PRIVATE KEY:')
print(private_key)
print()
print('ENCODED JWT USER ASSERTION:')
print(encoded_user_assertion)
print()
print('******************************')
print('IDCS OAUTH TOKEN REQUEST HEADERS AND PAYLOAD')
print('******************************')
print('REQUEST HEADERS:')
print(headers)
print()
print('REQUEST PAYLOAD:')
print(payload)
print()
print('******************************')
print('OAUTH TOKEN RESPONSE')
print('******************************')
print(response.json())
print()

Example using Java Code

For an example of using Java Code to create a JWT token for an assertion grant type, see: https://www.ateam-oracle.com/post/creating-a-jwt-token-for-an-assertion-grant-type-flow

For an example of using Java Code to create a JWT token for Oracle IDCS, see: https://www.ateam-oracle.com/post/create-a-jwt-token-in-java-for-oracle-idcs

Related Topics

Using JSON Web Token (JWT) Grant Type

Prerequisite Setup

Using Refresh Tokens



Last Published Tuesday, April 1, 2025