Outsiders Republic

Music. Food. Travel. Tech.

Server-to-Server Authentication with Salesforce

Kevin
Server-to-Server Authentication with Salesforce

This post will help you understand how to integrate a server with the Salesforce API. We will use the OAuth 2.0 JSON Web Token (JWT) bearer flow for this use case. This authorization flow uses a private key to sign an authorization token and requires you to approve the API client (i.e., your server) in Salesforce. Once configured, no direct user interaction will be needed for your server to make API calls to Salesforce. Your custom application is referred to as a “Connected App” in Salesforce parlance.

Sometimes you want to authorize servers to access data without interactively logging in each time the servers exchange information.

Salesforce Docs

Summary Steps

  1. Create a key pair and certificate identifying your custom application
  2. Create a Connected App in Salesforce
  3. Pre-authorize access for “permitted users” to the Connected App
  4. Update a user profile to associate it with the Connected App
  5. Generate and sign an assertion token (JWT)
  6. Make an HTTP POST request to Salesforce with the assertion token to create an access token
  7. Salesforce will issue the access token and respond to the HTTP request
  8. Make HTTP requests to the Salesforce API using the access token

Create a Certificate and Private Key

We’ll use OpenSSL to create an x509 certificate and a private key for the Connected App. Run the following commands in your terminal to create key and certificate files.

# generate a private key with the correct length
openssl genrsa -out private-key.pem 3072
# generate a corresponding public key
openssl rsa -in private-key.pem -pubout -out public-key.pem
# create a self-signed certificate
openssl req -new -x509 -key private-key.pem -out cert.pem -days 360

Configure Salesforce

Create a Connected App

  1. Login to your Salesforce developer account as an administrator
  2. Enter “app manager” in the Quick Find box
  3. Click the item Apps -> App Manager
  4. Click the New Connected App button
  5. Enter the following:
    • Connected App Name, e.g., My App
    • API Name (should autocomplete to My_App, or similar)
    • Contact Email
    • Check “Enable OAuth Settings”
    • Callback URL, e.g., http://localhost/callback (this value doesn’t really matter for this scenario, and, in fact, it’s not used, but Salesforce requires it anyway)
    • Check “Use digital signatures”
    • Click the Browse button to upload cert.pem (this is the x509 certificate you created in a previous step)
    • Add the following to Selected OAuth Scopes:
      • Access and manage your data (api)
      • Perform requests on your behalf at any time (refresh_token, offline_access)
  6. Click Save
  7. Click Continue
  8. Now would be a good time to Copy the Consumer Key for the connected app and save it. We’ll need it later.

Pre-authorize Access

  1. Enter “manage connected apps” in the Quick Find box
  2. Click the item Apps -> Connected Apps -> Manage Connected Apps
  3. Click the Edit action beside your new connected app
  4. Select Admin approved users are pre-authorized from Permitted Users
  5. Click Save

Update a User Profile

  1. Enter “profiles” in the Quick Find box
  2. Click the item Users -> Profiles
  3. Click Edit beside Standard Platform User
  4. Scroll down to Connected App Access
  5. Check the checkbox beside your new connected app, e.g. “A Demo App”
  6. Click Save

Create an Authorization Token

In our scenario, an authorization token is simply a JWT configured with the appropriate claims and signed with the private key we created in a previous step. There are many libraries available for a wide variety of programming languages that make it easier to use JWTs in your application. However, for this post, we will use an online tool to configure our JWT.

Claims

Now is a good time to collect the claims information that Salesforce expects before configuring our JWT.

  • Issuer: the Salesforce connected app consumer key you copied in an earlier step
  • Subject: any username with the Standard Platform User profile
  • Audience: https://login.salesforce.com
  • Expiration timestamp: the current time + 10 minutes, in UNIX epoch format

You can generate an expiration timestamp on Linux or macOS in your terminal with the following shell command:

# Print current time + 600 seconds
echo "$(date +%s) + 600" | bc

Encode a JWT

  1. Go to https://jwt.io in a new browser tab
  2. Scroll down to Debugger
  3. Select RS256 in the Algorithm dropdown
  4. (we will make our edits in the Decoded section)
  5. Confirm Header values
    • "alg": "RS256"
    • "typ": "JWT"
  6. Configure Payload
    • "iss": "<connected app consumer key>"
    • "sub": <salesforce username, usually in email format>
    • "aud": "https://login.salesforce.com"
    • "exp": <timestamp>
  7. Verify Signature
    • Open the cert.pem file in a text editor, copy the entire text, and paste it into the first box
    • Open the private-key.pem file in a text editor, copy the entire text and paste it into the second box
    • Confirm that “Signature Verified” is shown at the bottom of the debugger. If you see “Invalid Signature” instead, there is a problem with your certificate or private key.
  8. Copy the JWT from the Encoded section–we’ll need it in a moment.

Request Access Token

Finally, we’ll use curl to request an access token. Head back to your terminal and run the following commands.

# Set JWT environment variable to your JWT
# Example:
# $ JWT='eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzTVZHOXN6VmEyUn...'
JWT='<paste your JWT here>'
GRANT_TYPE='urn:ietf:params:oauth:grant-type:jwt-bearer'
SFDC='https://login.salesforce.com/services/oauth2/token'
curl -d "assertion=$JWT&grant_type=$GRANT_TYPE" -X POST $SFDC

If everything is configured properly, you should receive a response like this…

{"access_token":"00D410000012VvK!AQIAQKMzbJitdk15IQEFeDf85vZdFTDUeAEl2j2FSV2wLeOwfJY9TfRQYxtqRUalEzs8.hMQspkLjVOxgq5TcXGD8VCzkHZL","scope":"api","instance_url":"https://<tenant>-dev-ed.my.salesforce.com","id":"https://login.salesforce.com/id/00D410000012VvKEAU/005410000058zUdAAI","token_type":"Bearer"}

You can now use the access token to call the Salesforce API!!!



Categories: Tech

4 thoughts on “Server-to-Server Authentication with Salesforce”

  • Amazingly clear instructions, there is only one error: “iss” should be “consumer key” not “consumer secret”

  • These are great instructions, thank you!
    Noticed one small typo. When using jwt.io, I had to paste the public-key.pem into first box instead of cert.pem . Using cert.pem signature showed invalid

  • The response includes ‘id’ token which most likely is the row id of the signed in salesforce user which later can be used with ‘id_token’ Identify URL to access additional details about the user. The question is where are you associating this user in the authorization request?. Is this retrieved from the Admin Approved Users on the Connected App?. Further when the Authorization arrives in Salesforce, the connected App retrieves the very first user from the Provisioned list and uses his user record to generate the access token?. Thank you

Leave a Comment

Your email address will not be published. Required fields are marked *