npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fluojs/passport

v1.0.3

Published

Strategy-agnostic authentication guard wiring and strategy registry for Fluo.

Downloads

1,466

Readme

@fluojs/passport

Strategy-agnostic auth execution layer for fluo. It routes any AuthStrategy through a generic AuthGuard into the request context, populating requestContext.principal.

Table of Contents

Installation

npm install @fluojs/passport

When to Use

  • When you need to protect routes with authentication and authorization (RBAC/Scopes).
  • When using multiple auth strategies (e.g., JWT, Cookies, API Keys) in the same application.
  • When you need a bridge to existing Passport.js strategies.
  • When implementing refresh token rotation or account-linking policies.

Quick Start

1. Register Modules

Define your strategies and register them using PassportModule.forRoot(...).

import { Inject, Module } from '@fluojs/core';
import type { GuardContext } from '@fluojs/http';
import { DefaultJwtVerifier, JwtModule } from '@fluojs/jwt';
import { AuthenticationRequiredError, PassportModule, type AuthStrategy } from '@fluojs/passport';

@Inject(DefaultJwtVerifier)
export class BearerJwtStrategy implements AuthStrategy {
  constructor(private readonly verifier: DefaultJwtVerifier) {}

  async authenticate(context: GuardContext) {
    const authorization = context.requestContext.request.headers.authorization;
    const [scheme, token] = typeof authorization === 'string' ? authorization.split(' ') : [];

    if (scheme !== 'Bearer' || !token) {
      throw new AuthenticationRequiredError('Bearer access token is required.');
    }

    return this.verifier.verifyAccessToken(token);
  }
}

@Module({
  imports: [
    JwtModule.forRoot({
      algorithms: ['HS256'],
      audience: 'my-app',
      issuer: 'my-api',
      secret: 'your-secure-secret',
    }),
    PassportModule.forRoot(
      { defaultStrategy: 'jwt' },
      [{ name: 'jwt', token: BearerJwtStrategy }],
    ),
  ],
  providers: [BearerJwtStrategy],
})
export class AuthModule {}

JWT-based passport strategies require both pieces of module wiring: JwtModule.forRoot(...) registers DefaultJwtVerifier, and PassportModule.forRoot(...) registers the named strategy that @UseAuth('jwt') resolves. Returning the DefaultJwtVerifier.verifyAccessToken(...) result preserves the normalized principal contract (subject, claims, issuer, audience, roles, and scopes) that AuthGuard writes to requestContext.principal.

2. Protect Routes

Use @UseAuth() and @RequireScopes() to enforce authentication.

import { Controller, Get, type RequestContext } from '@fluojs/http';
import { UseAuth, RequireScopes } from '@fluojs/passport';

@Controller('/profile')
export class ProfileController {
  @Get('/')
  @UseAuth('jwt')
  @RequireScopes('profile:read')
  async getProfile(input: never, ctx: RequestContext) {
    return { user: ctx.principal };
  }
}

Common Patterns

Passport.js Bridge

Easily adapt any standard Passport.js strategy (like passport-google-oauth20) to work with fluo's DI and async lifecycle.

const googleBridge = createPassportJsStrategyBridge('google', GoogleStrategy, {
  mapPrincipal: ({ user }) => ({ subject: user.id, claims: user }),
});

The bridge settles each Passport.js strategy execution exactly once. A strategy must call one of the bound Passport actions (success, fail, redirect, pass, or error); promise rejections, promise completion without an action, and callback-style executions that exceed the bounded action timeout become authentication failures instead of leaving the request unresolved. Custom mapPrincipal functions must return a valid fluo Principal with a non-empty subject and object claims.

Cookie Auth Preset

Use CookieAuthModule.forRoot(...) when your app authenticates requests from HTTP cookies.

import { Module } from '@fluojs/core';
import { JwtModule } from '@fluojs/jwt';
import {
  CookieAuthModule,
  CookieAuthStrategy,
  COOKIE_AUTH_STRATEGY_NAME,
  PassportModule,
} from '@fluojs/passport';

@Module({
  imports: [
    CookieAuthModule.forRoot(),
    JwtModule.forRoot({
      algorithms: ['HS256'],
      secret: 'your-secure-secret',
    }),
    PassportModule.forRoot(
      { defaultStrategy: COOKIE_AUTH_STRATEGY_NAME },
      [{ name: COOKIE_AUTH_STRATEGY_NAME, token: CookieAuthStrategy }],
    ),
  ],
})
export class AuthModule {}

Import CookieAuthModule.forRoot(...), JwtModule.forRoot(...), and PassportModule.forRoot(...) together when you want cookie-auth support in an application module. The cookie preset provides CookieAuthStrategy and cookie options; JWT verification still comes from @fluojs/jwt, and the passport registry still comes from PassportModule.forRoot(...).

CookieAuthStrategy preserves the normalized JWT principal contract from @fluojs/jwt, including subject, claims, issuer, audience, roles, and scopes.

Cookie access tokens must be non-empty strings. Missing cookies can resolve to { authenticated: false } only when requireAccessToken: false; malformed present cookie values always fail authentication before JWT verification.

CookieManager appends access-token and refresh-token Set-Cookie values without overwriting cookies that were already placed on the response, even when the underlying adapter stores the existing header with different casing such as set-cookie.

Protected routes must keep using @UseAuth(...). If you configure requireAccessToken: false, a missing cookie resolves to an explicit unauthenticated result instead of an anonymous principal, so protected routes still reject the request.

Use @UseOptionalAuth(...) only on routes that intentionally support both signed-in and guest callers:

import { Controller, Get, type RequestContext } from '@fluojs/http';
import { UseOptionalAuth } from '@fluojs/passport';

@Controller('/session')
export class SessionController {
  @Get('/')
  @UseOptionalAuth('cookie')
  getSession(_input: never, ctx: RequestContext) {
    return { subject: ctx.principal?.subject ?? null };
  }
}

Refresh Token Lifecycle

The package provides a built-in RefreshTokenStrategy plus the RefreshTokenModule and RefreshTokenService contract for secure token rotation and revocation.

import { Module } from '@fluojs/core';
import { Controller, Post, type RequestContext } from '@fluojs/http';
import {
  PassportModule,
  REFRESH_TOKEN_STRATEGY_NAME,
  RefreshTokenModule,
  RefreshTokenStrategy,
  UseAuth,
} from '@fluojs/passport';

@Module({
  imports: [
    RefreshTokenModule.forRoot(MyRefreshTokenService),
    PassportModule.forRoot(
      { defaultStrategy: REFRESH_TOKEN_STRATEGY_NAME },
      [{ name: REFRESH_TOKEN_STRATEGY_NAME, token: RefreshTokenStrategy }],
    ),
  ],
  providers: [MyRefreshTokenService],
})
export class AuthModule {}

@Controller('/auth')
export class AuthController {
  @Post('/refresh')
  @UseAuth('refresh-token')
  async refresh(input: never, ctx: RequestContext) {
    return ctx.principal; // Contains new token pair
  }
}

Import RefreshTokenModule.forRoot(...) alongside PassportModule.forRoot(...) so the refresh-token strategy and shared REFRESH_TOKEN_SERVICE alias are available in the same module wiring.

RefreshTokenStrategy reads tokens from body.refreshToken, Authorization: Bearer ..., or x-refresh-token; malformed non-string tokens fail authentication. After rotation, it trusts the normalized access-token principal subject returned by @fluojs/jwt. JwtRefreshTokenAdapter requires a secret and a backing store; store: 'memory' is for development and single-instance deployments only, and rotation detects reuse through the store consume contract.

Account Linking and Status

Use createConservativeAccountLinkPolicy(...) and resolveAccountLinking(...) to model identity-link decisions. The default conservative policy links one unambiguous existing account link or user-confirmed matches, reports multiple existing links as conflicts, and otherwise creates, skips, rejects, or reports conflicts deterministically.

createPassportPlatformStatusSnapshot(...) and createPassportPlatformDiagnosticIssues(...) expose readiness/health diagnostics for registered strategies, default strategy configuration, presets, and refresh-token store readiness.

Public API Overview

Decorators

  • @UseAuth(strategyName): Attaches AuthGuard and sets the active strategy.
  • @UseOptionalAuth(strategyName): Attaches AuthGuard but allows routes without scopes to continue when the strategy reports missing credentials.
  • @RequireScopes(...scopes): Enforces specific scope requirements.

Module and Guard Entry Points

  • PassportModule: Module entry point for passport strategy wiring.
  • AuthGuard: The HTTP guard that executes the strategy chain and enforces required scopes.
  • PassportModuleOptions, AuthStrategyRegistration, AuthStrategyRegistry, AuthGuardContract: Strategy registry and guard wiring contracts.

