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
    • Platform Principles
    • Buildpacks
  • 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
      • Working with PHP
      • PHP Behavior in Heroku
    • 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
      • Heroku AppLink Reference
      • Getting Started with Heroku AppLink
      • Working 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 April 30, 2026

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 require a Salesforce external client app that’s configured with certificate-based authentication.

For more information on Heroku AppLink authorizations, see Working with Heroku AppLink.

As of the Salesforce Spring ’26 release, you can no longer create new connected apps in Salesforce. We’re deprecating using connected apps with Heroku AppLink, and replacing them with external client apps. From now on, create and use external client apps instead of connected apps with your Heroku AppLink integrations. If you have existing connected apps in your Salesforce org, you can still reference them in the API spec file or migrate them to external client apps.

Prerequisites

Before authorizing a user, you must:

  • Generate an RSA Key Pair
  • Create an External Client App
  • Pre-authorize 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 external client app:

openssl x509 -pubkey -noout -in server.crt > server.pub

Create an External Client App

Next, create and configure an external client app in Salesforce. Follow the Salesforce documentation to:

  • Create an external client app
  • Select Enable OAuth Settings
  • Select Use Digital Signatures and upload your server.crt certificate
  • Set the Callback URL to http://localhost:1717/OauthRedirect
  • Select the OAuth scopes for your external client app. At minimum, set the api and refresh_token scopes.

Pre-Authorize Users

Then, pre-authorize the users who can use the external client 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 external client app.

Authorize Users on Heroku AppLink

You need the following to authorize a user:

  • client-id: The consumer key from your external client 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 external client app.

To authorize a Salesforce user via JWT, run the command:

$ heroku salesforce:authorizations:jwt:add 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:jwt:add 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 authorizations in 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:jwt:add 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:jwt:add 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
  • © 2026 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