wink-identity-sdk
v0.3.0
Published
A JavaScript/TypeScript client to integrate **Wink Identity Web SDK**, manage authentication flows, and handle session lifecycle.
Readme
Wink ID
A JavaScript/TypeScript client to integrate Wink Identity Web SDK, manage authentication flows, and handle session lifecycle.
CDNs
<!-- jsdelivr -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/wink-id.umd.min.js"></script>
<!-- unpkg -->
<script src="https://unpkg.com/[email protected]/dist/wink-id.umd.js"></script>Installation
npm install wink-identity-sdk
# or
yarn add wink-identity-sdk
# or
pnpm add wink-identity-sdkImport
import { getWinkLoginClient, WinkError } from "wink-identity-sdk";API Overview
Core Methods
| Method | Description |
|--------|-------------|
| winkInit(params?: WinkInitParams): Promise<void> | Initializes the Wink login system, performs silent SSO check, and fires callbacks. |
| winkLogin(params?: WinkLoginParams): Promise<void> | Starts the Wink authentication flow and redirects to the Wink login page. |
| winkLogout(params?: WinkLogoutParams): Promise<void> | Clears the local session and redirects to the OIDC logout endpoint. |
| getParsed(): WinkIdToken \| null | Returns the decoded Wink ID token if the user is authenticated. |
Properties
| Property | Description |
|----------|-------------|
| token?: string | OAuth2 access token (5-minute lifetime). |
| idToken?: string | OIDC ID token. Required for logout. |
| refreshToken?: string | Token used to extend the session. |
| winkSessionId?: string | The active Wink session ID. Updated by winkLogin({ sessionId }). |
Usage
1. Create the Wink Login Client
The client must be created server-side session first. Never call the Wink session API directly from the browser — use a backend route as a proxy.
// 1. Fetch a sessionId from your backend (never from the browser directly)
const { sessionId } = await fetch("/api/wink/session").then(r => r.json());
// 2. Create the client
const winkLoginClient = getWinkLoginClient({
clientId: "__client_id__",
realm: "wink",
sessionId,
loggingEnabled: true,
cancelUrl: `${window.location.origin}/callback`,
onAuthErrorFailure: (error) => console.error(error),
});sessionId lifetime: The session is created at the moment you call your backend. If the user stays on the page for a long time before clicking "Login", the session may expire. See Keeping the sessionId fresh.
2. Initialize Wink Login
Call winkInit on every page load to check for an existing SSO session.
winkLoginClient.winkInit({
// Full URL recommended — relative paths can break in some routing setups
silentCheckSsoRedirectUri: `${window.location.origin}/silent-check-sso.html`,
onInitEnd() {
// SSO check is complete — safe to render auth-gated UI
},
onFailure(error) {
console.error(error); // error is a WinkError instance
},
async onSuccess() {
// User has an active session — fetch their profile
console.log("Authenticated:", winkLoginClient.token);
},
});Preventing auto-redirect on specific pages
The SDK can automatically resume an interrupted login flow. If you need to suppress this on a page that should never trigger an automatic redirect (e.g. a public landing page or post-logout screen):
winkLoginClient.winkInit({
disableAutoRedirect: true,
onFailure(error) { console.error(error); },
});3. Trigger Login
winkLoginClient.winkLogin({
redirectUri: `${window.location.origin}/auth/callback`,
onFailure(error) {
console.error(error); // error is a WinkError instance
},
});Keeping the sessionId fresh
If the user may stay on the page for a long time before clicking "Login", the original sessionId passed to getWinkLoginClient() may have expired. Pass a fresh one at login time without recreating the client:
// Fetch a new session from your backend right before redirecting
const { sessionId: freshSessionId } = await fetch("/api/wink/session").then(r => r.json());
await winkLoginClient.winkLogin({
redirectUri: `${window.location.origin}/auth/callback`,
sessionId: freshSessionId, // overrides the one from getWinkLoginClient()
});Important: Never pass
sessionIdon the callback/return page. It is only needed when starting a new login flow.
4. Handle the OAuth Callback
Wink uses response_mode=fragment — the OAuth code arrives in the URL hash, not the query string.
# Correct — code is in the hash
https://yourapp.com/auth/callback#code=abc&state=xyz
# Wrong assumption — nothing in the query string
https://yourapp.com/auth/callback?code=abc ← will be emptyOn your callback page, call winkInit without silentCheckSsoRedirectUri. The SDK will automatically complete the token exchange using the #code=... in the hash:
winkLoginClient.winkInit({
onSuccess() {
// Token exchange completed — user is authenticated
console.log("token:", winkLoginClient.token);
},
onFailure(error) {
console.error(error);
},
});5. Trigger Logout
winkLoginClient.winkLogout({
redirectUri: window.location.origin,
onFailure(error) {
console.error(error);
},
});winkLogout fully signs the user out of Wink. After logout, the next login will always require biometric verification — no silent re-authentication.
Error Handling
All onFailure callbacks receive a WinkError instance with additional context beyond a generic Error("Load failed").
import { WinkError } from "wink-identity-sdk";
winkLoginClient.winkInit({
onFailure(error) {
if (error instanceof WinkError) {
console.error("Code:", error.oidcCode); // e.g. "access_denied"
console.error("Description:", error.oidcDescription); // Wink error description
}
console.error(error.message); // always a readable string
},
});Common error codes
| oidcCode | Cause | Fix |
|------------|-------|-----|
| access_denied | User cancelled or was denied | Show a retry prompt |
| login_required | No active session for silent SSO | Expected — proceed to login |
| authentication_expired | Session timed out | Re-initialize and re-login |
| (network error) | CORS / connectivity issue | Contact Wink support to verify your app's origin is allowlisted |
Network errors: If you see
"Network error — check CORS (Web Origins) and connectivity", your app's origin may not be allowlisted for this Wink client. Contact Wink support to have it added.
Silent Check SSO File
Create public/silent-check-sso.html in your app:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Wink Silent Check</title>
</head>
<body>
<script>
window.parent.postMessage(location.href, location.origin);
</script>
</body>
</html>Known Caveats
Safari / iOS — iframe blocked by default
checkLoginIframe and silentCheckSsoFallback are disabled by default in this SDK. Enabling them causes a 10-second timeout in all modern browsers and they are incompatible with iOS Safari and modern browsers that restrict 3rd-party cookies.
If your environment explicitly supports 3rd-party cookies, you can re-enable them:
winkLoginClient.winkInit({
checkLoginIframe: true,
silentCheckSsoFallback: true,
// ...
});The tradeoff: with checkLoginIframe: false, logout in one tab does not propagate to other open tabs in real time. Tabs will detect the expired session on the next token refresh (within 5 minutes).
Redirect loop from login_session_state
If login_session_state=1 appears in the URL and no SSO session is found, winkInit will call winkLogin() automatically. This is intentional behavior to resume an interrupted flow. If it causes unexpected redirects on a specific page, pass disableAutoRedirect: true to that page's winkInit call.
SSO session termination
winkLogout() fully terminates the Wink session. Without calling it, the next login on any Wink-integrated app would silently re-authenticate without biometric verification. This is handled automatically — no extra configuration needed.
License
This project is private and not licensed for public use, distribution, or modification.