Strategy Contracts and Errors

  • AuthStrategy: The contract for implementing custom authentication logic.
  • AuthRequirement: Route-level metadata for the selected strategy, optional-auth mode, and required scopes.
  • AuthStrategyResult, AuthOptionalResult, AuthHandledResult: Strategy return variants for principals, intentionally missing credentials, and fully handled responses.
  • AuthStrategyResolutionError, AuthenticationRequiredError, AuthenticationFailedError, AuthenticationExpiredError: Public errors used by guards and strategy adapters for registry misses, missing credentials, invalid credentials, and expired credentials.

Metadata and Scope Helpers

  • defineAuthRequirement(...), getOwnAuthRequirement(...), getAuthRequirement(...): Public helpers for reading and writing auth requirement metadata when integrating custom decorators or tooling with AuthGuard.
  • Scope requirements are normally authored with @RequireScopes(...); lower-level scope normalization helpers remain internal and are not part of the package root export.

Cookie Auth Preset

  • CookieAuthModule: Module entry point for the built-in cookie-auth preset.
  • CookieAuthStrategy, COOKIE_AUTH_STRATEGY_NAME, COOKIE_AUTH_OPTIONS, DEFAULT_COOKIE_AUTH_OPTIONS: Cookie strategy wiring tokens and defaults.
  • CookieAuthOptions, CookieAuthPresetConfig, CookieManagerConfig, CookieOptions, SetCookieOptions: Cookie strategy and response cookie configuration types.
  • CookieManager: Utility for setting and clearing HttpOnly access/refresh token cookies.
  • Cookie helpers: createCookieAuthPreset, createCookieAuthStrategyRegistration, createCookieManager, normalizeCookieAuthOptions.

Refresh Token Preset

  • RefreshTokenModule: Module entry point for the built-in refresh-token preset.
  • RefreshTokenStrategy, REFRESH_TOKEN_STRATEGY_NAME, REFRESH_TOKEN_SERVICE: Refresh-token strategy and service alias wiring.
  • RefreshTokenService, RefreshTokenInput, RefreshTokenAuthResult: Application service contract and exchange payload shapes.
  • JwtRefreshTokenAdapter: Bridges @fluojs/jwt refresh logic to the passport interface.
  • REFRESH_TOKEN_MODULE_OPTIONS, RefreshTokenModuleOptions: JWT-backed refresh-token adapter configuration token and options, including the required secret and store contract.
  • Refresh helpers: createRefreshTokenStrategyRegistration.

Passport.js Bridge

  • createPassportJsStrategyBridge(...): Adapts Passport.js strategies to fluo AuthStrategy.
  • PassportJsAuthStrategy, PassportJsStrategyLike, PassportJsPrincipalMapperInput, PassportJsPrincipalMapper, PassportJsAuthStrategyOptions, PassportJsStrategyBridge: Bridge strategy, mapper, configuration, and provider bundle contracts.

Account Linking

  • ACCOUNT_LINKING_POLICY: DI token for registering an account-linking policy implementation.
  • createConservativeAccountLinkPolicy(...), resolveAccountLinking(...): Conservative default policy and resolver for identity-link decisions.
  • AccountIdentity, AccountLinkCandidate, AccountLinkAttempt, AccountLinkContext, AccountLinkPolicy, AccountLinkPolicyDecision, AccountLinkingOptions, AccountLinkingResolution: Account-linking input, policy, and result contracts.
  • AccountLinkConflictError, AccountLinkRejectedError: Errors raised for ambiguous or rejected account-linking attempts.

Status and Diagnostics

  • createPassportPlatformStatusSnapshot(...): Creates a runtime platform snapshot for strategy registry, preset readiness, ownership, and telemetry labels.
  • createPassportPlatformDiagnosticIssues(...): Emits diagnostic issues for empty registries, missing default strategies, cookie preset readiness, and refresh-token backing store readiness.
  • PassportPlatformStatusSnapshot, PassportStatusAdapterInput: Status helper input/output contracts.

UseOptionalAuth only bypasses missing credentials when no scopes are required; scoped routes still need a principal. Passport.js bridge redirect() commits the response and skips the protected handler, while pass() and strategy completion without a Passport action are authentication failures.

Related Packages

  • @fluojs/jwt: The underlying token core for JWT-based strategies.
  • @fluojs/http: Provides the routing and guard infrastructure.

Example Sources

  • packages/passport/src/guard.test.ts: Guard execution and scope enforcement patterns.
  • packages/passport/src/adapters/passport-js.ts: Implementation of the Passport.js bridge.
  • examples/auth-jwt-passport/src/auth/bearer.strategy.ts: JWT strategy implementation.