Used Newie, our AI search tool in the docs? Take a 2-minute survey to rate your experience!

Authentication and setup for self-checkout

Prev Next

NewStore APIs authenticate via OAuth 2.0. For self-checkout clients and applications, use the Authorization Code grant with PKCE (Proof Key for Code Exchange). This article covers credential provisioning, the full auth flow, token handling, and operational procedures.

Prerequisites

Before the kiosk can authenticate against any NewStore environment, you need:

  • An API client of type Application client for the self-checkout app, created in Omnichannel Manager. See Creating an API client in Omnichannel Manager.

  • A username and password per store. Credentials are provisioned per store, not per developer or per application, because each terminal authenticates on behalf of a specific store location. Keep these credentials secure and do not commit them to version control.

  • Your tenant name, used in all API base URLs and in the OIDC discovery URL.

Creating an API client in Omnichannel Manager

Permission required

This feature is only accessible to Omnichannel Manager users with the Admin role assigned to them.

The self-checkout app signs a person in and calls NewStore on their behalf, so it needs an API client of type Application client. An Application client is issued no secret, because a browser is a place where a user could read one. It authenticates with the Authorization Code grant and PKCE instead. You need permission to manage API clients in Omnichannel Manager.

  1. Go to Settings > Users & Roles > API Clients and click Add API Client.

  2. Under Client type, select Application client.

  3. In General, enter a Name for the client, for example self-checkout-kiosk.

    The name can contain only letters, numbers, underscores, and dashes. Add a Description if needed.

  4. In Token TTL (seconds), enter 300. This is the lifetime of the access token.

    An access token cannot be revoked, so keep it short. The app requests a new one with the refresh token before each one expires.

  5. In Application, enter the Redirect targets.

    This is the callback URL that the login flow returns the user to. At least one is required, and the URL must match what the app sends exactly, including scheme, host, port, and path. Add one entry per environment, for example http://localhost:3000/login/callback for development and https://<your kiosk host>/login/callback for production.

    A single star at the end of an entry acts as a wildcard.

  6. In Post-logout targets, enter the URL the terminal returns to after the store manager logs out at store closing, for example https://<your kiosk host>/signed-out.

  7. In Allowed origins, enter the browser origin of the kiosk app, for example https://<your kiosk host>.

    These are the origin sources allowed to call the platform for this client. If the kiosk runs on a mobile app, which has no origin, leave this property empty.

  8. Select Keep the user signed in after the access token expires.

    This enables the refresh token.

  9. In Refresh token TTL (seconds), enter 36000 for a 10 hour session that covers the business or sales day in the store.

    A refresh token can be revoked, so it limits the damage if a terminal is compromised, and the session ends by itself after closing. Set the value to the longest trading day of the store.

    Important

    If the token expires while the store is open, operations at the self-checkout kiosk stops until an associate logs in again.

  10. In Privileges, select the privileges that the self-checkout app needs.

    For the self-checkout APIs, select the privileges related to orders, catalog, checkout, promotions, taxes, and receipts.

  11. Click Submit.

Omnichannel Manager assigns the client a UUID. This UUID is the client ID.

Use it as AUTH_CLIENT_ID in the kiosk configuration. An Application client has no secret, so there is nothing else to store.

Note

The default values, 3600 and 2592000 seconds, give a one hour access token and a 30 day refresh token.

Do not use them for a kiosk that stands unattended on the shop floor, instead choose a window that minimizes risk.

Important

Create a separate Application client for self-checkout. Do not reuse the client that you may be using already for Associate App or Omnichannel Manager. Tokens issued to the self-checkout client carry only the privileges that self-checkout needs, and the short token lifetimes are specific to an unattended kiosk.

Redirect targets based on the type of client

The self-checkout app is a public client irrespective of the tech stack used. A web app in a browser, an Electron app, and a native app on Windows, iOS, or Android all use the Authorization Code grant with PKCE and hold no authentication secrets. The difference is in how the user is sent back to the app in the login flow.

  • Web app: An HTTPS URL that the app serves, for example https://<kiosk host>/login/callback, and http://localhost:<port>/login/callback for development. The app serves its entry page at that path so its router handles the callback.

  • Native or desktop app: A redirect that the app itself receives. This is typically a custom URL scheme such as com.example.selfcheckout:/oauth/callback, or a loopback address such as http://127.0.0.1:<port>/callback, opened through the system browser or the platform's authentication session. Register the exact value on the client.

