{"id":12744,"library":"oauth4webapi","title":"Low-Level OAuth 2 / OpenID Connect Client API","description":"oauth4webapi is a low-level JavaScript client library for implementing OAuth 2.1, OAuth 2.0 (with Security BCPs), FAPI 2.0, and OpenID Connect protocols. It provides a comprehensive set of routines for authorization server metadata discovery, various grant flows (Authorization Code Flow with PKCE, Refresh Token, Device Authorization, CIBA, Client Credentials), DPoP, Token Introspection/Revocation, PAR, UserInfo requests, and JWT-secured mechanisms. The library emphasizes secure, up-to-date best practices and is designed to run consistently across browser and non-browser JavaScript runtimes, including Node.js, Deno, and Bun. Currently at version 3.8.5, it receives frequent patch and minor releases, indicated by the detailed changelog. A key differentiator is its zero-dependency footprint and OpenID Connect certification, promoting high-assurance security standards without external dependencies.","status":"active","version":"3.8.5","language":"javascript","source_language":"en","source_url":"https://github.com/panva/oauth4webapi","tags":["javascript","access token","auth","authentication","authorization","basic","browser","bun","certified","typescript"],"install":[{"cmd":"npm install oauth4webapi","lang":"bash","label":"npm"},{"cmd":"yarn add oauth4webapi","lang":"bash","label":"yarn"},{"cmd":"pnpm add oauth4webapi","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"oauth4webapi is an ESM-only package. Direct CommonJS 'require' is not supported. Use dynamic import for CJS contexts or ensure your environment supports ESM.","wrong":"const oauth = require('oauth4webapi')","symbol":"oauth","correct":"import * as oauth from 'oauth4webapi'"},{"note":"While the library is often imported as a namespace, individual functions like `discover` can be destructured for tree-shaking and clearer usage.","wrong":"import oauth from 'oauth4webapi'; oauth.discover(...)","symbol":"discover","correct":"import { discover } from 'oauth4webapi'"},{"note":"Utilities for PKCE (Proof Key for Code Exchange) are directly exportable. This is a common pattern for specific cryptographic operations.","symbol":"generatePKCE","correct":"import { generatePKCE } from 'oauth4webapi'"}],"quickstart":{"code":"import { discover, calculatePKCEChallenge, generatePKCE, authorizationUrl, processAuthorizationResponse, exchangeCode, Issuer, Client, TokenEndpointResponse, JWKS } from 'oauth4webapi';\n\nconst as = await discover(new URL('https://accounts.google.com/.well-known/openid-configuration'));\n\nconst client: Client = {\n  client_id: process.env.GOOGLE_CLIENT_ID ?? '',\n  client_secret: process.env.GOOGLE_CLIENT_SECRET ?? '',\n  token_endpoint_auth_method: 'client_secret_post'\n};\n\nconst redirect_uri = 'http://localhost:3000/callback';\n\nasync function initiateOAuthFlow() {\n  const pkce = generatePKCE();\n  const code_challenge = await calculatePKCEChallenge(pkce);\n\n  const authUrl = new URL(authorizationUrl(as, client, {\n    redirect_uri,\n    scope: 'openid email profile',\n    response_type: 'code',\n    code_challenge,\n    code_challenge_method: 'S256',\n    nonce: 'some-random-nonce'\n  }));\n  console.log('Please visit this URL to authenticate:', authUrl.toString());\n  // In a real application, you would redirect the user to authUrl.\n  // For this example, you'd manually visit and get the code from the callback.\n}\n\nasync function handleCallback(requestUrl: string) {\n  const currentUrl = new URL(requestUrl);\n  const params = oauth.validateAuthResponse(as, client, currentUrl);\n\n  if (oauth.is= (params instanceof Error)) {\n    console.error('Authorization response error:', params);\n    return;\n  }\n\n  const response = await exchangeCode(as, client, params.code, {\n    redirect_uri,\n    code_verifier: 'your_pkce_code_verifier_here' // Replace with actual verifier from initiateOAuthFlow\n  });\n\n  if (response instanceof Error) {\n    console.error('Token exchange error:', response);\n    return;\n  }\n\n  console.log('Access Token:', response.access_token);\n  console.log('ID Token:', response.id_token);\n\n  // Further validation and usage of tokens would follow\n}\n\n// Example usage (simplified for quickstart)\ninitiateOAuthFlow();\n// To test handleCallback, you'd simulate a redirect after authentication\n// handleCallback('http://localhost:3000/callback?code=YOUR_CODE_HERE&state=YOUR_STATE_HERE');\n","lang":"typescript","description":"This quickstart demonstrates a basic OpenID Connect Authorization Code Flow with PKCE, covering discovery, authorization URL generation, and code exchange for tokens using Google as the IdP. It highlights key functions like `discover`, `generatePKCE`, `authorizationUrl`, and `exchangeCode`."},"warnings":[{"fix":"Migrate your project to use ES Modules, or use `import()` for dynamic loading in CommonJS contexts. Ensure your `package.json` specifies `\"type\": \"module\"` if using Node.js ESM.","message":"oauth4webapi is an ESM-only package. Projects requiring CommonJS must use dynamic import() or transpile their code to ESM. Direct `require()` statements will result in runtime errors.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Thoroughly test cryptographic operations in your target runtime environments. Consult runtime-specific documentation for Web Cryptography API differences. Ensure environments provide `crypto.subtle`.","message":"The library relies heavily on the Web Cryptography API, which may have varying levels of support or specific quirks across different JavaScript runtimes (e.g., Node.js, Deno, Bun, Cloudflare Workers, browsers). While efforts are made for compatibility, edge cases can arise.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always store and retrieve PKCE code verifiers, nonces, and state parameters securely for validation. Never expose sensitive client secrets on the client-side. Follow the examples and best practices outlined in the documentation meticulously.","message":"As a low-level client, oauth4webapi requires developers to manage the entire OAuth/OIDC flow, including PKCE verifiers, nonces, state parameters, and cookie/session management. Errors in handling these can lead to security vulnerabilities.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always implement the Authorization Code Flow with PKCE (Proof Key for Code Exchange) as per OAuth 2.1 and current BCPs for public clients. Avoid implicit flow entirely. Review the FAPI 2.0 examples.","message":"Older, less secure OAuth 2.0 flows or patterns without PKCE are discouraged. While the library supports various profiles, it promotes the latest Security Best Current Practices (BCP) and FAPI 2.0 standards.","severity":"deprecated","affected_versions":"<3.0.0 (and continued best practice in >=3.0.0)"},{"fix":"Monitor for any unexpected behavior related to cryptographic operations (e.g., `generateKeyPair`, `sign`, `verify`) after updating to v3.8.5 or later. If issues arise, consult the upstream Web Cryptography specification changes.","message":"A recent refactor in v3.8.5 accounts for an upcoming Web Cryptography change, which might subtly affect existing integrations relying on specific Web Crypto behaviors, though it's likely a forward-compatibility fix.","severity":"gotcha","affected_versions":">=3.8.5"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Change your import statement to `import * as oauth from 'oauth4webapi'`. If your project is CommonJS, consider setting `\"type\": \"module\"` in `package.json` or use `import('oauth4webapi')` dynamically.","cause":"Attempting to use `require('oauth4webapi')` in an ES Module context, or in a Node.js project configured for ESM when the library only exports ESM.","error":"TypeError: require is not a function"},{"fix":"Ensure you are running in a modern JavaScript runtime (Node.js >= 15, modern browsers, Deno, Bun, Cloudflare Workers). For older Node.js, you might need a polyfill, though it's generally recommended to upgrade.","cause":"The runtime environment (e.g., older Node.js versions or specific browser environments) does not provide a global `crypto` object with the Web Cryptography API.","error":"ReferenceError: crypto is not defined"},{"fix":"Verify that your runtime fully supports the Web Cryptography API methods used by oauth4webapi. In browser contexts, ensure your application is served over HTTPS. If in Node.js, ensure sufficient version.","cause":"The `crypto.subtle` object is available, but the specific Web Cryptography API method required (e.g., `generateKeyPair` for DPoP) is not implemented or is not available in the current context (e.g., secure contexts only in browsers).","error":"TypeError: subtle.generateKeyPair is not a function"},{"fix":"Review the DPoP nonce handling in your custom `fetch` implementation. Ensure it correctly processes `DPoP-Nonce` headers and updates the nonce accordingly, or consider using the library's default fetch behavior if possible. (Addressed in v3.8.2 with a workaround, but custom fetch still needs care.)","cause":"When providing a custom `fetch` implementation, DPoP nonces might not be correctly handled or cached, leading to replay protection issues or failed requests.","error":"Error: DPoP nonce caching caveats with customFetch"}],"ecosystem":"npm"}