An on-behalf-of token cannot give your app more access than the user has. The gateway enforces the user’s permissions, so your app does not need to manage those roles itself.
If your backend only ever acts as your app, keep using your access token. See Service Account Authentication.
How It Works
Your app does not create the on-behalf-of token itself. It first authenticates with its service account, then sends that access token to the Account Service to request a token for a specific user. When the Account Service receives the request, it checks:- Your app is installed for the specified tenant.
- The capability is enabled for your app.
- The specified user belongs to that tenant.
Before You Start
Three things need to be in place.1
Enable the capability
Your app’s service account declares it in the app manifest:You can also turn on Act on behalf of users on the service account in the Partner Portal.
2
Have your service account credentials
The
CLIENT_ID and CLIENT_SECRET issued when you registered your app. See Service Account Authentication.3
Know the user and the tenant
You name the user by their JTL ID and the tenant by its ID. Both come from a verified token:
An embedded app reads these from the app token its frontend sends. An app on its own domain reads them from the token it receives at sign-in. See App Token Authentication and Standalone Authentication.You do not need the user’s own token at exchange time, only their ID. Your app must be installed for the tenant, and the user must be a member of it.
Getting an On-Behalf-Of Token
The exchange takes two calls: one to authenticate as your app, one to swap that credential for a user-bound token.1
Get your access token
Request a
client_credentials token as you would for any other API call.2
Exchange it for a user-bound token
Send the access token as the bearer, and name the user and tenant in the body.The response carries the token, a refresh token, and its lifetime in seconds.
3
Call the API as the user
Use
accessToken as the bearer, and send the same tenant you named in the exchange.Implementation
The exchange in each language, taking the access token from your service account and returning a token bound to the user.Refreshing the Token
For long-running or unattended work, rotate the token with its refresh token rather than running the exchange again.Token Claims
The on-behalf-of token is a JWT you use as a bearer. Its subject is the user, so services authorize as the user, while the delegation stays visible in the claims.
The tenant is fixed when the token is minted, so a token issued for one tenant cannot be used against another.
Errors
The failures you are most likely to hit, and what causes them.403 Forbidden: the token carries no app ID
403 Forbidden: the token carries no app ID
The access token was issued without an app identity behind it. Confirm the app and its service account are registered in the Partner Portal, and that the credentials you are using belong to that app.
403 Forbidden: the capability is off, or the app is not installed
403 Forbidden: the capability is off, or the app is not installed
Two checks produce this. Confirm Act on behalf of users is enabled on your app’s service account, and that the merchant has installed your app on the tenant you named.
403 Forbidden: the user is not a member of the tenant
403 Forbidden: the user is not a member of the tenant
The
userId and tenantId do not belong together. Take both from the same verified app token, where sub is the user and urn:jtl:tenant_id is their tenant, rather than combining values from different sources.400 Bad Request on the refresh call
400 Bad Request on the refresh call
The refresh token is invalid, expired, revoked, or has already been rotated. Rotation invalidates the previous token immediately, so a stored copy from an earlier rotation fails. Run the full exchange again to get a new pair.
403 Forbidden on an API call after a successful exchange
403 Forbidden on an API call after a successful exchange
The token is valid, but the call exceeds what the user is permitted to do. An on-behalf-of token is bounded by that user’s own JTL-Wawi permissions, so a merchant without write access to a resource cannot write to it through your app. See Scopes & Permissions.
What’s Next?
Service Account Authentication
Obtain and cache the access token this exchange starts from.
App Token Authentication
Verify the app token that tells you which user and tenant to act for.
Scopes & Permissions
How enforcement differs between an access token and a user-bound token.
Using Platform APIs
Call the JTL Cloud and JTL-Wawi APIs with the right headers and scoping.