📱 Webviews
Authentication

Authentication in Webviews

The host app authenticates the user with the same JWT used for the Lynes Loyalty API. Lynes hosts the Webview; your backend signs tokens, your app sends them on the first load.

JWT signing: JWT Authentication.

What your app must do

  1. Sign a JWT for the logged-in user (sub = your user ID).
  2. Open the Webview URL with Authorization: Bearer <JWT> on the initial HTTP request.
  3. Refresh the JWT before reopening or reloading the Webview if it expired.

That is the complete native auth integration.

What the hosted Webview does internally

Your app                 Hosted Webview                    Lynes API
   |                            |                              |
   |  GET /… + Bearer JWT       |                              |
   |--------------------------->|                              |
   |                            |  auth-token cookie (5 min)   |
   |                            |  POST /api/token-exchange    |
   |                            |  POST /auth/token + JWT      |
   |                            |<-----------------------------|
   |                            |  session-token cookie        |
   |  UI (userId = sub)         |                              |
   |<---------------------------|                              |

Middleware

If the first request includes Authorization: Bearer …, the Webview stores it in:

CookieTTLRole
auth-token5 minBridge token for client-side exchange
auth-token-timestamp5 minFreshness metadata

Token exchange

POST {WEBVIEW_URL}/api/token-exchange
Authorization: Bearer <JWT>
Content-Type: application/json
 
{ "token": "<JWT without Bearer prefix>" }

The Webview backend calls:

POST {API_BASE_URL}/auth/token
Authorization: Bearer <JWT>
Content-Type: application/json
 
{ "token": "<JWT without Bearer prefix>" }

On success:

  • HttpOnly cookie session-token (server-side calls)
  • Client storage sessionToken (session restore in the browser)

userId in the UI is always the session JWT claim sub.

Session lifetime

  • Session cookie: typically 1 hour, or until expiresAt from the API if sooner.
  • Client checks expiry about every 30 seconds.
  • Expired or failed auth may navigate to your configured back callback.

Required JWT claims

ClaimRole
subUser ID (must match IDs used in Lynes events)
issYour tenant ID
audYour project ID
iatIssued at (unix seconds)
expExpiry (unix seconds)

Anti-patterns

Do notReason
Put JWT in query stringLeaks in logs and referrers
Pass userId as query paramIgnored
Put API secret in the mobile appSign JWTs only on your server
Skip JWT on first loadNo user session

Verify JWT (debug)

GET {WEBVIEW_URL}/api/auth
Authorization: Bearer <JWT>

Returns decodedFields.sub, exp, etc.

REST API vs. Webview

REST APIWebview
TokenJWT per requestJWT on first load, then internal session
SigningAPI secretSame API secret
User IDsubsub after exchange

Related