Authenticate a Salesforce Org for GitHub Actions

Set up automated authentication between GitHub Actions and your Salesforce org to continuously scan your code with the ApexGuru engine in Salesforce Code Analyzer. Choose the authentication method that best fits your environment.

  • JSON Web Token Bearer Flow: This approach is recommended for enterprise pipelines and team repositories. It uses a Connected App and an X.509 digital certificate to authenticate without storing static access tokens.
  • SFDX Auth URL: This lightweight, quick-start method is ideal for solo developers, rapid prototyping, or temporary sandboxes. It captures an existing authenticated CLI session URL into a single repository secret.

Prerequisites 

Before configuring the authentication method, complete these steps on your local workstation.

  • Install the Salesforce CLI
  • Identify the target Salesforce org
  • Create a dedicated integration user to prevent pipeline failures when team members change roles or leave. We recommend not binding CI/CD pipelines to individual user accounts

Authorize a Salesforce Org by Using a JWT Bearer Flow 

This approach is recommended for enterprise pipelines and team repositories. It uses a Connected App and an X.509 digital certificate to authenticate without storing static access tokens.

  1. In your local workspace, generate an RSA private key and a self-signed digital certificate using OpenSSL.
    OpenSSL is pre-installed on macOS and available via Git Bash on Windows. See Create a Private Key and Self-Signed Digital Certificate.

    Retain server.key (Private key — store in GitHub) and server.crt (Public cert — upload to Salesforce).

    Remove server.pass.key and server.csr.

  2. In your target org, create an external client app to authorize the incoming JWT requests.

    1. In your Salesforce org, click Setup App Manager or External Client Apps and create an external client app.

    2. Select Enable OAuth Settings.

    3. Set the callback URL to http://localhost:1717/OauthRedirect.

    4. Select Enable JWT Bearer Flow and upload your server.crt file.

    5. Add these OAuth scopes.

      1. Manage user data via APIs (api)

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

      3. Manage user data via Web browsers (web)

    6. Configure pre-authorization policies.

    7. Under OAuth Policies, for Permitted Users, select Admin approved users are pre-authorized.

    8. Under App Policies, add your Integration User’s profile or permission set to the Selected list.

    9. For IP Restrictions, select Relax IP restrictions.

    10. Save the app, and copy the generated Consumer Key (Client ID).

  3. Store the credentials in GitHub.

    1. In your GitHub repository, click Settings, click Secrets and variables, and then click Actions.

    2. Click New repository secret and add these key-value pairs.

