Skip Navigation
Show nav
Heroku Dev Center Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
Heroku Dev Center Dev Center
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log in or Sign up
View categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Buildpacks
    • Platform Principles
  • Developer Tools
    • AI Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Node.js Behavior in Heroku
      • Working with Node.js
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails Support
        • Working with Rails
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Inference Essentials
    • Inference API
    • Inference Quick Start Guides
    • AI Models
    • Tool Use
    • AI Integrations
    • Vector Database
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
    • Heroku AppLink
      • Working with Heroku AppLink
      • Heroku AppLink Reference
      • Getting Started with Heroku AppLink
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Other Salesforce Integrations
  • Integrating with Salesforce
  • Heroku AppLink
  • Working with Heroku AppLink
  • JWT Authorizations with Heroku AppLink

JWT Authorizations with Heroku AppLink

Table of Contents [expand]

  • Prerequisites
  • Authorize Users on Heroku AppLink
  • Use the Authorization In Your App
  • Security Best Practices
  • Additional Reading

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
  • Create a Connected App
  • Pre-authorized Users

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 Signatures and upload your public key file
  • Set the Callback URL to http://localhost:1717/OauthRedirect
  • Select the OAuth scopes for your connected app. At minimum, set the api and refresh_token scopes.

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-authorized in the Permitted Users dropdown.
  • 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 *.key to .gitignore).

Additional Reading

  • Heroku AppLink
  • Salesforce JWT Bearer Token Flow

Feedback

Log in to submit feedback.

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices