Table of Contents [expand]
Last updated December 05, 2025
Heroku AppLink supports JWT (JSON Web Token) authorization using JWT Bearer Token Flow for headless authentication in CI/CD pipelines and automated workflows. JWT authorization eliminates the need for interactive browser-based OAuth flows. Authorizations with AppLink requires a Salesforce connected app that’s configured with certificate-based authentication.
For more information on Heroku AppLink authorizations, see Working with Heroku AppLink.
Prerequisites
Before authorizing a user, you must:
Generate an RSA Key Pair
You need an RSA private key and self-signed certificate to use for the authorization command. To generate, run:
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt -days 365 -nodes
You also need a public key to upload for your connected app:
openssl x509 -pubkey -noout -in server.crt > server.pub
Create a Connected App
Next, create and configure a connected app in Salesforce. Follow the Salesforce documentation to:
- Create a connected app
- Select
Enable OAuth Settings - Select
Use Digital Signaturesand upload your public key file - Set the
Callback URLtohttp://localhost:1717/OauthRedirect - Select the OAuth scopes for your connected app. At minimum, set the
apiandrefresh_tokenscopes.
Pre-Authorize Users
Then, pre-authorize the users who can use the connected app. You must add the user you want to authorize AppLink with. Follow the Salesforce documentation to:
- Select
Admin approved users are pre-authorizedin thePermitted Usersdropdown. - Select specific profiles or permission sets to give access to your connected app.
Authorize Users on Heroku AppLink
You need the following to authorize a user:
client-id: The consumer key from your connected app. This client ID must match the key used to generate the JWT private key.jwt-key-file: The RSA private key you previously generated.username: Must be a user in the org and who has been pre-authorized for the connected app.
To authorize a Salesforce user via JWT, run the command:
$ heroku salesforce:authorizations:add:jwt org_jwt --addon applink-simple-60625 -a example-app --client-id 3MVG9N7GK6... --jwt-key-file jwt/server.key --username test-user@example.com --login https://test.salesforce.com
Adding credentials for test-user@example.com to example-app as org_jwt... Connected
To authorize a Data Cloud user via JWT, run the command:
$ heroku datacloud:authorizations:add:jwt dc_jwt --addon applink-simple-60625 -a example-app --client-id 3MVG9N7GK6... --jwt-key-file jwt/server.key --username test-user@example.com --login https://test.salesforce.com
Adding credentials for test-user@example.com to example-app as dc_jwt... Connected
Use the Authorization In Your App
After authorizing, your app can retrieve credentials using the AppLink SDKs. For example with the Node.js AppLink SDK for Salesforce:
const Applink = require('@heroku/applink');
const applink = new Applink();
// Retrieve authorization by developer name
const auth = await applink.getAuthorization('my-auth');
console.log('Access Token:', auth.access_token);
console.log('Instance URL:', auth.instance_url);
// Or retrieve by alias
const authByAlias = await applink.getAuthorizationByAlias('applink:my-auth');
CI/CD Integration Examples
Here are some examples of using your authorizationsin CI/CD integrations.
GitHub Actions
name: Deploy with AppLink JWT
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Heroku CLI
run: |
curl https://cli-assets.heroku.com/install.sh | sh
heroku plugins:install @heroku-cli/plugin-applink
- name: Add JWT Authorization
env:
HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
JWT_PRIVATE_KEY: ${{ secrets.JWT_PRIVATE_KEY }}
SF_CLIENT_ID: ${{ secrets.SF_CLIENT_ID }}
SF_USERNAME: ${{ secrets.SF_USERNAME }}
run: |
echo "$JWT_PRIVATE_KEY" > /tmp/jwt.key
heroku salesforce:authorizations:add:jwt ci-auth \
--app my-app \
--client-id $SF_CLIENT_ID \
--jwt-key-file /tmp/jwt.key \
--username $SF_USERNAME
rm /tmp/jwt.key
- name: Deploy to Heroku
run: git push heroku main
CircleCI
version: 2.1
jobs:
deploy:
docker:
- image: cimg/base:stable
steps:
- checkout
- run:
name: Setup Heroku
command: |
curl https://cli-assets.heroku.com/install.sh | sh
heroku plugins:install @heroku-cli/plugin-applink
- run:
name: Add JWT Authorization
command: |
echo "$JWT_PRIVATE_KEY" > /tmp/jwt.key
heroku salesforce:authorizations:add:jwt ci-auth \
--app $HEROKU_APP_NAME \
--client-id $SF_CLIENT_ID \
--jwt-key-file /tmp/jwt.key \
--username $SF_USERNAME
rm /tmp/jwt.key
workflows:
deploy:
jobs:
- deploy:
context: production
Security Best Practices
Here are some best practices to keep in mind:
- Key Rotation: Rotate JWT key pairs regularly, for example, every 90 days.
- Key Storage: Store private keys securely in secret managers such as GitHub Secrets, AWS Secrets Manager, etc.
- Access Control: Use dedicated service accounts with minimal required permissions.
- Audit Logging: Monitor authorization usage in Salesforce Setup > Login History.
- Key Protection: Never commit private keys to version control (add
*.keyto.gitignore).