OpenID Connect Client
openid-client is an OpenID Certified JavaScript client library designed for implementing OAuth 2.0 and OpenID Connect flows. It offers a comprehensive API for common authentication and authorization patterns, including Authorization Code, Refresh Token, Device Authorization, Client-Initiated Backchannel Authentication (CIBA), and Client Credentials grants. The library also supports advanced features like Demonstrating Proof-of-Possession (DPoP), Token Introspection and Revocation, Pushed Authorization Requests (PAR), and various JWT Secured operations (JAR, JARM, UserInfo). It is built for a wide range of JavaScript runtimes, including Node.js, browsers, Deno, and Cloudflare Workers. Currently at version 6.8.3, openid-client is actively maintained with a regular release cadence, ensuring compliance with the latest protocol specifications. A key differentiator is its OpenID Certification for Basic, FAPI 1.0, and FAPI 2.0 Relying Party Conformance Profiles, guaranteeing high standards of protocol interoperability.
Common errors
-
TypeError: (0, openid_client_1.discovery) is not a function
cause Attempting to use `require()` to import `openid-client` in a CommonJS module, or running an ESM module without proper configuration (e.g., missing `"type": "module"` in `package.json` or incorrect file extension).fixEnsure your project is configured for ES Modules. Use `import { discovery } from 'openid-client'` and add `"type": "module"` to your `package.json` or rename your file to `.mjs`. -
Error: authorization_code grant type not allowed for this client
cause The client registered with the Authorization Server does not have the 'authorization_code' grant type enabled or the 'response_types' are misconfigured.fixVerify your client registration at the Authorization Server to ensure 'authorization_code' is an allowed grant type and 'code' is an allowed response type. Double-check `client.response_types` configuration. -
Error: invalid_grant
cause The authorization code exchanged for tokens is invalid, expired, or has already been used. This can also happen due to PKCE mismatch.fixEnsure the `code_verifier` sent during the token exchange matches the `code_challenge` sent during the authorization request. Also, ensure the authorization code is used only once and within its validity period. Check the redirect URI matching exactly.
Warnings
- breaking Since v5, openid-client is a pure ECMAScript Module (ESM). Attempting to use `require()` for imports will result in a TypeError.
- gotcha When using `redirect_uri` with a query string or a bare origin, there are known subtle issues that may require a specific workaround documented by the library.
- gotcha The Passport strategy integration (e.g., in Express.js apps) may now require custom logic to drive initiating authentication requests, affecting previous implementations that relied on implicit request handling.
- breaking When using the Passport strategy, a fix was implemented to correctly delete one-time state on callback, which might alter behavior for applications expecting state to persist or for those that didn't correctly clean up state previously.
Install
-
npm install openid-client -
yarn add openid-client -
pnpm add openid-client
Imports
- discovery
const { discovery } = require('openid-client')import { discovery } from 'openid-client' - Client
import Client from 'openid-client'
import { Client } from 'openid-client' - generators
import * as generators from 'openid-client/lib/helpers/generators'
import { generators } from 'openid-client' - All exports
const openid = require('openid-client')import * as openid from 'openid-client'
Quickstart
import { Issuer, generators } from 'openid-client';
const main = async () => {
const issuerUrl = process.env.OIDC_ISSUER_URL ?? 'https://accounts.google.com';
const clientId = process.env.OIDC_CLIENT_ID ?? 'YOUR_CLIENT_ID';
const clientSecret = process.env.OIDC_CLIENT_SECRET ?? 'YOUR_CLIENT_SECRET';
const redirectUri = process.env.OIDC_REDIRECT_URI ?? 'http://localhost:3000/callback';
try {
// Discover the OpenID Provider's configuration
const googleIssuer = await Issuer.discover(issuerUrl);
console.log('Discovered issuer: %s %O', googleIssuer.issuer, googleIssuer.metadata);
// Register a new client with the issuer
const client = new googleIssuer.Client({
client_id: clientId,
client_secret: clientSecret,
redirect_uris: [redirectUri],
response_types: ['code'],
});
// Generate parameters for the authorization request
const code_verifier = generators.codeVerifier();
const code_challenge = generators.codeChallenge(code_verifier);
const state = generators.state();
const nonce = generators.nonce();
const authorizationUrl = client.authorizationUrl({
scope: 'openid email profile',
code_challenge,
code_challenge_method: 'S256',
state,
nonce,
redirect_uri: redirectUri,
});
console.log(`
Navigate to this URL to start the login flow:\n${authorizationUrl}
`);
} catch (error) {
console.error('Error during OpenID Connect setup:', error);
}
};
main();