2.3.1 β€’ Published 9 months ago

@identityprovider/client v2.3.1

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

@identityprovider/client

A lightweight and framework-agnostic TypeScript client for interacting with an OpenID Connect (OIDC) Identity Provider using Authorization Code Flow with PKCE.

✨ Features

  • Full PKCE-based authorization
  • authorize() + silentAuthorize() for login flows
  • Handles state, nonce, codeVerifier generation, storage, & validation
  • Uses sessionStorage for short-term, tab-isolated security artifacts
  • Token exchange with direct IdP call or custom local API (ideal for secure HttpOnly cookies)
  • Configurable PKCE cleanup delay for React/SPAs
  • Robust error handling with custom error types
  • Framework-agnostic: works with React, Vue, Svelte, plain JavaScript

πŸš€ Installation

npm install @identityprovider/client

🧱 Usage

1. Instantiate the client

import { IdentityProviderClient } from "@identityprovider/client";

// cleanupDelayMs (optional): default is 5000 ms (5 seconds)
const client = new IdentityProviderClient(
    "https://idp.example.com",     // Base URL of the Identity Provider
    "your-client-id",              // OIDC client_id
    5000                           // Optional: PKCE cleanup delay in milliseconds
);

2. Start the authorization flow

await client.authorize({
  redirectUri: "https://your-app.com/callback",
  scope: "openid profile email"
});

This will redirect the user to the Identity Provider's login screen.

3. Handle the callback and exchange tokens

βœ… In-memory/localStorage token handling:

const response = await client.token({ 
    code,
    redirectUri: "https://your-app.com/callback"
});
// response.accessToken, response.idToken, etc.

You do not need to pass any options.

πŸ” Secure HttpOnly cookie-based flow (recommended):

await client.token({
  code,
  redirectUri: "https://your-app.com/callback",
  tokenExchangeHandler: async (request) => {
    const res = await fetch("/api/connect/token", {
      method: "POST",
      body: JSON.stringify(request),
      headers: {
        "Content-Type": "application/json"
      },
      credentials: "include" // important!
    });

    if (!res.ok) {
      throw new Error("Token exchange failed");
    }

    return await res.json();
  }
});

Your backend should then:

  1. Call the Identity Provider's /connect/token
  2. Set secure HttpOnly cookies (access and refresh tokens)

πŸ”„ Silent Authorization

You can use the silentAuthorize method to refresh tokens without user interaction. This is useful for maintaining a session without prompting the user.

const code = await client.silentAuthorize({ scope: "openid profile email" });

This will:

  • Loads an invisible iframe
  • Performs a prompt=none flow
  • Resolves with an authorization code if still authenticated
  • Throws SilentAuthorizationError if not

πŸšͺ Logout

Use the logout() method to log out the user by redirecting them to the Identity Provider’s logout endpoint.

client.logout({ postLogoutRedirectUri: "https://your-app.com/logout" });

βš™οΈ Advanced Options

cleanupDelayMs (constructor)

Controls how long to retain PKCE-related values (state, nonce, code_verifier) in sessionStorage after a successful token exchange.

new IdentityProviderClient("https://idp", "clientId", 7000); // Keep values for 7s

Recommended: at least 3–5 seconds for React dev mode double renders.

❌ Typed Error Handling

All client errors extend Error and can be caught using instanceof:

  • StateMismatchError
  • CodeVerifierMissingError
  • NonceMissingError
  • IdTokenMissingError
  • TokenExchangeError
  • SilentAuthorizationError

Example:

try {
  await client.token();
} catch (err) {
  if (err instanceof StateMismatchError) {
    alert("State does not match β€” possible CSRF!");
  }
}

πŸ›‘οΈ Security Best Practices

  • Always validate state and nonce (the client does this for you)
  • Prefer using HttpOnly cookies via your own API
  • Set SameSite=Strict or Lax on cookies where appropriate
  • Avoid persisting tokens in localStorage

πŸ“¦ License

MIT

2.3.1

9 months ago

2.3.0

9 months ago

2.2.0

10 months ago

2.1.0

10 months ago

2.0.0

10 months ago

1.0.5

10 months ago

1.0.4

10 months ago

1.0.3

10 months ago

1.0.2

10 months ago

1.0.1

10 months ago

1.0.0

10 months ago