React JS

This guide covers integrating Wink Identity Web into a React app using the official Wink Identity Web SDK and the React Starter Kit.

CRITICAL SECURITY – READ FIRST

NEVER expose sensitive data in client-side code.

  • clientSecret – server-side only
  • API keys and credentials – server-side only
  • Direct calls to the Wink Session API from the browser – use a backend proxy only
📘

Session creation and any calls that use credentials MUST go through your backend API.


Option A: Use the Starter Kit (recommended)

The fastest way to integrate is to use the React Starter Kit, which already implements the secure flow (session from backend, no secret in frontend, user profile from backend).

  • Repository: wink-identity-web-react-js-starter-kit
  • Stack: React, TypeScript, Vite
  • Includes: WinkAuthProvider, useWinkAuth() hook, session id from backend, user profile from backend, SDK-handled logout via winkLogout(), silent-check SSO

Quick start:

  1. Clone the repo and install dependencies (pnpm install or npm install).
  2. Run the backend (e.g. Wink Identity Backend Templates – Express starter). The frontend needs a backend that exposes GET /session and GET /user.
  3. Copy .env.example to .env.local and set:
    • VITE_WINK_CLIENT_ID
    • VITE_WINK_REALM
    • VITE_WINK_BASE_URL
    • VITE_WINK_AUTH_URL
    • VITE_WINK_BACKEND_URL (your backend URL)
  4. Run pnpm dev (or npm run dev).
  5. Open the app, click Login with Wink, and complete the flow.
❗️

No clientSecret or other credentials are used in the frontend; session creation and user data are done via your backend.


Option B: Add Wink to an existing React app

If you prefer to integrate into an existing app instead of using the starter:

Prerequisites

  • React 16.8+ (Hooks)
  • Node.js 18+
  • A backend API that creates the Wink session and returns user profile (see Backend Integration).

1. Install the SDK

npm install wink-identity-sdk
# or
pnpm add wink-identity-sdk

2. Environment variables (client-safe only)

Use a .env or .env.local file. With Vite, variable names must start with VITE_. Never put clientSecret or any secret here.

VITE_WINK_CLIENT_ID=your-client-id
VITE_WINK_REALM=your-realm
VITE_WINK_BASE_URL=https://login-api.winkapis.com
VITE_WINK_AUTH_URL=https://auth.winkapis.com
VITE_WINK_BACKEND_URL=http://localhost:8080

Your backend uses credentials and calls the Wink Session API; the frontend only calls your backend (e.g. GET /session, GET /user).

3. Backend contract

Your backend must expose:

  • GET /session?returnUrl=...&cancelUrl=... — Creates a Wink session server-side and returns JSON that includes a session id (e.g. sessionId, SessionId, or id).
  • GET /user?clientId=...&token=... — Returns the user profile after authentication.

4. Integration flow

  1. On app load: Create a Wink client once with getWinkLoginClient(config) (no sessionId needed here). Call client.winkInit({ silentCheckSsoRedirectUri: '...', onSuccess, onFailure }) to check for an existing session (SSO).
  2. On login: Call your backend GET /session?returnUrl=...&cancelUrl=... right before the user initiates login and read the sessionId from the response. Pass it directly to client.winkLogin({ sessionId, redirectUri }) — no need to recreate the client.
  3. After auth: Fetch user profile from your backend (GET /user) using the token from the client; do not rely on the client alone for profile.
  4. Logout: Call client.winkLogout({ redirectUri }). The SDK handles the full OIDC logout internally, terminates the Wink session, and redirects the user.
📘

For a full reference implementation (config shape, error handling, protected routes), use the React Starter Kit as the source of truth.

5. Session ID is mandatory

You must obtain a sessionId from your backend right before the user initiates login and pass it to client.winkLogin({ sessionId }). This ensures the session is always fresh — a session fetched at page load may expire if the user waits before clicking "Sign in". Never call the Wink Session API from the browser.

🚧

Security: Your backend calls the Wink Session API with credentials. See Backend Integration and Session Management for details.

6. Token lifetimes (reference)

  • Access Token: 5 minutes
  • Refresh Token: 30 minutes (each refresh extends all tokens by 5 minutes)
  • See Login and Logout Behavior for full token lifecycle.

Flow overview

User clicks "Login with Wink"
    ↓
App calls backend GET /session?returnUrl=...&cancelUrl=...
    ↓
Backend calls Wink Session API (server-side), returns sessionId
    ↓
App calls client.winkLogin({ sessionId, redirectUri })
    ↓
User is redirected to Wink Identity → authenticates (e.g. biometric)
    ↓
Wink redirects back to your app (callback URL)
    ↓
SDK processes callback; onSuccess fires, app fetches user from backend GET /user
    ↓
User is authenticated; call client.winkLogout({ redirectUri }) to sign out

Key points

  1. Starter Kit first — Use the React Starter Kit for a complete, secure example.
  2. Session from backend — Always get sessionId from your backend right before login and pass it to client.winkLogin({ sessionId }).
  3. No secrets in the frontend — No clientSecret; no direct Wink Session API calls from the browser.
  4. User profile from backend — After auth, get profile via your backend (GET /user).
  5. Logout — Call client.winkLogout({ redirectUri }). The SDK handles the OIDC logout and Wink session termination automatically.

Troubleshooting

IssueWhat to check
Session creation failsBackend GET /session returns 200 and a body with a session id; returnUrl and cancelUrl are valid. Backend has correct Wink credentials.
Login redirect doesn't startsessionId is passed to client.winkLogin({ sessionId }) when the user initiates login.
User profile emptyBackend GET /user is called with clientId and token after onSuccess; backend is configured and returns the expected shape.
Token refresh / expiryAccess 5 min, refresh 30 min; implement refresh via your backend or token endpoint if you need longer sessions. See Login and Logout Behavior.

Additional resources


What’s Next

Now that your front end is configured, proceed to: