Skip to main content
New tool CRON Expression Builder — preview next run times before you schedule Apex. Open the builder →
Diagram showing the process for unattended Salesforce sandbox user token generation in a CI/CD flow
Integration

Unattended Sandbox User Token Generation for CI/CD

Pulling access tokens for a pile of sandbox test users is a common CI/CD snag when the tests have to run as specific identities. Here are the unattended OAuth flows and API paths worth trying.

Key takeaways The instance-specific ConsumerKey is the barrier that stops standard unattended JWT flows for new users. The OAuth 2.0 Token Exchange Flow built on the established Admin token is the most promising standard OAuth path, as long as the Connected App allows delegation across user identities. If the OAuth exchange fails, querying the Tooling API for the sandbox's ConnectedApplication record to get the instance-specific ConsumerKey lets you fall back to a standard, user-specific JWT grant for each test user.

Unattended CI/CD sandbox user authentication: access token generation

A fully automated CI/CD pipeline for Salesforce sandboxes usually has to authenticate API calls as specific, non-admin test users inside those sandboxes. The hard part is getting an OAuth access token for arbitrary users programmatically, with no manual step such as a browser redirect.

Here is where things stand, which paths I ruled out, and what might still work for pre-provisioned sandbox test users running unattended.

Current CI/CD automation status

The setup phases already run on their own:

  • Sandbox provisioning is done.
  • The Sandbox Administrator authenticates through the Tooling API (/services/data/vXX.0/tooling/executeAnonymous) or an equivalent endpoint via the JWT Bearer flow, which yields an administrative access token.
  • The roughly 110 test users get created inside the sandbox.

The roadblock: arbitrary user token retrieval

What I need is a valid OAuth access token for each of those 110 test users, using only the admin token I already hold or static credentials I already have, such as the private key file.

Ruled out authentication flows

Several standard methods do not fit this unattended sandbox case:

  • sf org login web needs an interactive browser flow, so unattended execution is out.
  • sf org login jwt in its standard form leans on the sandbox's own consumerKey. That key changes with every new sandbox instance, so there is no reliable way to store it or fetch it programmatically for all test users across environments that keep getting rebuilt.
  • The sandboxAuth Tooling API endpoint is scoped to authenticate the sandbox creator, the admin user, rather than test users provisioned later.
  • The username/password OAuth flow is deprecated, and it still needs the Connected App's consumerKey and consumerSecret, which vary the same way the JWT flow's do once they are tied to the sandbox instance.

Known technical assets

Here is what I can count on:

  1. A valid access token for the Sandbox Administrator.
  2. The usernames for every target test user.
  3. A static private key file that works across organizational environments.
  4. The Connected App configuration (Client ID/Consumer Key) is identical to Production, though the instance-specific Client ID still has to be resolved.

Investigating programmatic token generation paths

Direct flows are blocked by the changing consumerKey, so the answer probably lies in delegation or in reusing the session context I already have.

1. Admin-delegated token generation via REST

Can the administrative session I hold delegate authority and mint tokens for other users? That usually points at the OAuth 2.0 Token Exchange Flow.

The urn:ietf:params:oauth:grant-type:token-exchange grant lets a client holding one security token, here the admin access token, swap it for a new token on behalf of a different subject, here the test user. It depends on the Connected App permitting token exchange, and on the admin token presented being authorized to make that exchange for the subject you want.

So if the Connected App is configured for delegation or audience restriction, exchanging the admin token (subject_token) for a test user token (resource_owner_id) might be feasible.

2. Apex execution as target user

If no REST API exposes direct delegation, running Apex as the target user may supply the context instead.

  1. Use the existing Admin token to run an anonymous Apex block through the Tooling API (/tooling/executeAnonymous).
  2. The Apex runs under the Admin context.
  3. Call System.runAs(TestUserRecord) to take on the test user's context inside that execution.
  4. Inside the runAs block, try to reach or generate a session ID or token tied to that user. Producing a full OAuth token from inside Apex for external use is complex, and it often calls for custom Apex endpoints that mimic OAuth provider behavior, which may still want a Consumer Key.

3. Discovering sandbox-specific Connected App details

If I could fetch the consumerKey for the sandbox's copy of the Connected App programmatically, the standard JWT flow would work for each user.

That means checking the ConnectedApplication object, or related metadata through the Tooling API, to see whether the ConsumerKey for the sandbox instance can be queried after creation, perhaps keyed to the sandbox ID or the Admin ID.

// Pseudocode for potential Tooling API query
SELECT Id, ConsumerKey FROM ConnectedApplication WHERE Name = 'YourAppName'

If that key comes back, you can run the standard JWT flow for each test user with their username, the retrieved sandbox ConsumerKey, and the static Private Key.

Originally reported by reddit.com

Newsletter

One email every Tuesday

New guides, tool updates, and the release-note changes that break things.

No spam. Unsubscribe in one click.

Comments

Loading comments...

Leave a Comment