Secret NameValue
SF_CLIENT_IDThe consumer key copied from your external client app.
SF_PRIVATE_KEYThe content of server.key, including -----BEGIN/END PRIVATE KEY-----.
SF_USERNAMEThe dedicated integration user for example, ci-codeanalyzer@yourcompany.com.
SF_INSTANCE_URLYour Salesforce My Domain URL (for example, [https://yourcompany.my.salesforce.com\](https://yourcompany.my.salesforce.com).
  1. In your .github/workflows/ci.yml pipeline file, add the authentication step before running the Code Analyzer scan.
1`name: Authenticate to Salesforce Org`  
2  `run: |`  
3    `echo "${{ secrets.SF_PRIVATE_KEY }}" > server.key`  
4    `sf org login jwt \`  
5      `--client-id ${{ secrets.SF_CLIENT_ID }} \`  
6      `--jwt-key-file server.key \`  
7      `--username ${{ secrets.SF_USERNAME }} \`  
8      `--instance-url ${{ secrets.SF_INSTANCE_URL }} \`  
9      `--set-default`  
10    `rm server.key`

Authorize a Salesforce Org by Using an SFDX Auth URL 

This lightweight, quick-start method is ideal for solo developers, rapid prototyping, or temporary sandboxes. It captures an existing authenticated CLI session URL into a single repository secret.

  1. Log in to your machine using your dedicated integration user, and then print the auth URL.

    1# Log in interactively (opens a browser)
    2sf org login web --alias ci-org
    3# Print the SFDX Auth URL for that org
    4sf org display --verbose --target-org ci-org

    Copy the value of the Sfdx Auth Url field, which starts with force://....

    Alternatively, export directly as JSON.

    1sf org display --verbose --json --target-org ci-org

    Copy the value under result.sfdxAuthUrl.

    Note: You need the --verbose flag to display the auth URL. To revoke access later, from Setup, in the Quick Find box, enter Connected Apps OAuth Usage, and then select Connected Apps OAuth Usage. Revoke the Salesforce CLI app for that user.

  2. Store the credentials in GitHub.

    In your GitHub repository, click Settings, click Secrets and variables, and then click Actions.

    Click New repository secret and add the value that you copied in the Sfdx Auth Url field.

  3. Create or update your pipeline file at .github/workflows/code-analyzer.yml.

    1`name: Test run-code-analyzer@v2 (ApexGuru)`
    2
    3`on:`  
    4  `pull_request:`  
    5    `branches: [main]`  
    6  `workflow_dispatch:`
    7
    8`jobs:`  
    9  `code-analysis:`  
    10    `permissions:`  
    11      `pull-requests: write`  
    12      `contents: read`  
    13      `actions: read`  
    14    `runs-on: ubuntu-latest`  
    15    `steps:`  
    16      `- name: Check out files`  
    17        `uses: actions/checkout@v5`
    18
    19      `- name: Setup Java`  
    20        `uses: actions/setup-java@v5`  
    21        `with:`  
    22          `distribution: 'zulu'`  
    23          `java-version: '>=11'`
    24
    25      `- name: Install Salesforce CLI`  
    26        `run: npm install -g @salesforce/cli@latest`
    27
    28      `- name: Install Code Analyzer Plugin`  
    29        `run: sf plugins install code-analyzer@latest`
    30
    31      `- name: Authenticate to Salesforce`  
    32        `env:`  
    33          `SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL }}`  
    34        `run: echo "$SFDX_AUTH_URL" | sf org login sfdx-url --set-default --sfdx-url-stdin`
    35
    36      `- name: Run Salesforce Code Analyzer`  
    37        `id: run-code-analyzer`  
    38        `uses: forcedotcom/run-code-analyzer@v2`  
    39        `with:`  
    40          `run-arguments: --workspace . --rule-selector apexguru --output-file sfca_results.html --output-file sfca_results.json`  
    41          `results-artifact-name: code-analyzer-results`  
    42          `github-token: ${{ github.token }}`
    43
    44      `- name: Print results`  
    45        `run: |`  
    46          `echo "Exit code: ${{ steps.run-code-analyzer.outputs.exit-code }}"`  
    47          `echo "Total violations: ${{ steps.run-code-analyzer.outputs.num-violations }}"`  
    48          `echo "Sev1: ${{ steps.run-code-analyzer.outputs.num-sev1-violations }}"`  
    49          `echo "Sev2: ${{ steps.run-code-analyzer.outputs.num-sev2-violations }}"`  
    50          `echo "Sev3: ${{ steps.run-code-analyzer.outputs.num-sev3-violations }}"`

    The --sfdx-url-stdin reads the URL from standard input (piped from echo), preventing sensitive tokens from writing to disk. --set-default targets this org for the Code Analyzer execution that follows.

Troubleshooting 

  • If several repositories share credentials, don’t duplicate secrets manually. In your GitHub repository, click Settings, click Secrets and variables, and then click Actions. Click New repository secret. Set repository access to All repositories or Selected repositories for centralized management and rotation.
  • GitHub-hosted runners draw from a large, dynamic pool of public IP addresses. If your org enforces strict login IP restrictions, apply these resolution steps:
    • JWT: Make sure that the external client app is configured to Relax IP restrictions under OAuth Policies.
    • SFDX Auth URL: Relax the Login IP Ranges, In the Integration User’s profile or org Network Access settings, relax the login IP ranges.
      Alternatively, if your organizational policies forbid relaxing IP rules, use self-hosted GitHub runners with fixed static IP addresses and allowlist those IP addresses in Salesforce.

See Also