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

ngx-oauth

v8.0.5

Published

A fully OAuth2.1 compliant angular library

Downloads

2,090

Readme

ngx-oauth

A fully OAuth 2.1 / OpenID Connect compliant library for Angular. Zoneless, signal-based, SSR-safe.

Supports Authorization Code + PKCE, Implicit, Resource Owner Password, and Client Credentials flows, with OpenID Connect autodiscovery, JWT verification (jose), automatic token refresh, and an authenticated fetch.

Requirements

  • Angular 21+ (@angular/core, @angular/common, @angular/forms)
  • @angular/material (only for the optional <oauth-login> component)
  • jose >= 6 (JWT verification)

Install

npm install ngx-oauth jose

Configure

Register the config in your ApplicationConfig (or module) with provideOAuthConfig.

import { ApplicationConfig, provideZonelessChangeDetection } from '@angular/core'
import { provideOAuthConfig } from 'ngx-oauth'

export const appConfig: ApplicationConfig = {
  providers: [
    provideZonelessChangeDetection(),
    provideOAuthConfig({
      config: {
        // OpenID Connect autodiscovery — endpoints resolved from issuerPath/.well-known
        issuerPath: 'https://your-idp.com/realms/realm',
        clientId: 'your-client-id',
        scope: 'openid profile email',
        pkce: true
      }
    })
  ]
}

Or configure endpoints manually instead of issuerPath:

provideOAuthConfig({
  config: {
    authorizePath: 'https://your-idp.com/authorize',
    tokenPath: 'https://your-idp.com/token',
    revokePath: 'https://your-idp.com/revoke',
    userPath: 'https://your-idp.com/userinfo',
    clientId: 'your-client-id',
    scope: 'openid profile email',
    pkce: true
  }
})

OAuthConfig

| Option | Description | |---|---| | config | Flow config — one of OpenIdConfig, AuthorizationCodePKCEConfig, ImplicitConfig, ResourceOwnerConfig, ClientCredentialConfig. | | storageKey | localStorage key for the token. Default 'token'. Accepts a Signal<string> for a reactive (e.g. per-site) key. | | ignorePaths | RegExp[] — requests whose path matches are sent without an Authorization header by OAUTH_FETCH. | | strictJwt | Verify id_token signature against the IdP JWKS. Default true. |

Public clients (SPA): use Authorization Code + PKCE (pkce: true) and do not set clientSecret. A secret in browser code is not confidential and buys no security.

Usage

Inject the OAUTH token to drive the flow. All state is exposed as signals.

import { Component, inject } from '@angular/core'
import { OAUTH, OAuthType } from 'ngx-oauth'

@Component({ /* ... */ })
export class LoginComponent {
  private readonly oauth = inject(OAUTH)

  readonly status = this.oauth.status          // Signal<OAuthStatus>
  readonly isAuthorized = this.oauth.isAuthorized  // Signal<boolean>
  readonly token = this.oauth.token            // WritableSignal<OAuthToken>

  // Authorization Code / Implicit — redirects to the IdP
  login() {
    this.oauth.login({
      redirectUri: `${location.origin}/callback`,
      responseType: OAuthType.AUTHORIZATION_CODE // or OAuthType.IMPLICIT
    })
  }

  // Resource Owner Password
  loginPassword(username: string, password: string) {
    this.oauth.login({ username, password })
  }

  // Client Credentials — no parameters
  loginClient() {
    this.oauth.login()
  }

  logout() {
    this.oauth.logout()
  }
}

Handling the redirect callback

On your callback route, call oauthCallback to complete the Authorization Code (PKCE) or Implicit exchange:

import { Component, inject } from '@angular/core'
import { OAUTH } from 'ngx-oauth'

@Component({ template: '' })
export class CallbackComponent {
  constructor() {
    inject(OAUTH).oauthCallback() // reads window.location by default
  }
}

Server-side rendering (SSR)

oauthCallback, login, and logout need browser APIs (location, localStorage) and finish with a redirect, so they must run on the client, not during SSR. If a route guard runs them server-side and returns a redirect, the server emits an HTTP 302 that navigates the browser away before it can complete the flow — the login silently fails.

Preferred — render the callback route on the client. When the route is statically addressable, set RenderMode.Client in app.routes.server.ts; the server sends a shell and the browser performs the whole navigation (running the guard once, on the client):

import { RenderMode, ServerRoute } from '@angular/ssr'

export const serverRoutes: ServerRoute[] = [
  { path: 'oauth_callback', renderMode: RenderMode.Client },
  { path: '**', renderMode: RenderMode.Server }
]

When the route can't be targeted — e.g. it's nested under a dynamic prefix like :tenant/:locale/oauth_callback that no static ServerRoute path matches (there is no matcher function, and ** is a trailing-only catch-all) — defer inside the guard instead. Return early on the server so the route renders without redirecting; the client re-runs the guard on initial navigation and completes the exchange:

import { inject, PLATFORM_ID } from '@angular/core'
import { isPlatformServer } from '@angular/common'
import { CanActivateFn } from '@angular/router'
import { OAUTH } from 'ngx-oauth'

export const oauthCallbackGuard: CanActivateFn = async () => {
  if (isPlatformServer(inject(PLATFORM_ID))) return true // defer — let the client do it
  await inject(OAUTH).oauthCallback()
  return true // …then redirect to your post-login target
}

Apply the same isPlatformServer guard to your login/logout routes for the same reason.

OAUTH API

| Member | Type | Description | |---|---|---| | login(params?) | Promise<void> | Start a flow; params determine which (see above). | | logout(next?, state?) | Promise<void> | End session (RP-initiated logout if logoutPath, else token revoke). | | oauthCallback(url?) | Promise<void> | Complete a redirect flow. | | status | Signal<OAuthStatus> | NOT_AUTHORIZED | AUTHORIZED | DENIED. | | isAuthorized | Signal<boolean> | | | token | WritableSignal<OAuthToken> | Persisted token; auto-refreshed on expiry. | | type | Signal<OAuthType> | Active grant type. | | state | Signal<string> | state returned from the redirect. |

Authenticated fetch

OAUTH_FETCH is a drop-in fetch that attaches the bearer token, refreshes it when expired, and skips paths in ignorePaths.

import { inject } from '@angular/core'
import { OAUTH_FETCH } from 'ngx-oauth'

const fetch = inject(OAUTH_FETCH)
const res = await fetch('/api/resource')

User info

OAUTH_USER is an Angular resource resolving the user profile — from the verified id_token when present, otherwise from the userinfo endpoint.

import { inject } from '@angular/core'
import { OAUTH_USER } from 'ngx-oauth'

const user = inject(OAUTH_USER) // resource<UserInfo | undefined>
// user.value(), user.isLoading(), ...

Login component (optional)

A ready-made Material login/menu button lives in the ngx-oauth/component entry point.

import { OAuthLoginComponent } from 'ngx-oauth/component'

@Component({
  imports: [OAuthLoginComponent],
  template: `<oauth-login [config]="{ redirectUri, responseType }" [i18n]="i18n" />`
})

Labels are customizable via the i18n input (OAuthLoginI18n).

License

MIT