Isn't Salesforce a CRM ? Why are talking about JWT with Salesforce ?
Exactly, Salesforce is a CRM and also a solid developer friendly and completely flexible platform which supports integration with almost any of 3rd party systems , database, applications.
Hmmmm ok .. Why JWT ? There are other authorization flows which can be used.
For other types of mainstream authorization flows such as Webserver flow, you need a user presence to authenticate.
Sometimes you want to authorize servers to access data without interactively logging in each time the servers exchange information.
For these cases, you can use the OAuth 2.0 JSON Web Token (JWT) bearer flow.
But How ?
Well, This flow uses a certificate to sign the JWT request and doesn’t require explicit user interaction.
However, this flow does require prior approval of the client app.
How does this work in a nutshell ?
The client(who ever is trying to access salesforce data) posts a JWT to the Salesforce OAuth token endpoint.
Salesforce then processes the JWT, which includes a digital signature, and issues the access token(As per prior approval of app).
OK! Lets look into a simple example between 2 Salesforce Orgs
OrgA with a Visualforce tab acting as Client App.
OrgB acting as target salesforce server from where we need to get authorized and fetch data.
I will refer these as OrgA and OrgB through out the post.
Lets take a look into our client application (which is a visualforce page tab)
When you hit Fetch JWT Token button on that page, You should expect an access token along with other parameters issued by a our salesforce OrgB (or) as highlighted "https://oceans11-dev-ed.my.salesforce.com"
Lets talk code now.
I will split the flow into 6 steps for simplicity.
- Create a JWT
- Create a Certificate and private key.
- Upload the Certificate in connected app of your target OrgB
- Upload the private key in Files of your Client OrgA
- Request for access token
- Salesforce Grants Access Token
1. Create a JWT
JWT is JSON Web Token. It consists of header and claims.
JWT header should look like this
{"alg":"RS256"}
alg - algorithm you are using
It firstly consists of claims, it should be of this format.
{
"iss": "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQ
ukXnVjzRgSuQqGn75NL7yfkQcyy7",
"sub": "my@email.com",
"aud": "https://login.salesforce.com",
"exp": "1333685628"
}
lets see what do we have here... These are called JWT Claims.
iss - OAuth client_id
sub - username of the target org you are connecting to
aud - url you would want to connect. if thats a sandbox then use test instead of login.
exp - time to expire the token.
You have to Base64url encode the JWT Header and the encoded JWT Claims Set separately without any line breaks.
Next, Create a string for the encoded JWT Header and the encoded JWT Claims Set in this format
Encoded JWT Header+ "." + Encoded JWT Claims
It would look something like this (before the dot(.) we have the header in encoded format )
eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZ1NjI4In0=
Please refer to generateJsonBody and combineJWTHeader_Claimset method for the logic using apex code provided in the Git Repo link at the end of this post.
Now we have the JWT claims & header , lets see step 2
2. Create a Certificate and private key.
This flow requires a digital certificate and the private key used to sign the certificate.
Please feel free to use your own private key and certificate issued by a certification authority.
Alternatively, you can use OpenSSL to create a key and a self-signed digital certificate.
Refer this on How to create a Digital Certificate
Once you have completed this step,
3. Upload the Certificate in connected app of your target OrgB
We would need to upload this digital certificate to the connected app in OrgB that is also required for the JWT bearer authorization flow.
4. Upload the private key in Files of your Client OrgA
and create the payload to access the token
As You already have the private key file which you obtained while creating the self signed open ssl certificate, we use it to sign the request
Since this is a salesforce org, I have uploaded it in a File and retrieved it using the ContentVersion object.
Sign the resulting string using RSA SHA256.
Create a string of the string from this step in the following format.
the combined JWT string + "." + base64_encoded_signature
See retrievePKContent and signPkey method from the Git repo link which
the base64 encoded signature should be something like this (I have clipped the content for keeping it small).
eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZ1NjI4In0=.iYCthqWCQucwi35yFs-nWNgpF5NA_a46fXDTNIY8ACko6BaEtQ9E6h4Hn1l_pcwcK
I_GlmfUO2dJDg1A610t09TeoPagJsZDm_H83bsoZUoI8LpAA1s-2a
36y2L2Bh7M8TNWiKa_BNM6s1FNKDAwHEWQrNtAeReXgRy0MZgQY2rZtqT2FcDyjY3JVQb
En_CSjH2WV7ZlUwsKHqGfI7hzeEvVdfOjH9NuaJozxvhPF489IgW6cntPuT2V647JWi7ng
5. Request for Access Token.
Next, Once you have the entire base64encoded string , make a callout to the token endpoint of the target org ORGB in this case.
the endpoint should look like this
https://login.salesforce.com/services/oauth2/token?grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion='+YOUR-ENTIRE-JWT-VALUE STRING YOU PREPARED '
This should be a POST call.
6. Salesforce grants access token.
once done, if everything is place correctly, You should see a response with access token.
If we see the Visualforce page above, that gives you the below result.
If you observe the image, I got the access token, I can see all the scopes and the id corresponds to the user id and org id
and the token type which is bearer.
Using this token you can easily access the data of the Target OrgB
Please find the complete code in GIT Link HERE
Please do not commit any changes to main
Hope this post helps someone who is trying to understand the JWT with salesforce or is trying to implement it.
See you again with a new post.
Top comments (0)