Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Configuring OAuth Client Credentials with JWT on ServiceNow

Othman2
Tera Contributor

 

This guide explains how to configure OAuth authentication based on a signed JWT, in a scenario where ServiceNow does not generate the JWT, but only verifies it and issues the final OAuth token.

This situation is very common when an external application needs to authenticate into ServiceNow without a password, using only a key pair and a signed JWT.

Many people struggle with this topic (myself included), so this tutorial goes through every step, without assuming any knowledge, and with all the exact commands you need.


🟦 Before starting: understanding the basic idea

For ServiceNow to accept a JWT, you need a pair of keys:

Key Stored Where? Purpose
Private KeyOn the external applicationUsed to sign the JWT
Public KeyInside ServiceNowUsed to verify the signed JWT

We will use 3 tools:

  • ServiceNow → to issue the final OAuth token

  • jwt.io → to generate and sign the JWT

  • Postman → to test the final OAuth request


🟦 The 5 main steps

1️⃣ Generate the key pair (private + public)
2️⃣ Import the public key into ServiceNow
3️⃣ Create and configure the Application Registry
4️⃣ Correctly generate a signed JWT
5️⃣ Call ServiceNow from Postman using this JWT


🟦 1️⃣ Generating the private and public keys

Why this step?

✔ The private key will be used to sign your JWT
✔ The public key will be stored in ServiceNow to verify the signature
✔ Without this key pair, ServiceNow will reject any JWT

We will use keytool (included with Java) and OpenSSL.


🔧 1.1 Generate a keystore containing the private key

Run in your terminal:

 

 
keytool -genkey \ -alias snclient \ -keyalg RSA \ -validity 365 \ -keystore snclient.keystore \ -storepass abcd1234 \ -keypass abcd1234

 

👉 This creates the file snclient.keystore
👉 The keystore and key password is abcd1234

You can choose any filenames or passwords, but make sure you save them, you will need them later.


🔧 1.2 Convert to PKCS12 format

Why?
Because OpenSSL cannot extract the private key directly from a JKS keystore.

So we convert the .keystore into .p12:

 

 
keytool -importkeystore \ -srckeystore snclient.keystore \ -srcstoretype JKS \ -destkeystore snclient.p12 \ -deststoretype PKCS12 \ -storepass abcd1234 \ -deststorepass abcd1234

 

Result: snclient.p12


🔧 1.3 Extract the private key in PEM format

Now extract the private key:

openssl pkcs12 -in snclient.p12 -nocerts -nodes -out private_key.pem

 

Result:
👉 private_key.pem (private key)

⚠️ This key must remain secret. Never upload it to ServiceNow.
ServiceNow only needs the public key.


🔧 1.4 Export the public key in PEM format

Export the certificate from the keystore:

 
keytool -exportcert \ -alias snclient \ -keystore snclient.keystore \ -storepass abcd1234 \ -file snclient.cer

 

This creates: snclient.cer

Convert it to PEM:

openssl x509 -inform der -in snclient.cer -out certificate.pem

 

Result:
👉 certificate.pem (public key)


🎯 At the end of Step 1, you must have:

File Contains Used For
private_key.pemPrivate keyUsed to sign JWTs
certificate.pemPublic keyUsed by ServiceNow to verify JWTs

🟦 2️⃣ Import the public key into ServiceNow

Why?
Because ServiceNow must verify the JWT signature using this public key.

Go to:
System Security → Certificates

Steps:

  1. Click New

  2. Select PEM Certificate

  3. Paste the entire content of certificate.pem into the PEM Certificate field

  4. Save

Your certificate is now ready.
ServiceNow now knows your public key.

Othman2_0-1764840349604.png

 


🟦 3️⃣ Create and configure the Application Registry

Go to:
System OAuth → Application Registry

  1. Click New

  2. Choose:
    Create an OAuth JWT API endpoint for external clients

  3. Give it a name

  4. Save

ServiceNow will generate:

  • Client ID (very important, used everywhere)

  • Client Secret

Othman2_1-1764840373773.png

 


🔧 Add a JWT Verifier Map

In the related list:

➡️ JWT Verifier Maps
➡️ Click New

Fill in:

  • Name: anything you want

  • KID: automatically generated (keep this!)

  • Shared Key: enter abcd1234 (keystore password)

  • Certificate: select the certificate imported in Step 2

Why is Shared Key = keystore password?

👉 ServiceNow verifies that this password matches the one used to generate your key pair.

Othman2_2-1764840388293.png

 


🟦 4️⃣ Generate the JWT (the part everyone fails)

We will use https://jwt.io for clarity.

A JWT has 3 parts:

1️⃣ Header
2️⃣ Payload
3️⃣ Signature (signed with your private key)


🔧 Header (important)

{ "alg": "RS256", "typ": "JWT", "kid": "YOUR_SERVICENOW_KID" }

 

Explanation:

  • alg: signing algorithm → ServiceNow accepts RS256

  • kid: the Key ID → generated automatically in your JWT Verifier Map


🔧 Payload (even more important)

Example:

{ "sub": "user.non.admin@example.com", "aud": "CLIENT_ID", "iss": "CLIENT_ID", "exp": 1764771148, "iat": 1764770848, "jti": "uuid-unique" }

 

Explanation:

Claim Purpose
subServiceNow user executing the action (⚠️ cannot be admin)
audThe Client ID
issThe Client ID
iatCurrent timestamp
expExpiration timestamp (iat + 5 min recommended)
jtiUnique ID for this JWT (UUID)

🔧 Generate iat and exp in JS

  • iat = now

  • exp = now + 5 minutes

Example:

 

 
var iat = Math.floor(Date.now() / 1000); var exp = iat + 300; // + 5 minutes gs.info("iat=" + iat + " exp=" + exp);

 

🔧 Signature (using the private key)

In jwt.io, paste the full content of private_key.pem in:

➡️ Sign → Private Key

jwt.io will generate your signed JWT.

Copy it.

Othman2_3-1764840412295.png

 


🟦 5️⃣ Send the request in Postman

Method:
➡️ POST
➡️ URL:

https://<your_instance>.service-now.com/oauth_token.do

 

Auth:
➡️ None

Body (x-www-form-urlencoded):

Key Value
client_idYour Client ID
client_secretYour Client Secret
grant_typeurn:ietf:params:oauth:grant-type:jwt-bearer
assertionYour signed JWT
Othman2_4-1764840439683.png

 


Expected response

 

{
"access_token": "eyJhbGciOi...", "token_type": "Bearer", "expires_in": 3600 }

Othman2_5-1764840450569.png

 

0 REPLIES 0