Assistance with JWT generation with Grouper integration

scoburn1
Tera Contributor

Good Morning All,

 

We have been asked to attempt to integrate with the following application (Grouper) here:

https://spaces.at.internet2.edu/display/Grouper/Grouper+web+services+-+authentication+-+self-service...

 

The authentication method available is "Self Service JWT". Their team has provided us the Private Key string outlined in Step 1. Now, we are attempting to generate the JWT using this on our end. 

 

While the following script looks to output a JWT, we are unclear if this is created and signed properly or what mechanisms ServiceNow has to handle these. We did see the documentation here (https://docs.servicenow.com/bundle/tokyo-platform-security/page/administer/security/concept/Scoped-A...) but as we are not setting them up as an Oauth provider I don't believe this is the path forward. There are also some signing references on the CertificateEncryption() API but again this looks to point to certificate records whereas we are just being provided a Key. We are also not using a MID server or importing external libraries at this time. 

Here is the current Script Include and client call used:

var JWTGenerator = Class.create(); 

JWTGenerator.prototype = { 

    initialize: function() {}, 

    generateJWT: function() { 

        try { 

            // Define the JWT Header 

            var header = { 

                alg: "RS256", 

                typ: "JWT" 

            }; 


            // Define the JWT Payload 

            var payload = { 

                iss: "your-issuer", 

                sub: "your-subject", 

                aud: "your-audience", 

                exp: (new Date().getTime() / 1000) + 600,  // Token expiration time (10 minutes from now) 

                iat: new Date().getTime() / 1000, 

                // Add additional claims here as needed 

            }; 

            // Convert the header and payload to Base64 

            var encodedHeader = GlideStringUtil.base64Encode(JSON.stringify(header)); 

            var encodedPayload = GlideStringUtil.base64Encode(JSON.stringify(payload)); 

            encodedHeader.GlideStringUtil.replace(/=+$/, ''); //strips out == padding  

            //encodedPayload.GlideStringUtil.replace(/=+$/, ''); 

            encodedPayload.replaceAll("(\=+$\)", ""); 

            gs.info("Payload: " + encodedPayload); 

            var newb64EncodedText = encodedPayload.replaceAll("(\=+$\)", ""); 

            gs.info("Java Payload: " + newb64EncodedText); 

                 

 
            // Create the signature 

            var key = gs.getProperty('grouper_dev_key');
			gs.info("Key is: " + key);

			var dataToSign = encodedHeader + "." + newb64EncodedText;

            var signature = GlideStringUtil.base64Encode( 

                GlideDigest.generate('SHA256', dataToSign, key) 

            ); 

 

            // Return the complete JWT 

            var jwtuser = 'jwtUser_OWVmNzE4M2M3MGU4NDNkYmEwNTdiYzk3N2Q2ZTRjZDM=_';

            return jwtuser + encodedHeader + "." + newb64EncodedText + "." + signature; 

        } catch (e) { 

            gs.error("Error generating JWT: " + e.message); 

            return null; 

        } 

    }, 

 
 

    type: 'JWTGenerator' 

}; 

 

 

Calling from a Background Script:

var jwtGen = new JWTGenerator(); 
var jwt = jwtGen.generateJWT(); 
gs.info("Generated JWT: " + jwt); 

 

Any assistance or ideas would be greatly appreciated.

 

Thank you.

7 REPLIES 7

SN Emy
Tera Guru

Hey,

Just checking in—any updates on this? How did you end up handling it?

Thanks,

scoburn1
Tera Contributor

Hey Emy,

 

A way was not found forward regarding the authentication piece - we're currently handling processes simply by sending the group in question information as part of a Request. 

If anyone has a successful example of integrating ServiceNow with Grouper, solutions are welcome.

Yes, I found a solution OOB and worked: https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0717946

This is an example on how to test it : 

// var bearerPrefix = "Bearer jwtUser_XXXX"; the grouper manager should provide you this
// var jwtAPI = new sn_auth.GlideJWTAPI();
// var headerJSON = { typ: "JWT", alg: "RS256"};
// var header = JSON.stringify(headerJSON);
// var gdt = new GlideDateTime();
// var iat = Math.floor(gs.nowDateTime().getNumericValue() / 1000);
// var exp = Math.floor(gdt.getNumericValue() / 1000);
// var payloadJSON = { "iat": iat, "exp": exp ,"iss": ""};

// //iss in line below needs to be changed if app id changes
// var payloadJSON = { "iat": gs.now(), "exp": gdt };
// var payload = JSON.stringify(payloadJSON);

// var jwtProviderSysId = "a9f2aad51bed62d0a359a9b5604bcbf8";
// var jwt = jwtAPI.generateJWT(jwtProviderSysId, header, payload);

// gs.info("JWT: " + bearerPrefix + jwt);
 
once ypu get the berear toekn, you can create a rest message to test other endpoints 

 

scoburn1
Tera Contributor

Thank you very much for the effort I will definitely take a look. Just a couple clarifying questions if possible on how you set it up with regards to the linked support article (https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0717946

For this step 2. Create a JWT Signing key and assign corresponding signing jks:
That Signing Key Password field would store the Grouper private key in this case?

For step 4. Create a 3rd party Oauth provider in Application Registry. Configure JWT Provider and Signing Keys in ServiceNow:
And just wanted to clarify which one here you decided to go with...as the self service jwt looks to necessitate the private key and user rather than the client ID/secret/token URL values the example provided

scoburn1_0-1748028918705.png

My last question pertains to the above I believe...did you choose 'no authorization' in your rest message screenshot? My understanding is that the user would be authorized as a result of the signing function of the GlideJWTAPI() script interacting with the private key in step 2 (and this is where I wasn't sure where the Box example of the oauth step came in).

Thank you again for your time.