OAuth 2.0 JWT Bearer Flow for Server-to-Server Integration
In a server-to-server integration, there is no need for an user to interactively log in to provide authorization. In this case OAuth 2.0 JSON Web Token (JWT) bearer flow can provide the authorization.
Communities support all available authentication flows, except for the username-password OAuth authentication flow and the SAML assertion flow (https://help.salesforce.com/articleView?id=networks_auth_configure_oauth.htm&type=0)
Hence , we can use a flow like web server or user agent flow or use JWT flow. (https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&type=0)
When we talk about JSON Web Token, it is consist of 3 parts
Headers – Which contains the algorithm which will be used to sign the request
Payload – The actual data and information about the users
Signature – Signature consists of 3 parts and the structure is given below.
Payload consist of 4 parts
issuer "iss", this is the consumer key for your connected app
audience "aud", this is always
https://login.salesforce.comfor production, orhttps://test.salesforce.comfor sandboxes (or whatever your Salesforce community url is, if you have one)subject "sub", this is the username (user@yourcompany.tld) of the user you want to execute requests as
expiration "exp", this is the expiration time of the JWT itself, and provides a way to tolerate differences in client & server time. 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
We are going to do this from within Salesforce and in this case we can use Salesforce JWT class (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_class_Auth_JWT.htm#apex_class_Auth_JWT).
We need to specify aud, iss, sub , exp and rest of thing will take care by the JWT Auth class.
jwt.setAud(aud);
jwt.setIss(iss);
jwt.setSub(sub);
// Expiration time of the JWT itself
// Best to make this a long instead of an int
//The validity must be the expiration time of the assertion within 3 minutes,
//expressed as the number of seconds from 1970-01-01T0:0:0Z measured in UTC.
Long exp = DateTime.now().addMinutes(5).getTime();
System.debug('>>>> ' + exp);
jwt.setValidityLength(Integer.valueof(exp));
// Storing the certificate in Salesforce is a requirement for using the JWS class
Auth.JWS jws = new Auth.JWS(jwt, 'Name of the Certificate');
String tokenEndpoint = 'https://bolt.salesforce.com/services/oauth2/token';
Auth.JWTBearerTokenExchange bearer = new Auth.JWTBearerTokenExchange(tokenEndpoint, jws);
String accessToken = bearer.getAccessToken();
System.debug(' Token ' + accessToken);
Steps to create a Self-Signed Certificate.
Step 1 : The self-signed certificate
Go to Setup | Security | Certificate and Key Management | Create Self-Signed Certificate, define a label, a unique name,check Exportable Private Key and click on save.
Then open the newly created certificate and click on Download Certificate to download it.
Step 2 : The Connected App
Go to Setup | Apps | App Manager | New Connected App and check Use digital signature to upload the certificated you downloaded at step 1.
Fill all the other required information to create the connected app and don’t forget to allow community user profiles to access it and set the policy to Admin approved users are pre-authorized. Then copy the Consumer Secret, we’ll need it later.
Set Oauth scopes as needed.
Click on Manage to set the policy and select the profiles. At the end make sure API Enabled check box is checked on the profile.
Step 3 : The JWT token
The last step is about getting an access token that authenticate the connected community/standard user. To do so, we’ll use the OAuth 2.0 JWT Bearer Token Flow. JWT flow is a server to server authentication flow. Use the private key to sign the json and post the JWT to the OAuth token endpoint, which in turn processes the JWT and issues an access_token (but no refresh_token).
We can use a query the username based on the user id otherwise we can store username in config/metedata to retrieve it. Then use the method below to get an access token. You’ll need to update siteBase and consumerKey parameters.
Sample code -
public static String getAccessToken(String username){
String siteBase = 'https://***.force.com';
String consumerKey = '3MV..***..0Ln8ievjdl';
Auth.JWT jwt = new Auth.JWT();
jwt.setSub(username);
jwt.setIss(consumerKey);
jwt.setAud(siteBase);
Auth.JWS jws = new Auth.JWS(jwt, 'B2BeCommerceCert');
String tokenEndpoint = siteBase+'/services/oauth2/token';
Auth.JWTBearerTokenExchange bearer = new
Auth.JWTBearerTokenExchange(tokenEndpoint, jws);
String accessToken = bearer.getAccessToken();
return accessToken;
}
}
As the logged-in community user, we can now perform apex DML actions (and not simply as the integration user).





Comments
Post a Comment