JSPM

  • Created
  • Published
  • Downloads 4060970
  • Score
    100M100P100Q196040F
  • License MIT

High-Level OAuth 2 / OpenID Connect Client API for JavaScript Runtimes

Package Exports

  • openid-client
  • openid-client/package.json

Readme

High-Level OAuth 2 / OpenID Connect Client API for JavaScript Runtimes

TODO

Features

The following features are currently in scope and implemented in this software:

  • Authorization Server Metadata discovery
  • Authorization Code Flow (profiled under OpenID Connect 1.0, OAuth 2.0, OAuth 2.1, FAPI 1.0 Advanced, and FAPI 2.0)
  • Refresh Token, Device Authorization, and Client Credentials Grants
  • Demonstrating Proof-of-Possession at the Application Layer (DPoP)
  • Token Introspection and Revocation
  • Pushed Authorization Requests (PAR)
  • UserInfo and Protected Resource Requests
  • Authorization Server Issuer Identification
  • JWT Secured Introspection, Response Mode (JARM), Authorization Request (JAR), and UserInfo
Auth0 by Okta

If you want to quickly add authentication to JavaScript apps, feel free to check out Auth0's JavaScript SDK and free plan. Create an Auth0 account; it's free!

Certification

OpenID Certification

Filip Skokan has certified that this software conforms to the Basic, FAPI 1.0, and FAPI 2.0 Relying Party Conformance Profiles of the OpenID Connectβ„’ protocol.

πŸ’— Help the project

Support from the community to continue maintaining and improving this module is welcome. If you find the module useful, please consider supporting the project by becoming a sponsor.

Quick start

import * as client from 'openid-client'

let server!: URL
let clientId!: string
let clientSecret!: string
let config: client.Configuration = await client.discovery(
  server,
  clientId,
  clientSecret,
)

Authorization Code Flow

Authorization Code flow is for obtaining Access Tokens (and optionally Refresh Tokens) to use with third party APIs.

When you want to have your end-users authorize or authenticate you need to send them to the authorization server's authorization_endpoint. Consult the web framework of your choice on how to redirect but here's how to get the authorization endpoint's URL with parameters already encoded in the query to redirect to.

/**
 * Value used in the authorization request as redirect_uri pre-registered at the
 * Authorization Server.
 */
let redirect_uri!: string
let scope!: string
/**
 * The following MUST be generated for every redirect to the
 * authorization_endpoint. You must store the code_verifier and state in the
 * end-user session such that it can be recovered as the user gets redirected
 * from the authorization server back to your application.
 */
let code_verifier: string = client.randomPKCECodeVerifier()
let code_challenge: string =
  await client.calculatePKCECodeChallenge(code_verifier)
let state!: string

let parameters: Record<string, string> = {
  redirect_uri,
  scope,
  code_challenge,
  code_challenge_method: 'S256',
}

if (
  config.serverMetadata().code_challenge_methods_supported?.includes('S256') !==
  true
) {
  /**
   * We cannot be sure the server supports PKCE so we're going to use state too.
   * Use of PKCE is backwards compatible even if the AS doesn't support it which
   * is why we're using it regardless.
   */
  state = client.randomState()
  parameters.state = state
}

let redirectTo: URL = client.buildAuthorizationUrl(config, parameters)

// now redirect the user to redirectTo.href
console.log('redirecting to', redirectTo.href)

When end-users are redirected back to your redirect_uri your application consumes the callback and passes in the code_verifier to include it in the authorization code grant token exchange.

let getCurrentUrl!: (...args: any) => URL

let tokens: client.TokenEndpointResponse = await client.authorizationCodeGrant(
  config,
  getCurrentUrl(),
  {
    pkceCodeVerifier: code_verifier,
    expectedState: state,
  },
)

console.log('Token Endpoint Response', tokens)

You can then fetch a protected resource response

let protectedResourceResponse: Response = await client.fetchProtectedResource(
  config,
  tokens.access_token,
  new URL('https://rs.example.com/api'),
  'GET',
)

console.log(
  'Protected Resource Response',
  await protectedResourceResponse.json(),
)

Device Authorization Grant (Device Flow)

let scope!: string
let response = await client.initiateDeviceAuthorization(config, { scope })

console.log('User Code:', response.user_code)
console.log('Verification URI:', response.verification_uri)
console.log('Verification URI (complete):', response.verification_uri_complete)

You will display the instructions to the end-user and have them directed at verification_uri or verification_uri_complete, afterwards you can start polling for the Device Access Token Response.

let tokens: client.TokenEndpointResponse =
  await client.pollDeviceAuthorizationGrant(config, response)

console.log('Token Endpoint Response', tokens)

This will poll in a regular interval and only resolve with tokens once the end-user authenticates.

Client Credentials Grant

Client Credentials flow is for obtaining Access Tokens to use with third party APIs on behalf of your application, rather than an end-user which was the case in previous examples.

let scope!: string
let resource!: string

let tokens: client.TokenEndpointResponse = await lib.clientCredentialsGrant(
  config,
  { scope, resource },
)

console.log('Token Endpoint Response', tokens)

API Reference

openid-client is distributed via npmjs.com and github.com.

Examples

example ESM import

import * as client from 'openid-client'
  • Authorization Code Flow (OAuth 2.0) - source
  • Authorization Code Flow (OpenID Connect) - source | diff
  • Extensions
    • JWT Secured Authorization Request (JAR) - source | diff
    • JWT Secured Authorization Response Mode (JARM) - source | diff
    • Pushed Authorization Request (PAR) - source | diff

Supported Runtimes

The supported JavaScript runtimes include those that support the utilized Web API globals and standard built-in objects. These are (but are not limited to):

  • Browsers
  • Bun
  • Cloudflare Workers
  • Deno
  • Electron
  • Node.js[^nodejs]
  • Vercel's Edge Runtime

Supported Versions

Version Security Fixes πŸ”‘ Other Bug Fixes 🐞 New Features ⭐ Runtime and Module type
v6.x βœ… βœ… βœ… Universal[^universal] ESM[^cjs]
v5.x βœ… ❌ ❌ Node.js CJS + ESM

[^nodejs]: Node.js v20.x as baseline is required

[^universal]: Assumes runtime support of WebCryptoAPI and Fetch API

[^cjs]: CJS style require('openid-client') is possible in Node.js versions where process.features.require_module is true or with the --experimental-require-module Node.js CLI flag.