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

@sftech/ng-auth

v2.1.1

Published

![Version](https://img.shields.io/badge/version-2.0.2-blue)

Downloads

464

Readme

@sftech/ng-auth

Version

Angular library for OAuth2/OIDC authentication with anonymous session fallback, guards, and HTTP interceptor.

Installation

npm install @sftech/ng-auth

Peer Dependencies

| Package | Minimum Version | |---------|----------------| | @angular/common | >=20.0.0 | | @angular/core | >=20.0.0 |

Configuration

Add AuthModule.forRoot() to your app.config.ts:

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { AuthModule, IAuthConfig, authenticationInterceptor } from '@sftech/ng-auth';

const authConfig: IAuthConfig = {
    authProvider: 'oauth',               // 'oauth' | 'none'
    authBackendUrl: '/api/auth',         // Backend auth API base URL
    postLogoutRedirectUri: 'http://localhost:4200',
    anonymousFallback: true,             // Optional: enable anonymous sessions (default: false)
    autoRefreshToken: true,              // Optional: enable automatic token refresh (default: true)
    refreshBeforeExpiryMinutes: 1,       // Optional: minutes before expiry to refresh (default: 1)
};

export function appConfig(): ApplicationConfig {
    return {
        providers: [
            importProvidersFrom(AuthModule.forRoot(authConfig)),
            provideHttpClient(withInterceptors([authenticationInterceptor])),
        ],
    };
}

IAuthConfig Reference

interface IAuthConfig {
    /** Authentication provider. Use 'oauth' for OAuth2/OIDC, 'none' to disable auth entirely. */
    authProvider: 'oauth' | 'none';

    /** Base URL of the backend auth API (e.g. '/api/auth' or 'https://api.example.com/auth'). */
    authBackendUrl: string;

    /** URI to redirect to after OAuth provider logout. */
    postLogoutRedirectUri?: string;

    /**
     * When true, users without an OAuth session automatically receive an anonymous session.
     * The anonymous session is created via POST /auth/anonymous. Default: false.
     */
    anonymousFallback?: boolean;

    /** When false, disables automatic token refresh scheduling. Default: true. */
    autoRefreshToken?: boolean;

    /** Minutes before token expiry to trigger a refresh. Default: 1. */
    refreshBeforeExpiryMinutes?: number;
}

Routing

Add the auth routes to your application:

import { Route } from '@angular/router';
import { authenticationGuard } from '@sftech/ng-auth';

export const appRoutes: Route[] = [
    {
        path: 'auth',
        loadChildren: () => import('@sftech/ng-auth').then((m) => m.authRoutes),
    },
    {
        path: 'protected',
        component: MyComponent,
        canActivate: [authenticationGuard],
    },
];

The authRoutes include:

  • /auth/callback - OAuth callback handler (CallbackComponent)
  • /auth/recovery - Anonymous session recovery page (RecoveryComponent)

Features

  • OAuth2/OIDC authentication via backend redirect flow
  • Signal-based reactive authentication state (isAuthenticated, isAnonymous, recoveryCode)
  • Anonymous session fallback with recovery code support
  • Automatic token refresh scheduling based on session expiry
  • Unified auth status endpoint for both OAuth and anonymous sessions
  • Functional guards: authenticationGuard, adminGuard
  • HTTP interceptor that adds withCredentials: true to auth-related requests
  • Session recovery component for restoring anonymous sessions by code
  • localStorage persistence of recovery codes across page refreshes

API Reference

Services

| Service | Description | Key Methods | |---------|-------------|-------------| | AuthenticationService | Signal-based authentication service | checkAuthStatus(), login(), logout(), refreshToken(), recoverByCode(), loadUserInfo() |

Guards

| Guard | Type | Description | |-------|------|-------------| | authenticationGuard | CanActivateFn | Protects routes. Redirects to login when not authenticated. With anonymousFallback: true, creates an anonymous session instead. When authProvider is 'none', allows all access. | | adminGuard | CanActivateFn | Restricts routes to users with the admin role. |

Interceptors

| Interceptor | Description | |-------------|-------------| | authenticationInterceptor | HttpInterceptorFn that adds withCredentials: true to requests matching /api/auth, /api/orchestrator, or /api/orchestrator-db. |

Models

| Model | Description | Factory Methods | |-------|-------------|-----------------| | AuthStatus | Represents authentication state | fromDto(), fromAnonymousSessionDto(), notAuthenticated(), authenticated() | | UserInfo | OAuth user profile data | fromDto() |

DTOs

| DTO | Description | |-----|-------------| | IAuthStatusResponseDto | Response from GET /auth/status. Covers both OAuth and anonymous sessions. | | IAnonymousSessionResponseDto | Response from POST /auth/anonymous and POST /auth/anonymous/recover. Contains full session data. | | ILogoutResponseDto | Response from POST /auth/logout. Includes optional anonymousSession field for fallback setup. | | IUserInfoResponseDto | Response from GET /auth/user. OAuth user profile. | | ITokenRefreshResponseDto | Response from POST /auth/refresh. |

Enums

| Enum | Values | Description | |------|--------|-------------| | EAuthApiEndpoint | STATUS, USER, LOGIN, LOGOUT, REFRESH, ANONYMOUS_CREATE, ANONYMOUS_RECOVER | Backend endpoint path segments | | EAuthFailureReason | Library-defined values | Reason codes returned when authenticated: false | | EAuthStorageKey | RECOVERY_CODE | Keys used for localStorage | | EAuthRole | ADMIN | Role values checked by adminGuard |

DTO Interfaces

IAuthStatusResponseDto

interface IAuthStatusResponseDto {
    authenticated: boolean;
    userId?: string;
    /** Visitor ID for anonymous sessions. Mapped to userId in AuthStatus. */
    visitorId?: string;
    expiresAt?: string;
    timeRemaining?: number;
    reason?: EAuthFailureReason;
    /** Present when the session is an anonymous session (since 2.0.0). */
    isAnonymous?: boolean;
    /** Recovery code for anonymous sessions, returned when isAnonymous is true (since 2.0.0). */
    recoveryCode?: string;
}

IAnonymousSessionResponseDto

interface IAnonymousSessionResponseDto {
    authenticated: boolean;
    isAnonymous: boolean;
    userId: string;
    visitorId: string;
    recoveryCode: string;
    sessionId: string;
    expiresAt: string;
}

ILogoutResponseDto

interface ILogoutResponseDto {
    message: string;
    providerLogoutUrl: string;
    success: boolean;
    /** Anonymous session returned by the backend after OAuth logout when anonymousFallback is true (since 2.0.0). */
    anonymousSession?: {
        sessionId: string;
        userId: string;
        visitorId: string;
        recoveryCode: string;
        expiresAt: string;
    };
}

Usage Examples

Basic Setup (OAuth only)

// app.config.ts
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { AuthModule, IAuthConfig, authenticationInterceptor } from '@sftech/ng-auth';

const authConfig: IAuthConfig = {
    authProvider: 'oauth',
    authBackendUrl: '/api/auth',
};

export function appConfig(): ApplicationConfig {
    return {
        providers: [
            importProvidersFrom(AuthModule.forRoot(authConfig)),
            provideHttpClient(withInterceptors([authenticationInterceptor])),
        ],
    };
}

Advanced: Anonymous Session Fallback

When anonymousFallback: true is set, unauthenticated users automatically receive an anonymous session. This is useful for applications that want to track anonymous activity before users log in.

// app.config.ts
const authConfig: IAuthConfig = {
    authProvider: 'oauth',
    authBackendUrl: '/api/auth',
    anonymousFallback: true,
};
// my.component.ts
import { Component, inject } from '@angular/core';
import { AuthenticationService } from '@sftech/ng-auth';

@Component({
    selector: 'app-my',
    template: `
        <div *ngIf="auth.isAnonymous()">
            You are browsing anonymously.
            Recovery code: {{ auth.recoveryCode() }}
        </div>
        <div *ngIf="auth.isAuthenticated() && !auth.isAnonymous()">
            Welcome, {{ auth.currentUser()?.name }}!
        </div>
    `,
})
export class MyComponent {
    protected auth = inject(AuthenticationService);
}

Advanced: Using AuthenticationService Signals

import { Component, inject } from '@angular/core';
import { AuthenticationService } from '@sftech/ng-auth';

@Component({ ... })
export class MyComponent {
    private auth = inject(AuthenticationService);

    // Signals — use in templates or effects
    isAuthenticated = this.auth.isAuthenticated;  // Signal<boolean>
    isAnonymous = this.auth.isAnonymous;          // Signal<boolean>
    userId = this.auth.userId;                    // Signal<string | undefined>
    currentUser = this.auth.currentUser;          // Signal<UserInfo | null>
    recoveryCode = this.auth.recoveryCode;        // Signal<string | null>
    timeRemaining = this.auth.timeRemaining;      // Signal<number | undefined>

    login() { this.auth.login(); }
    logout() { this.auth.logout().subscribe(); }
}

Advanced: Session Recovery

Users with an anonymous session can obtain a recovery code from auth.recoveryCode(). If they lose their session cookie (e.g., different browser), they can restore the session:

import { Component, inject } from '@angular/core';
import { AuthenticationService } from '@sftech/ng-auth';

@Component({ ... })
export class RecoveryPageComponent {
    private auth = inject(AuthenticationService);

    recover(code: string) {
        this.auth.recoverByCode(code).subscribe((status) => {
            if (status.authenticated) {
                // Session restored successfully
            }
        });
    }
}

The built-in RecoveryComponent (available at the /auth/recovery route) handles this flow automatically.

Advanced: Protecting Admin Routes

import { Route } from '@angular/router';
import { authenticationGuard, adminGuard } from '@sftech/ng-auth';

export const appRoutes: Route[] = [
    {
        path: 'admin',
        component: AdminComponent,
        canActivate: [authenticationGuard, adminGuard],
    },
];

Auth Flows

1. OAuth Login

login() → GET /auth/login?redirect_url=<encoded-origin>/auth/callback → OAuth provider → callback → GET /auth/status → GET /auth/user

The GET /auth/status endpoint is the single unified status check for both OAuth and anonymous sessions.

2. Anonymous Fallback (initial page load, no session)

GET /auth/status → { authenticated: false }
→ POST /auth/anonymous → { authenticated: true, isAnonymous: true, recoveryCode: "..." }

The POST /auth/anonymous response contains all session data needed to construct AuthStatus directly — no follow-up status call is made.

3. Resuming Existing Anonymous Session

GET /auth/status → { authenticated: true, isAnonymous: true, visitorId: "...", recoveryCode: "..." }

A single status call detects the existing anonymous session. The visitorId field is mapped to userId in the AuthStatus model.

4. OAuth Logout with Anonymous Fallback

POST /auth/logout → { success: true, anonymousSession: { ... } }
→ AuthStatus constructed from embedded anonymousSession (no additional calls)

If anonymousSession is absent from the logout response (backend version compatibility), a POST /auth/anonymous call is made as a fallback.

5. Anonymous Logout (reset identity)

clearAuthState()
→ POST /auth/anonymous → { authenticated: true, isAnonymous: true, ... }

There is no /auth/anonymous/logout endpoint. Anonymous logout clears local state and creates a fresh session.

6. Token Refresh

POST /auth/refresh  (OAuth sessions)
GET /auth/status    (anonymous sessions — re-checks the unified endpoint)

Refresh is scheduled automatically based on timeRemaining from the status response. Configure with autoRefreshToken and refreshBeforeExpiryMinutes.

7. Session Recovery

POST /auth/anonymous/recover { recoveryCode } → { authenticated: true, isAnonymous: true, ... }

The response contains full session data. AuthStatus is constructed directly without a follow-up status call.

API Requirements

The library expects the following endpoints on the backend at the configured authBackendUrl:

| Method | Path | Description | |--------|------|-------------| | GET | /status | Unified auth status. Returns OAuth or anonymous session data. | | GET | /user | OAuth user profile. Only called when authenticated: true and not anonymous. | | GET | /login | Initiates OAuth login redirect. Accepts optional redirect_url query parameter (URL-encoded callback URL). When provided, the backend redirects to this URL after OAuth completion instead of its own configured frontendCallbackUrl. Required for Capacitor environments. | | POST | /logout | OAuth logout. Returns optional anonymousSession for fallback. | | POST | /refresh | Refreshes OAuth access token. | | POST | /anonymous | Creates a new anonymous session. Returns full session data. | | POST | /anonymous/recover | Recovers an anonymous session by recovery code. Returns full session data. |

Migration from 1.x

Version 2.0.0 contains breaking changes. If you are upgrading from 1.x, review the following:

Removed Exports

| Symbol | Action Required | |--------|----------------| | IAnonymousLogoutResponseDto | Removed. The /auth/anonymous/logout endpoint does not exist in the backend. No replacement needed — anonymous logout is now client-side only. | | EAuthApiEndpoint.ANONYMOUS_STATUS | Removed. Use the unified EAuthApiEndpoint.STATUS (GET /auth/status) for all session status checks. | | EAuthApiEndpoint.ANONYMOUS_LOGOUT | Removed. Anonymous logout does not call any backend endpoint. | | AuthStatus.fromAnonymousStatusDto() | Removed. Use AuthStatus.fromDto() — it now detects anonymous sessions via the isAnonymous flag automatically. |

Changed Behavior

| Area | Change | |------|--------| | IAuthStatusResponseDto | Extended with isAnonymous?: boolean and recoveryCode?: string fields. The unified GET /auth/status endpoint now returns these fields for anonymous sessions. | | IAnonymousSessionResponseDto | Expanded from a minimal shape to include authenticated, isAnonymous, userId, visitorId, recoveryCode, sessionId, and expiresAt. | | ILogoutResponseDto | Extended with an optional anonymousSession field. When anonymousFallback: true, the backend embeds the new anonymous session in the logout response. | | AuthStatus.fromDto() | Now detects anonymous sessions via the isAnonymous flag in the response and maps visitorId to userId automatically. No code changes needed if you were calling checkAuthStatus(). | | createAnonymousSession() | Uses the POST /auth/anonymous response directly to build AuthStatus — no follow-up GET call. | | recoverByCode() | Uses the POST /auth/anonymous/recover response directly — no follow-up GET call. | | logout() (OAuth) | Reads anonymousSession from the logout response when anonymousFallback: true — no additional POST /auth/anonymous call in the happy path. | | Angular peer dependency | Bumped from >=19.0.0 to >=20.0.0. |

Migration Example

Before (1.x):

// If you referenced removed enum values or DTOs directly:
import {
    EAuthApiEndpoint,
    IAnonymousLogoutResponseDto,
    AuthStatus,
} from '@sftech/ng-auth';

// ANONYMOUS_STATUS and ANONYMOUS_LOGOUT no longer exist:
const anonStatusUrl = EAuthApiEndpoint.ANONYMOUS_STATUS; // ERROR in 2.0.0
const anonLogoutUrl = EAuthApiEndpoint.ANONYMOUS_LOGOUT; // ERROR in 2.0.0

// fromAnonymousStatusDto() no longer exists:
const status = AuthStatus.fromAnonymousStatusDto(dto);   // ERROR in 2.0.0

After (2.0.0):

import { EAuthApiEndpoint, AuthStatus } from '@sftech/ng-auth';

// Use unified STATUS for all session checks:
const statusUrl = EAuthApiEndpoint.STATUS; // '/status'

// fromDto() now handles anonymous sessions automatically:
const status = AuthStatus.fromDto(dto);    // Works for OAuth and anonymous
// Or use fromAnonymousSessionDto() for POST /auth/anonymous responses:
const anonStatus = AuthStatus.fromAnonymousSessionDto(anonDto);

Development

Build

npx nx build ng-auth

Test

npx nx test ng-auth

Lint

npx nx lint ng-auth

Changelog

See CHANGELOG.md

License

MIT