oidc-provider Documentation

repository·main·Indexed 25 days ago

https://github.com/panva/node-oidc-provider

A comprehensive OAuth 2.0 and OpenID Connect (OIDC) Authorization Server implementation for Node.js. Version 9.11.1 supports modern security profiles like FAPI and advanced flows including PKCE, DPoP, and Device Flow. The library provides tools for account discovery via findAccount, interaction handling for login and consent, custom grant type registration, and integration with web frameworks such as Express, Koa, Fastify, Hapi, and NestJS.

Tokens
30.2K
Snippets
61
Records
159
Agent score
87%

What's inside oidc-provider

  1. Overview of implemented specifications

    main

    The oidc-provider module implements a wide range of OAuth 2.0 and OpenID Connect specifications.

    Core Specifications:

    • RFC6749 (OAuth 2.0) & OIDC Core 1.0
    • OIDC Discovery 1.0 & RFC8414 (Authorization Server Metadata)
    • Dynamic Client Registration (OIDC Dynamic Client Registration 1.0, RFC7591, RFC7592)
    • OIDC RP-Initiated Logout 1.0 & OIDC Back-Channel Logout 1.0
    • RFC7009 (Token Revocation)
    • RFC7636 (PKCE)
    • RFC7662 (Token Introspection)
    • RFC8252 (AppAuth for Native Apps)
    • RFC8628 (Device Flow)
    • RFC8705 (MTLS)
    • RFC8707 (Resource Indicators)
    • RFC9101 (JAR)
    • RFC9126 (PAR)
    • RFC9207 (Issuer Identifier in Auth Response)
    • RFC9449 (DPoP)
    • RFC9701 (JWT Response for Introspection)
    • FAPI 1.0 & FAPI 2.0 (Security Profiles)
    • JARM (JWT Secured Authorization Response Mode)
    • CIBA (OIDC Client Initiated Backchannel Authentication)

    Supported Access Token Formats:

    • Opaque
    • JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens

    Experimental Features (Note: Breaking changes may occur in MINOR updates):

    • FAPI-CIBA (Implementers Draft 01)
    • OAuth 2.0 Attestation-Based Client Authentication (Draft 10)
    • OAuth Client ID Metadata Document (CIMD) (Draft 02)
    • OpenID for Verifiable Credential Issuance 1.0
  2. Mount oidc-provider to an existing application

    main

    You can mount a Provider instance to an existing web application using a path prefix (e.g., /oidc).

    Important Considerations:

    • If you use a path prefix, you must update the interactions.url configuration to reflect the new path.
    • Ensure that the authorization server metadata endpoints (like .well-known/openid-configuration) are correctly resolved to the provider's routes based on your issuer identifier.

    Example Scenarios for Metadata Resolution:

    • If issuer is https://op.example.com/oidc and mounted at /oidc: routes must resolve to https://op.example.com/oidc/.well-known/openid-configuration and https://op.example.com/.well-known/oauth-authorization-server/oidc.
    • If issuer is https://op.example.com and mounted at /oidc: routes must resolve to https://op.example.com/.well-known/openid-configuration and https://op.example.com/.well-known/oauth-authorization-server.
  3. Use pre- and post-middlewares with oidc-provider

    main

    Since oidc-provider is built on Koa, you can use provider.use() to add custom middleware. This allows for pre-processing (before the route handler) and post-processing (after the route handler).

    In post-processing, you can inspect ctx.oidc.route to identify which specific OIDC route was executed.

    Available route names for ctx.oidc.route: authorization, backchannel_authentication, challenge, client_delete, client_update, client, code_verification, cors.challenge, cors.credential, cors.device_authorization, cors.discovery, cors.introspection, cors.jwks, cors.openid_credential_issuer, cors.pushed_authorization_request, cors.revocation, cors.token, cors.userinfo, credential, device_authorization, device_resume, discovery, end_session_confirm, end_session_success, end_session, introspection, jwks, openid_credential_issuer, pushed_authorization_request, registration, resume, revocation, token, userinfo.

    provider.use(async (ctx, next) => {
      /** pre-processing
       * you may target a specific action here by matching `ctx.path`
       */
      console.log("pre middleware", ctx.method, ctx.path);
    
      await next();
    
      /** post-processing
       * since internal route matching was already executed, you can target a specific action here,
       * checking `ctx.oidc.route`.
       */
      console.log("post middleware", ctx.method, ctx.oidc.route);
    });
  4. Initialize and run oidc-provider

    main

    You can create an OAuth 2.0 and OpenID Connect authorization server by instantiating the Provider class. The constructor requires an issuer URL and a configuration object. You can then use the .listen() method to start the server on a specific port.

    Note that oidc-provider can be mounted to existing connect, express, fastify, hapi, or koa applications.

    import * as oidc from "oidc-provider";
    
    const provider = new oidc.Provider("http://localhost:3000", {
      // refer to the documentation for other available configuration
      clients: [
        {
          client_id: "foo",
          client_secret: "bar",
          redirect_uris: ["http://localhost:8080/cb"],
          // ... other client properties
        },
      ],
    });
    
    const server = provider.listen(3000, () => {
      console.log(
        "oidc-provider listening on port 3000, check http://localhost:3000/.well-known/openid-configuration",
      );
    });
  5. Configure TLS offloading proxies

    main

    When running oidc-provider behind a TLS offloading proxy (like Nginx), you must ensure the application correctly identifies the original protocol and IP address. This is necessary for generating correct HTTPS URLs and maintaining security.

    1. Configure the Proxy: The proxy must pass X-Forwarded-For and X-Forwarded-Proto headers to the downstream application.
    2. Configure the Application: Set the proxy option to true in your application or provider instance.
    SetupConfiguration
    Standalone oidc-providerprovider.proxy = true
    Mounted to expressprovider.proxy = true
    Mounted to koayourKoaApp.proxy = true
    Mounted to fastifyprovider.proxy = true
    Mounted to hapiprovider.proxy = true
    Mounted to nestprovider.proxy = true
    location / {
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
    
      proxy_pass http://127.0.0.1:8009;
      proxy_redirect off;
    }
  6. Handle events in oidc-provider

    main

    The oidc-provider instance acts as an event emitter. You can listen to various lifecycle events by attaching listeners to the provider instance.

    In event handlers, this refers to the Provider instance. For events that pass a ctx (request context) parameter, ctx.oidc contains an OIDCContext object which provides additional details such as recognized parameters, the loaded client, or the session.

  7. Basic configuration of oidc-provider

    main

    To initialize an oidc-provider instance, import Provider from oidc-provider and instantiate it with an issuer URL and a configuration object. At a minimum, you should define your clients array containing client metadata like client_id, client_secret, and redirect_uris. You can start the server using the provider.listen() method.

    import * as oidc from "oidc-provider";
    
    const provider = new oidc.Provider("http://localhost:3000", {
      // refer to the documentation for other available configuration
      clients: [
        {
          client_id: "foo",
          client_secret: "bar",
          redirect_uris: ["http://localhost:8080/cb"],
          // ... other client properties
        },
      ],
    });
    
    const server = provider.listen(3000, () => {
      console.log(
        "oidc-provider listening on port 3000, check http://localhost:3000/.well-known/openid-configuration",
      );
    });
  8. Define registration and management policies

    main

    Use the policies object within features.registration to intercept and modify client metadata during dynamic registration. Policies execute before standard validation.

    Policy functions receive (ctx, properties) where ctx is the Koa request context and properties is the client metadata object. You can set defaults, force values, or throw an errors.InvalidClientMetadata error to reject the request.

    To assign different policies to the resulting Registration Access Token, update the entity within the final policy:

    ctx.oidc.entities.RegistrationAccessToken.policies = ['update-policy'];
  9. Acknowledge experimental features to suppress warnings

    main

    To suppress experimental feature warnings and ensure your configuration is validated against breaking changes, you must acknowledge the specific version of the experimental feature using the ack property within the feature configuration. If an unacknowledged breaking change is introduced in a newer version of oidc-provider, the server will throw an error during instantiation.

    import * as oidc from 'oidc-provider'
    
    new oidc.Provider('http://localhost:3000', {
      features: {
        webMessageResponseMode: {
          enabled: true,
          ack: 'individual-draft-01', // Use the specific version string provided in the warning
        },
      },
    });