Salesforce - JWT Bearer Flow for Authentication
Hello Trailblazers,
In this blog we are going to focus on OAuth 2.0 JWT Bearer Flow for Server-to-Server Integration. JWT Bearer Flow is used for server to server communication and to avoid logging in each time.
JWT Bearer Token is something that you provide to some other service to let that service authenticate you. 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. Which means you need to allow access first for the connected app by using some third-party authorization app.
So, we can consider JWT as a key which gives us access to various things.
Pre-requisites for JWT(JSON Web Token) Bearer Flow
- X509 certificate
- Connected App
X509 certificate
Since we will be signing JWT using RSA SHA256, we need certificate as a secret for signing data. You can download certificate from Salesforce or you can use openssl for generating certificate using below steps.
You need to install openSSL first in your system from here.
- Once you are done with installation, navigate to directory where you want to store certificate and key files.
- Execute below commands in command prompt/terminal and enter required data whenever prompted.
- After successful execution of above commands, you will see 3 files created in your directory – csr.pem, key.pem, server.crt
CSR is Certificate Signing Request, which you need to create Certificate, this file contains details which you have entered and a public key. - We will use server.crt in Salesforce connected app. And you will need to share all files with third party who is going to access Salesforce resources with this connection.
openssl req -newkey rsa:2048 -new -nodes -keyout key.pem -out csr.pem
openssl x509 -req -days 365 -in csr.pem -signkey key.pem -out server.crt
Connected App
- Create new Salesforce connected app from Setup > Apps > New Connected App
- Enter Name, Email and other required details.
- Under API (Enable OAuth Settings) section
- Check Enable OAuth Settings
- Check Use digital signatures. Here you will see option to upload certificate. While using JWT flow there is no significance of Client Secret as we use certificates. Upload certificate here that we generated earlier.
- The permissions (Oauth scopes) that your connected app requires for the JWT Bearer flow to work are:
- Access and manage your data (api)
- Perform requests on your behalf at any time (refresh_token, offline_access)
- Keep rest of the settings as it is.
- Save. Your app will look like below :
Now we are done with the configuration that is required at Salesforce end. Now all things need to be done at third party from where we are going to initiate the request.
Steps that are involved in this flow are:
- Create a JWT
- Request Access Token
- Salesforce Grants Access Token
- Access Protected Data
Create a JWT
Salesforce requires that a JWT is signed using RSA SHA256, which uses an uploaded certificate as the signing secret. So certificate that we have uploaded to connected app will be used for signing JWT.
Let’s understand how to construct JWT-
- JWT header
{"alg":"RS256"} - Base64url encode the JWT header as defined in http://tools.ietf.org/html/rfc4648#page-7.
End result should be
"eyJhbGciOiJSUzI1NiJ9" - Construct a JSON Claims Set for the JWT with the following parameters:
- iss : This is the consumer key of your connected app
- aud : This is url of your environment which is https://login.salesforce.com for Production and Developer org, https://test.salesforce.com for Sandbox org, https://community.force.com/customers if implementing for a community.
- sub : This should contain username of user you want to execute request as.
- exp : This is the unix timestamp (seconds or milliseconds since unix epoch) + a little more time to allow for the JWT to make it to Salesforce. Really, any timestamp 1 minute or more in the future should work fine here. It has nothing to do with how long the access token is valid for.
- Now we need to encode this claims set using base64 encode. But keep in mind one thing that while encoding you must remove line breaks for claims set if there are any.
Final value should look like this
EyJpc3MiOiAiM01WRzlaTDBwcEdQNVVyQTZ6eS5FdVlfV1BXYk5YaDJ0Yk11dVpIX3RCa09yYzgzRm5nSGRTZWNQNDlUcloxVU93c3JFOWc5eHQwVTlTF9DYVpNQyIsInN1YiI6ICJtYW5pc2hAcHNsLmNvbSIsImF1ZCIICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwiZXhwIjogIjE1OTQ3MDcwNTQzNDUifQ== - Create a String using Encode JWT Header and claims set as below
"ENCODED_JWT_HEADER"+ . +"ENCODED_JWT_CLAIMS_SET"
So string will be like
EyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzlaTDBwcEdQNVVyQTZ6eS5FdVlfV1BXYk5YaDJ0Yk11dVpIX3RCa09yYzgzRm5nSGRTZWNQNDlUcloxVU93c3JFOWc5eHQwVTlTF9DYVpNQyIsInN1YiI6ICJtYW5pc2hAcHNsLmNvbSIsImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwiZXhwIjogIjE1OTQ3MDcwNTQzNDUifQ== - Sign the resulting string using SHA256 with RSA. And key which was shared with certificate should be used for signing.
Use data which is between -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----.
Also remove all line breaks. - Now create final string as
"ENCODED_JWT_HEADER"+.+"ENCODED_JWT_CLAIMS_SET"+.+"RESULTING_STRING_FROM_ABOVE_STEP"
This is what we call assertion.
So JSON Claims Set will look like
{
"iss":"3MVG9ZL0ppGP5UrA6zy.EuY_WPWbNXh2tbMuuZH_tBkOrc83FngHdSecP49Tr
Z1UOwsrE9g9xt0U5eL_CaZMC",
"sub": "SALESFORCE_USERNAME", //enter your username here
"aud": "https://login.salesforce.com",
"exp": "1333685628"
}
Apex and JAVA code examples for this process can be found here.
So our JWT is ready for request. But before going to request for access token, you need to self-authorize for connected app using some third party authorizer like https://oauthdebugger.com/
On oauthdebugger enter required details and select Response Type as Code and Response Mode as quey.
If you do not follow this step you’ll get response while generating token as
{
"error": "invalid_grant",
"error_description": "user hasn't approved this consumer"
}
Request Access Token
Since JWT is ready with us, we’ll have to make POST call to Salesforce token request endpoint with below details.
Endpoint: https://login.salesforce.com/services/oauth2/token (as per Org type)
Method: POST
Header: Content-Type: application/x-www-form-urlencoded
Params:
grant_type : urn:ietf:params:oauth:grant-type:jwt-bearer
assertion : STRING_CREATED_IN_STEP_7_ABOVE
Salesforce Grants Access Token
And if everything goes well, you’ll get response like below:
{
"access_token": "00D1s0000008aW8!ARoAQNNX5kYRdxJwNNgBA99D6m2gGapNuTMmpsjot4w4MfEBRBAUoNisPbid13jXN.Ews_.Wls3o4zvXTL03Wpd7b4GGPmo8",
"scope": "api",
"instance_url": "https://ap15.salesforce.com",
"id": "https://login.salesforce.com/id/00D1s0000008aW8EAI/0051s000000afzyAAA",
"token_type": "Bearer"
}
And this access token received here can be used for subsequent calls.
Hope you all have understood the JWT Bearer Flow Authentication and how to implement it, do let me know in comments.
Comments
Post a Comment