Set up the JWT bearer OAuth flow for Salesforce - Amazon Glue
Services or capabilities described in Amazon Web Services documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with Amazon Web Services in China (PDF).

Set up the JWT bearer OAuth flow for Salesforce

Refer to Salesforce public documentation for enabling server-to-server integration with OAuth 2.0 JSON Web Tokens.

Creating a cert/key pair of PEM files

Create a cert/key pair of PEM files

openssl req -newkey rsa:4096 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem

Creating a Salesforce connected app with JWT

  1. Log in to Salesforce and click the settings gear at top right and select Setup.

  2. On the left, navigate to App Manager. (Platform Tools > Apps > App Manager)

  3. Choose New Connection App.

  4. Provide an app name, let the rest be auto filled.

  5. Check the box for Enable OAuth Settings.

  6. Set a callback URL. It won’t be used for JWT, so you can use https://localhost.

  7. Check the box for Use Digital Signatures.

  8. Upload the cert.pem file created earlier.

  9. Add the required permissions:

    1. Manage user data via APIs (api).

    2. Access custom permissions (custom_permissions).

    3. Access the identity URL service (id, profile, email, address, phone).

    4. Access unique user identifiers (openid).

    5. Perform requests at any time (refresh_token, offline_access).

  10. Check the box for Issue JSON Web Token (JWT)-based access tokens for named users.

  11. Choose Save.

  12. Choose Continue.

  13. Choose Manage Consumer Details.

  14. Copy the consumer key (client id).

  15. Copy the consumer secret (client secret).

  16. Click Cancel.

Generating a JSON Web Token (JWT)

  1. Convert key pair into pkcs12 (set an export password when prompted).

    openssl pkcs12 -export -in cert.pem -inkey key.pem -name jwtcert > jwtcert.p12
  2. Create a Java keystore from pkcs12 (set a destination keystore password when prompted, and provide previous export password for source keystore password).

    keytool -importkeystore -srckeystore jwtcert.p12 -destkeystore keystore.jks -srcstoretype pkcs12 -alias jwtcert
  3. Confirm keystore.jks includes jwtcert alias (enter previous destination keystore password when prompted).

    keytool -keystore keystore.jks -list
  4. Use the Java class JWTExample provided in Salesforce documentation to generate the signed token.

    1. Edit the values in claimArray as necessary:

      • claimArray[0] = client id

      • claimArray[1] = salesforce user id

      • claimArray[2] = salesforce login url

      • claimArray[4] = expiration date in millis since epoch. 3660624000000 is 2085-12-31.

    2. Replace path/to/keystore with correct path to your keystore.jks.

    3. Replace keystorepassword with the destination keystore password you entered

    4. Replace privatekeypassword with the source keystore password you entered

    5. Compile the code. The code depends on the Apache Commons Codec for base64 encoding.

      javac -classpath ".:./commons-codec-1.16.1.jar" JWTExample.java
    6. Run the code.

      java -classpath ".:commons-codec-1.16.1.jar" JWTExample
  5. Once the connected app and JWT are created, still the user needs to be authorized for the app. See step 3 in https://mannharleen.github.io/2020-03-03-salesforce-jwt/ for two approaches.

With the above steps completed, this should output a JSON Web Token (JWT) which can be used to obtain access tokens from Salesforce.

Example input:

export password for pkcs12: awsglue destination keystore password for jks: awsglue source keystore password for jks: awsglue claimArray[0] = “client-id”; claimArray[1] = “my@email.com”; claimArray[2] = "https://login.salesforce.com“; claimArray[3] = "3660624000000"; path to keystore: ./keystore.jks keystore password: awsglue privatekey password: awsglue

Example output:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.signature

Useful links:

  • https://www.base64encode.org/

  • https://jwt.io/

  • https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_jwt_flow.htm

JWTExample.java:

import org.apache.commons.codec.binary.Base64; import java.io.*; import java.security.*; import java.text.MessageFormat; public class JWTExample { public static void main(String[] args) { String header = "{\"alg\":\"RS256\"}"; String claimTemplate = "'{'\"iss\": \"{0}\", \"sub\": \"{1}\", \"aud\": \"{2}\", \"exp\": \"{3}\"'}'"; try { StringBuffer token = new StringBuffer(); //Encode the JWT Header and add it to our string to sign token.append(Base64.encodeBase64URLSafeString(header.getBytes("UTF-8"))); //Separate with a period token.append("."); //Create the JWT Claims Object String[] claimArray = new String[5]; claimArray[0] = "value"; claimArray[1] = "my@email.com"; claimArray[2] = "https://login.salesforce.com"; claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300); MessageFormat claims; claims = new MessageFormat(claimTemplate); String payload = claims.format(claimArray); //Add the encoded claims object token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8"))); //Load the private key from a keystore KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream("./keystore.jks"), "awsglue".toCharArray()); PrivateKey privateKey = (PrivateKey) keystore.getKey("jwtcert", "awsglue".toCharArray()); //Sign the JWT Header + "." + JWT Claims Object Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(token.toString().getBytes("UTF-8")); String signedPayload = Base64.encodeBase64URLSafeString(signature.sign()); //Separate with a period token.append("."); //Add the encoded signature token.append(signedPayload); System.out.println(token.toString()); } catch (Exception e) { e.printStackTrace(); } } }