2.3.1 β€’ Published 5 months ago

@identityprovider/client v2.3.1

Weekly downloads
-
License
MIT
Repository
github
Last release
5 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

5 months ago

2.3.0

5 months ago

2.2.0

5 months ago

2.1.0

5 months ago

2.0.0

5 months ago

1.0.5

5 months ago

1.0.4

5 months ago

1.0.3

5 months ago

1.0.2

5 months ago

1.0.1

5 months ago

1.0.0

5 months ago