oauth2-server

website·Indexed 31 days ago

https://tsoauth2server.com/

A TypeScript OAuth 2.0 and OpenID Connect (OIDC) server library. It supports various grant types including Authorization Code with PKCE, Client Credentials, Refresh Token, and Token Exchange (RFC 8693), as well as OIDC features like ID Tokens, Discovery, and UserInfo endpoints. The library provides adapters for frameworks such as Fastify and h3, and includes a flexible repository system for entity management.

Tokens
27.1K
Snippets
100
Records
165
Agent score
49%

What's inside oauth2-server

  1. Overview of @jmondi/oauth2-server

    The @jmondi/oauth2-server library is a standards-compliant OAuth 2.0 authorization server for Node.js (requires Node.js 22 or later) written in TypeScript. It implements RFC 6749 and companion RFCs for bearer tokens, revocation, introspection, and token exchange. Key features include signed JWT Access Tokens, default PKCE enforcement, and an optional OpenID Connect layer. The library is framework-agnostic and requires the developer to provide their own storage (via repositories) and routing.
  2. Use the Express adapter to handle OAuth2 requests

    The Express adapter (available in version >2.0.0) provides utility functions to convert between standard Express Request and Response objects and the OAuthRequest and OAuthResponse objects used by the @jmondi/oauth2-server package. This allows the OAuth2 server logic to remain decoupled from the specific web framework while still integrating seamlessly with Express.
  3. Implement OIDC using the Authorization Code Grant

    The OpenID Connect (OIDC) layer is implemented as an extension of the authorization_code grant rather than as a separate provider. ID-token issuance is handled within the AuthCodeGrant class. The non-grant endpoints—UserInfo, discovery, and JWKS—are implemented as methods on the AuthorizationServer class, alongside revoke and introspect.
  4. Convert native Web Request and Response objects using the Vanilla adapter

    The Vanilla adapter (available in version >3.4.0) allows developers to bridge native JavaScript Request and Response objects with the OAuthRequest and OAuthResponse types used by the @jmondi/oauth2-server package. This is essential when integrating the OAuth2 server into environments that use standard Web APIs, such as Hono, Cloudflare Workers, or Bun.
  5. Validate an Access Token in API middleware

    Depending on your architecture, there are two primary ways to validate an Access Token:

    1. Internal Validation (Same Process): If the API and authorization server share the same process, verify the JWT and then read the repository. This is the most performant method.
    2. External Validation (Different Service): If the resource server is a separate service, cannot access the signing key, or must comply with RFC 7662, use the /token/introspect endpoint.
  6. Enforce fail-closed security at consumer-delegated seams

    The library implements a 'fail-closed' security principle at delegation points where security-relevant operations are handed to a consumer. Instead of relying on documentation to warn consumers to implement security checks (like algorithm pinning) in custom interfaces, the library wraps these interfaces to enforce mandatory security guards. This prevents silent security degradations, such as algorithm confusion attacks or nonce-loss vulnerabilities, by throwing explicit errors when security requirements are not met.
  7. Integrate @jmondi/oauth2-server with Fastify

    The Fastify adapter (available in version >2.0.0) provides utility functions to convert Fastify Request and Reply objects into OAuthRequest and OAuthResponse objects, and vice versa. This allows the OAuth2 server logic to operate independently of the underlying web framework while remaining compatible with Fastify.
  8. Handle OIDC Authentication Freshness (prompt and max_age)

    For OpenID Connect (OIDC) compliance, the server must handle prompt and max_age parameters. Since the library cannot see the session, the /authorize route must manually check session freshness:

    • prompt=none: The server must not show login or consent forms. If no session exists or approval is missing, redirect to redirect_uri with error=login_required or error=consent_required and the state parameter.
    • max_age: Compare the last login time with the current time. If the session is older than max_age seconds, force the user to re-authenticate and update authRequest.authTime.
    const authRequest = await authorizationServer.validateAuthorizationRequest(requestFromExpress(req));
    const lastLoginSeconds = req.session.authTime; // set by your login route
    
    const sessionIsStale = 
      authRequest.maxAge !== undefined && 
      (lastLoginSeconds === undefined || lastLoginSeconds + authRequest.maxAge < Math.floor(Date.now() / 1000));
    
    if (!req.user || sessionIsStale) {
      if (authRequest.prompt === "none") {
        const redirect = new URL(String(authRequest.redirectUri));
        redirect.searchParams.set("error", "login_required");
        if (authRequest.state) redirect.searchParams.set("state", authRequest.state);
        res.redirect(redirect.toString());
        return;
      }
      res.redirect("/login");
      return;
    }
    
    authRequest.user = req.user;
    authRequest.authTime = lastLoginSeconds;
  9. Choose the correct OAuth 2.0 grant type

    Select a grant based on the client type and the identity of the token owner:

    • Client Credentials: Use when a machine/server needs a token for itself (no user involved). Requires a Confidential Client.
    • Authorization Code with PKCE: Use for user-facing applications (server apps, browser apps, or native mobile apps). PKCE protects the code from interception and is safe for Public Clients.
    • Refresh Token: Use to obtain a new Access Token after the current one expires without requiring user interaction.
    • Token Exchange: Use to exchange a security token from another system (e.g., a third-party session token) for a token from this server (RFC 8693).
    • Custom Grant: Use as an advanced option by extending the CustomGrant class when no standard grant fits the requirements.
  10. Upgrade ts-oauth2-server to v5

    Upgrading to v5 requires Node.js 22 as the minimum runtime. Update your runtime and CI environment, then reinstall packages. OpenID Connect is introduced in v5 as an optional feature and does not affect existing setups unless the oidc block is configured.
    # Ensure Node.js version is >= 22
    node -v
  11. Implement the Password Grant request and response flow

    To request a token using the password grant, send a POST request to the /token endpoint.

    Request Parameters:

    • grant_type: Must be password.
    • client_id: The registered Client identifier.
    • client_secret: Required for Confidential Clients.
    • username: The user's username.
    • password: The user's password.
    • scope (optional): Space-separated list of requested scopes.

    Response Fields:

    • token_type: Always Bearer.
    • expires_in: Access token lifetime in seconds.
    • access_token: A signed JWT for the resource server.
    • refresh_token: A signed JWT used for the refresh token grant.
    • scope: The granted scopes, space-separated.
    POST /token HTTP/1.1
    Host: example.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=password
    &client_id=xxxxxxxxx
    &client_secret=xxxxxxxxx
    &username=xxxxxxxxx
    &password=xxxxxxxxx
    &scope="contacts.read contacts.write"
  12. Execute the OIDC Authorization Code Flow

    To trigger the OIDC flow, the client must request the openid scope at the /authorize endpoint. Optional scopes include profile, email, address, and phone. Upon exchanging the code at the /token endpoint, the server returns both an Access Token and an ID Token. The Access Token can then be used to query the UserInfo endpoint.