This articles explains how can we authenticate in Box.com using JWT OAuth 2.0. Here is the API details in Box API documentation: https://developer.box.com/guides/authentication/jwt/without-sdk/
Box – Prerequisites
- Box access with Admin privileges
- Create custom app in Box. While creating the custom app select “OAuth 2.0 with JWT (Server Authentication)” as Authentication Method
- Authorize app by Admin:
- Goto Admin Console –> Apps –> Custom Apps –> click Authorize new app
- Paste the Client Id of app and submit
- Goto App –> Copy the Client Id, Client Secret, Enterprise Id. It will be used in Salesforce.
Salesforce – Prerequisites
- Create self signed certificate with size 2048: https://help.salesforce.com/apex/HTViewHelpDoc?id=security_keys_creating.htm
- Export the key. It will download the public key in your system.
- Open the key in any editor and copy it.
- Goto Box.com –> open the App –> configuration –> there should be an option to add Public key. Just paste the key coped from previous step
Apex Code
A). In following implementation, we are not using standard JWT and JWS because it throws error “Signature verification error. The public key identified by \”kid\” must correspond to the private key used for signing.” So decided to do it using by our own.
B). Datetime.now does not produce correct UNIX time and it throws error: “Please check the ‘exp’ claim.” So, JWT class is used to just generate the exp parameter.
C). Unlike other JWT implementation, Box requires Client Secret in Parameter
public class BoxAuthenticationUsingJWT{ public static void connectWithBox(){ //replace with your app client id String clientId = '6651wi15q83qvav53jznsgdswuxxxxxx'; //replace with your app client secret String clientSecret = '1DTfOrIQF0M2YxSKmKmk9jY5abxxxxxx'; String endpoint = 'https://api.box.com/oauth2/token'; String iss = clientId; String aud = endpoint; String sub = '334200xxx'; //replace Enterprise Id //Long exp = DateTime.now().addhours(-8).addSeconds(30).getTime(); // Datetime.now is returning fiff time than what need JWT token Auth.Jwt jwt = new Auth.Jwt(); jwt.setValidityLength(60); String jwtRequestd = jwt.toJSONString(); Map<String, Object> m = (Map<String, Object>)JSON.deserializeUntyped(jwtRequestd); Long exp = (Long)m.get('exp'); system.debug(jwtRequestd); system.debug(jwt.getValidityLength()); // Start constructing the header and claims String jwtHeader = '{"typ":"JWT","alg":"RS256"}'; String jwtClaims = '{"iss":"' + iss +'","jti":"'+UserInfo.getUserID()+'","box_sub_type":"enterprise","sub":"' + sub + '","aud":"' + aud + '","exp":' + exp + '}'; system.debug(jwtClaims); String jwtRequest = System.encodingUtil.base64Encode(Blob.valueOf(jwtHeader)).replace('+', '-').replace('/', '_') + '.' + System.encodingUtil.base64Encode(Blob.valueOf(jwtClaims)).replace('+', '-').replace('/', '_'); String signature = System.encodingUtil.base64Encode(Crypto.signWithCertificate('RSA-SHA256', Blob.valueOf(jwtRequest), 'jwt')).replace('+', '-').replace('/', '_'); String signedJwtRequest = jwtRequest + '.' + signature; // The JWT is fully constructed, now it's time to make the call to get the access token. String payload = 'grant_type=' + System.EncodingUtil.urlEncode('urn:ietf:params:oauth:grant-type:jwt-bearer', 'UTF-8'); payload += '&client_id='+clientId+'&client_secret='+clientSecret; payload += '&assertion=' + signedJwtRequest; Http httpObj = new Http(); HttpRequest req = new HttpRequest(); HttpResponse res; req.setEndpoint(endpoint); req.setMethod('POST'); req.setHeader('Content-Type', 'application/x-www-form-urlencoded'); req.setBody(payload); res = httpObj.send(req); System.debug(res.getBody()); } }
Run below line in developer console to test it:
BoxAuthenticationUsingJWT.connectWithBox();
Here is Github repo link
I blog often and I truly appreciate your information. Your article has truly peaked my interest.
I will book mark your blog and keep checking for new details about once
per week. I opted in for your RSS feed too.
asmr 0mniartist