A native or desktop app has no browser origin, so leave Allowed origins empty. Tokens stay in memory on every kind of client. Do not write them to disk or to any storage mechanism on the device.

Choosing the token lifetime

An access token cannot be revoked. Whoever holds it can call the platform until it expires. A refresh token can be revoked, and it is exchanged at the token endpoint, and not shared via APIs.

Setting

Recommended value

Why

Token TTL (seconds)

300 (5 minutes)

Limits how long a leaked access token is usable. The app requests a new one with the refresh token before each one expires.

Keep the user signed in after the access token expires

Selected

Issues a refresh token at login, so the store manager or lead associate logs in once in the morning.

Refresh token TTL (seconds)

36000 (10 hours)

Covers the business or sales day in the store. The session ends by itself after closing, and the token can be revoked if a terminal is compromised.

Post-logout targets

The signed-out page of the kiosk

Logging out at store closing ends the session on the server and return the terminal to a known screen.

Requesting the tokens

Add a nonce to the authorization request alongside state. Keep both with the PKCE verifier across the redirect, and reject the response if either does not match:

?response_type=code
&client_id={your-client-id}
&redirect_uri={a redirect target of the client}
&scope=openid
&state={random}
&nonce={random}
&code_challenge={code_challenge}
&code_challenge_method=S256

The token response contains access_token, refresh_token, id_token, and expires_in in seconds. Check that the nonce claim of the id_token equals the value you sent. Record the expiry of the access token as the current time plus expires_in, and refresh shortly before it.

Refreshing the access token

With a 5 minute access token, the app refreshes about every four minutes, without any action from store staff:

POST {token_endpoint}
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token={refresh_token}
&client_id={your-client-id}

The response carries a new access_token and expires_in, and can carry a new refresh_token. Replace both in memory. A refresh that fails with 400 after the refresh token lifetime has passed is the normal end of the trading day. Return to the login screen.

Logging out at store closing

Logging out ends the session on the server. Discard the tokens in memory, then open the end session endpoint from the discovery document:

{end_session_endpoint}
?id_token_hint={id_token}
&post_logout_redirect_uri={a post-logout target of the client}

The authorization server returns the terminal to the post-logout target, which must be listed on the API client. Add this step to the store closing checklist.

Testing the client

Test the client with a static page that runs the discovery, login with PKCE, refresh, and logout steps Serve the page from an origin that is listed in Allowed origins, with its own URL listed in Redirect targets and in Post-logout targets.

A successful test displays the token response, the decoded claims of the id_token and the access_token, and a new access_token after a refresh.


Authorization Code and PKCE

Browser-based applications cannot hold a client secret securely. PKCE (Proof Key for Code Exchange) eliminates that requirement: the application generates a one-time verifier, includes a derived challenge in the authorization request, and proves possession of the original verifier at token exchange time. No secret is ever stored in the browser.

The Resource Owner Password Credentials (ROPC/password) grant does not work with this platform. Use Authorization Code + PKCE only.

Flow

1. Generate code_verifier
   A random string, 43–128 characters, URL-safe characters only.
   code_challenge = base64url(SHA256(code_verifier))

2. Redirect the user to the authorization endpoint:
   ?response_type=code
   &state={random}
   &nonce={random}
   &client_id={your-client-id}
   &redirect_uri={your-registered-callback-url}
   &code_challenge={code_challenge}
   &code_challenge_method=S256
   &scope=openid

3. The user enters their provisioned store username and password
   on the NewStore-hosted login page.

4. The authorization server redirects to your callback URL:
   {your-registered-callback-url}?code=AUTH_CODE&state=...

5. Exchange the code for tokens:
   POST {token_endpoint}
   Content-Type: application/x-www-form-urlencoded

   Check that the nonce claim of the id_token matches.

   grant_type=authorization_code
   &code={AUTH_CODE}
   &redirect_uri={your-registered-callback-url}
   &code_verifier={code_verifier}
   &client_id={your-client-id}

6. Store access_token and refresh_token in memory only.
   (Not localStorage, keychain, or app storage — XSS risk.)

7. Attach the access token to all platform API calls:
   Authorization: Bearer {access_token}

8. On 401:
   Shortly before expires_in runs out, refresh with the request for a new access token.
   If refresh fails, redirect to login.

After a successful login, remove the auth parameters from the URL:

history.replaceState({}, document.title, window.location.pathname);

This prevents the authorization code from being visible in the address bar and avoids a second exchange attempt if the page is reloaded.

Redirect URI

Your callback URL must be listed in Redirect targets on the API client. The URL must match exactly, including scheme, host, port, and path. For local development, register a URL such as http://localhost:3000/login/callback. For production deployments you register your public URL. Edit the API client in Omnichannel Manager to add or update redirect targets.

For web apps, your application must serve index.html at the callback path so the auth redirect is handled by your client-side router rather than returning a 404.

OIDC discovery

Fetch the authorization and token endpoint URLs from the OIDC discovery document rather than hardcoding them. The document is available at:

https://id.{env}.newstore.net/auth/realms/{your-tenant}/.well-known/openid-configuration

Where:

  • {env} is s for staging, p for production

  • {your-tenant} is your tenant name, provided during provisioning

Fetch this document at application startup. The response includes authorization_endpoint and token_endpoint; use these values for all auth requests. This ensures your application automatically picks up any endpoint changes without a code deployment.

Token handling

Store tokens in memory only

localStorage and sessionStorage are accessible to any JavaScript on the page and are not appropriate for credential storage. Keep tokens in a module-scoped variable or equivalent in-memory store.

Token expiry

The access token expires after five minutes and the refresh token after the trading day. See Choosing the token lifetime. Refresh proactively from expires_in or the token's exp claim rather than waiting for a 401 in the middle of a transaction.

On 401

Attempt a token refresh using the refresh_token grant. If the refresh succeeds, replay the failed request. If the refresh fails (for example, the refresh token has expired), redirect to the login flow.

A refresh failure after the refresh token lifetime has passed is the expected end of the sales day, not a refresh failure.

Daily operational procedure

Self-checkout credentials are per-store. The store manager logs in at the start of each trading day:

  1. Open each self-checkout terminal.

  2. Complete the login flow on each terminal individually.

  3. Each terminal receives its own access token and refresh token.

  4. Terminals stay authenticated for the trading day. The app renews the access token every few minutes with the refresh token, without any action from staff.

  5. At store closing, log out on each terminal. The app discards the tokens and calls the end session endpoint, which returns the terminal to the post-logout target.

Add this step to your store opening checklist. Authentication failures during the trading day block checkout entirely — ensuring the login completes before the store opens is simpler than diagnosing a mid-day disruption.

Environment configuration

Configure your application with these variables. Real platform values require provisioned credentials.

Variable

Real platform value

AUTH_URL

https://id.{env}.newstore.net/auth/realms/{your-tenant}/protocol/openid-connect/auth

AUTH_TOKEN_URL

https://id.{env}.newstore.net/auth/realms/{your-tenant}/protocol/openid-connect/token

AUTH_CLIENT_ID

Client ID of the Application client you created in Omnichannel Manager.

AUTH_REDIRECT_URI

One of the redirect targets of the API client.

For {env}: use s for staging, p for production. Prefer fetching AUTH_URL and AUTH_TOKEN_URL dynamically from the OIDC discovery document rather than setting them as fixed variables.

Integration checklist

Before going live, go through this checklist to ensure all tasks are complete.

  • Application client created in Omnichannel Manager with a 300 second access token, refresh tokens enabled, and a refresh token lifetime that covers the sales day.

  • Per-store users with kiosk role and credentials provisioned

  • OIDC discovery document fetched at startup; endpoints not hardcoded

  • Authorization Code + PKCE flow implemented and validated against staging

  • Access and refresh tokens stored in memory only (not localStorage, not cookies)

  • Proactive token refresh implemented; 401 handler in place

  • Auth code parameters cleared from URL after successful exchange for web apps

  • Morning login procedure documented in store opening checklist

  • Redirect targets, post-logout targets, and allowed origins set on the API client for every environment