Lately I’ve been playing around with Azure and integrating Salesforce and Azure. One of the integration patterns calls for using Json Web Tokens (JWT) that you can the exchange for an access token in Azure. There is a catch however…
Since Azure requires that the thumbprint of the certificate be added to the header of the JWT (using the key “x5t”) we cannot use the built in support for JWT in Named Credentials as there are no provisions for custom header key/values. The JTW/JWS classes in Apex cannot be used either as we cannot customize the header there either. Building upon https://github.com/salesforceidentity/jwt I’ve created https://github.com/lekkimworld/azurejwt-apex that bridges the gap.
This allows you to build and sign a JWT that you may exchange for an access token using your tenants OAuth token endpoint v.2 in Azure. Example Apex code is like this:
// declarations (because I'm old school) final String azureClientId = '88d888a5-0cf4-473a-b9a0-7c88e6fc888e'; final String azureTenantId = 'b34feb2b-132f-4322-af1d-c888f5d888d0'; final String azureCertThumbprint = '4rElsDFTysrbKhB0zTsrRNSxT6s='; final String azureScopes = '5384888d-868f-442b-b1b3-8688807de914/.default'; // create JWT with certificate from keys mgmt and set the x5t in the header to the // thumbprint of the cert as expected by Azure AzureJWT jwt = new AzureJWT(); jwt.cert = 'JWT_Callout_Certificate'; jwt.iss = azureClientId; jwt.sub = azureClientId; jwt.aud = 'https://login.microsoftonline.com/' + azureTenantId + '/oauth2/v2.0/token'; jwt.x5t = azureCertThumbprint; // invoke the flow and obtain an access_token final String access_token = AzureJWTBearerFlow.getAccessToken(azureClientId, azureTenantId, azureScopes, jwt); // use the access token against a Function App in Azure HttpRequest req = new HttpRequest(); req.setEndpoint('https://foo-functions-demo.azurewebsites.net/api/MyFunction?name=Salesforce'); req.setMethod('GET'); req.setHeader('Authorization', 'Bearer ' + access_token); Http http = new Http(); HTTPResponse res = http.send(req); System.debug(res.getBody());
In the https://github.com/lekkimworld/azurejwt-apex Github repo you will find the two Apex classes from the above example together with the example code.
The certificate thumbprint (bold above) isn’t the regular SHA-1 thumbprint but is a special hexdump/base64 encoded edition. To make it even more interesting the thumbprint displayed in Azure Portal is not the thumbprint we need. The thumbprint/hash may be computed this like (gleaned from https://stackoverflow.com/a/52625165):
echo $(openssl x509 -in yourcert.pem -fingerprint -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64