- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 03-23-2020 08:59 AM
Hi Guys. As you may know, RSA 256 is the only algorithm available to sign with the JWT key.
Apple using ES256 algorithm and certificate that ends with p8 that available to download from their site.
If you'd like to use Apple's API services in SN and you need to sign the JWT key, you may find this article interesting.
A script in SN that calls the Mid server script include and sends Apple's parameters from SN to the mid server:
var jsProbe = new JavascriptProbe('YOUR MID SERVER NAME');
jsProbe.setName("ANY NAME THE ECC");
jsProbe.addParameter("certificate","YOUR CERTIFICATE P8 STRING");
jsProbe.addParameter("kid",'KEY ID');
jsProbe.addParameter("teamId",'TEAM ID');
jsProbe.setJavascript("var remoteFileImport = new appleConnect(); remoteFileImport.getSignedToken()"); //Name of the mid server script include and the executed method
jsProbe.create();
This script will generate an output record in the ECC table for the mid server with the name you have chosen.
Mid server script include:
Name: appleConnect
var appleConnect= Class.create();
appleConnect.prototype = {
initialize : function() {
this.certificate = probe.getParameter("certificate");
this.kid = probe.getParameter("kid");
this.teamId = probe.getParameter("teamId");
},
getSignedToken : function (){
var privateKeyPEM =this.certificate.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s", "");
var keyBytes = Packages.java.util.Base64.getDecoder().decode(privateKeyPEM);
var keyFactory = Packages.java.security.KeyFactory.getInstance("EC");
var PKCS8EncodedKeySpec = Packages.java.security.spec.PKCS8EncodedKeySpec;
var key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
var timestamp = new Packages.java.util.Date();
var exp = new Packages.java.util.Date(timestamp.getTime()+2000*60); //the expiration time for the token. you can change it to the time you'd like but be aware of apple's limit
var header = new Packages.com.nimbusds.jose.JWSHeader
.Builder(Packages.com.nimbusds.jose.JWSAlgorithm.ES256)
.keyID(this.kid)
.build();
var claimsSet = Packages.com.nimbusds.jwt.JWTClaimsSet.Builder()
.issuer(this.teamId)
.issueTime(timestamp)
.expirationTime(exp)
.audience("appstoreconnect-v1")
.build();
var signedJWT = new Packages.com.nimbusds.jwt.SignedJWT(header, claimsSet);
var signer = new Packages.com.nimbusds.jose.crypto.ECDSASigner(key);
signedJWT.sign(signer);
var token = signedJWT.serialize();
return token;
},
};
The script will return the generated token to the input ECC record.
Important note:
1. you need to add 3 JAR files to use the libraries inside the script include:
- JSON-smart-2.3.jar
- accessors-smart-1.2.jar
- nimbus-jose-jwt-8.10.jar
It might a little bit of time for SN to upload and update the mid server with these files, so be patient if you'll get errors when you call the methods that use them.
If you like this article, please hit the like button.
Have fun!
- 5,526 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Avid,
Can you please let us know where to find TEAM ID and how to download the CERTIFICATE from Apple site .Even we are trying to authenticate JWT token for Apple account.
Appreciate your help
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Did you try implementing the same using CertificateEncryption ? I see it supports SHA256withECDSA
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @avid
I have a similar requirement to generate a JWT token. However, I do not have a MID Server available in my environment.
Is it possible to generate an ES256 JWT in ServiceNow without using a MID Server? If yes, could you please suggest the recommended approach?
Any guidance would be highly appreciated.
FYI:- i am using below BS and token two parts generated but last one is not generating its showing Null
var certSysId = '';
var keyId = '';
var teamId = '';
function base64UrlEncode(obj) {
var str = JSON.stringify(obj);
var b64 = GlideStringUtil.base64Encode(str);
return b64.split('=').join('')
.split('+').join('-')
.split('/').join('_');
}
var header = { "alg": "ES256", "typ": "JWT", "kid": keyId };
var payload = {
"iss": teamId,
"iat": Math.floor(Date.now() / 1000),
"exp": Math.floor(Date.now() / 1000) + 3600
};
var encodedHeader = base64UrlEncode(header);
var encodedPayload = base64UrlEncode(payload);
var dataToSign = encodedHeader + "." + encodedPayload;
try {
var encryption = new GlideCertificateEncryption();
var signature = encryption.sign(certSysId, "1", "SHA256withECDSA", dataToSign);
// JWT
var finalJwt = dataToSign + "." + signature;
gs.info("Final ES256 JWT: " + finalJwt);
} catch (e) {
gs.error("Encryption Error: " + e.getMessage());
}
