Adding Sign-In to an Existing App
To get started, install the JTL’s auth library:Create the Manifest and Register your App
You must register your app with JTL before it can access JTL resources. Create anapp.json file in your frontend project root:
publicClient object tells JTL this is a browser-based authentication flow, where the user signs in through the JTL identity provider and is redirected back to your app after authentication.
redirectUris defines the allowed URLs where JTL can send the user after signing in. postLogoutRedirectUris defines where the user can be redirected after signing out.
See App Manifest: Authentication for the full field list.
Next, create a .env file in your frontend project root:
app.json and .env configuration and uses them to register the app with JTL.
Run:
Configure the Environment
Once your app is registered, copy the public client ID in the Partner Portal and add it to your environment variables:.env
.env file and populate it with the required values.
Wrap your App
The provider holds the session and makes it available to the rest of your component tree. Mount it above your router, passing the values from your environment.main.tsx
clientId has a value, the provider renders its children unchanged.
Protect a Route
RequireJtlAuth renders its children only when a merchant is signed in. Anyone reaching a protected route without a session is sent to the identity provider and returned to the same route afterwards.
App.tsx
RequireJtlAuth renders a top bar showing the signed-in merchant and a sign-out control. To place that bar yourself, use the JtlAuthBar component directly.
Gate the routes that run on your own domain. Routes that render inside the Hub or Cloud ERP receive identity through AppBridge and are not gated this way.
Read the Signed-In User
useJtlAuth returns the current session. The profile object carries the ID token claims, and access_token is the credential you send to the JTL Cloud API.
RequireJtlAuth a session always exists, so the null check guards only the moment before the provider resolves.
Fetch the User Profile
The ID token carries basic identity claims. The provider’s userinfo endpoint returns the full set, including the tenant the merchant belongs to.Call the JTL-Wawi API
API calls carry the access token and the tenant the merchant belongs to. Read the tenant fromurn:jtl:tenant_id in the userinfo response.
user.access_token at call time rather than holding a copy in component state.
Optionally, you can use the getTokenInformation function to get the token information.
organizationId in the token information is the same as the tenantId.
Sign Out
RequireJtlAuth includes a sign-out control in its top bar. To sign out from elsewhere in your app, call signoutRedirect from the session hook.
postLogoutRedirectUris. Without an entry, sign-out ends on the identity provider rather than back in your app.
Common Issues
Common failures and what causes them.Sign-in fails with a redirect URI error
Sign-in fails with a redirect URI error
The identity provider matches redirect URIs exactly, so the URL your app
sends must be present in your manifest character for character. A trailing
slash, a different port, or
http where the manifest declares https all
count as a mismatch. Check the value in your manifest against the URL in the
browser address bar when the error appears, and register a new app version
if they differ.The merchant returns to the sign-in page repeatedly
The merchant returns to the sign-in page repeatedly
This happens when the session cannot be stored, usually because the app is
served over
http on a host other than localhost, or because browser
storage is blocked. Serve the app over https in any environment other than
local development, and confirm that third-party storage restrictions are not
applying to your domain.The userinfo request returns 401
The userinfo request returns 401
The access token has expired or was rejected. Read
user.access_token at
the point of the call rather than capturing it once, so the value reflects
the most recent refresh. If the token is current and the request still
fails, confirm that VITE_JTL_ISSUER points at the same environment your
app is registered in.A protected route shows a configuration hint instead of signing in
A protected route shows a configuration hint instead of signing in
The client ID is missing, so the library has nothing to authenticate
against. Confirm that
VITE_JTL_CLIENT_ID is set and that the provider
receives it. A freshly scaffolded app has no client ID until it is
registered, so run npm run register first.The sign-in top bar renders without styling
The sign-in top bar renders without styling
Tailwind has not scanned the library’s
dist directory, so its utility
classes were never generated. Add the @source directive for
@jtl-software/cloud-apps-auth/dist to your CSS alongside the one for
Platform UI, then restart the dev server.API calls return a tenant error
API calls return a tenant error
The
X-Tenant-ID header is missing or does not match a tenant the merchant
belongs to. Read the value from urn:jtl:tenant_id in the userinfo
response.What’s Next?
Using Platform APIs
Query the JTL Cloud and JTL-Wawi APIs with the right headers and scoping.
App Manifest
Declare the public client, redirect URIs, and capabilities your app needs.
Architecture Overview
Compare the integration types and authentication flows available to your
app.
Platform UI
Build your interface with the JTL component library.