Safeguard
Open Source

angular-oauth2-oidc: Secure OAuth2 and OIDC in Angular

angular-oauth2-oidc is the most widely used OAuth2 and OpenID Connect client for Angular apps. Here is how to wire it up with PKCE, validate tokens correctly, and avoid the config mistakes that leak sessions.

Marcus Chen
DevSecOps Engineer
6 min read

angular-oauth2-oidc is the de facto OAuth2 and OpenID Connect client library for Angular single-page apps, and using it safely comes down to picking the authorization code flow with PKCE, validating ID tokens properly, and being deliberate about where you store tokens. Maintained by Manfred Steyer, the package tracks Angular's release cadence closely; the current major line sits at version 22.x, and it pulls hundreds of thousands of weekly downloads, so a lot of production auth runs through it.

This guide covers how the library works, the settings that matter for security, and the mistakes that turn a working login into a session-hijack risk.

What angular-oauth2-oidc actually does

The library gives you an OAuthService that handles the browser side of the OpenID Connect protocol: redirecting the user to your identity provider, receiving the callback, exchanging the authorization code for tokens, validating the ID token, and keeping the access token fresh. It supports discovery via the provider's .well-known/openid-configuration document, which means you configure an issuer URL and the library learns the authorization, token, and JWKS endpoints from there.

You install it the usual way:

npm install angular-oauth2-oidc

A minimal, security-conscious configuration looks like this:

import { AuthConfig } from 'angular-oauth2-oidc';

export const authConfig: AuthConfig = {
  issuer: 'https://id.example.com/realms/app',
  redirectUri: window.location.origin + '/callback',
  clientId: 'web-spa',
  responseType: 'code',
  scope: 'openid profile email',
  useSilentRefresh: false,
  showDebugInformation: false,
};

The responseType: 'code' line is the single most important choice here, and it is worth explaining why.

Use the code flow with PKCE, not implicit

Older Angular OAuth2 tutorials used the implicit flow, where the access token comes back directly in the URL fragment. The OAuth2 Security Best Current Practice (RFC 9700) deprecates implicit flow for browser apps because tokens end up in browser history, referrer headers, and logs. angular-oauth2-oidc supports the authorization code flow with PKCE (Proof Key for Code Exchange), which is what you should use for any new Angular OIDC OAuth2 setup.

Enable it explicitly:

this.oauthService.configure(authConfig);
this.oauthService.loadDiscoveryDocumentAndTryLogin().then(() => {
  if (!this.oauthService.hasValidAccessToken()) {
    this.oauthService.initCodeFlow();
  }
});

Calling initCodeFlow() (rather than the old initImplicitFlow()) triggers PKCE automatically. The library generates a code verifier, sends only its hash to the authorization endpoint, and completes the exchange with the verifier. An attacker who intercepts the authorization code cannot redeem it without the verifier, which closes the code-interception attack that plain code flow is vulnerable to in a public client.

Validate the ID token, don't just decode it

An ID token is a signed JWT that asserts who the user is. Decoding it tells you the claims; validating it tells you whether to trust them. angular-oauth2-oidc validates the signature against the provider's JWKS and checks the standard claims when you provide the right config, but there are two settings people get wrong.

First, keep clock-skew tolerance tight. The clockSkewInSec option defaults are generous; do not inflate it to paper over a misconfigured server clock, because a wide window weakens exp and nbf enforcement. Second, if you set strictDiscoveryDocumentValidation to false to work around a non-compliant provider, understand you have turned off a real check. Prefer fixing the provider metadata.

The angular oauth2 token validation also depends on the jwks being reachable and fresh. The library caches keys; if your provider rotates signing keys, make sure discovery reloads so validation does not fail closed in a way that logs users out unexpectedly.

Where to store tokens

By default the library stores tokens in sessionStorage. Both localStorage and sessionStorage are readable by any JavaScript running on the page, which means a single cross-site scripting flaw exposes the tokens. There is no fully XSS-proof storage for a pure SPA, so the realistic defense is layered:

  • Prefer sessionStorage over localStorage so tokens die when the tab closes.
  • Ship a strict Content-Security-Policy to shrink your XSS attack surface.
  • Keep access-token lifetimes short and rely on refresh, so a stolen token has a small window.
  • If your architecture allows it, consider the backend-for-frontend pattern where refresh tokens live in an HttpOnly cookie on your own server and never reach JavaScript.

XSS is the dominant threat to browser-based auth, and a static analysis or SCA workflow that flags a vulnerable transitive dependency pulling untrusted markup into the DOM is part of keeping that surface small.

Silent refresh and token renewal

To keep a session alive without bouncing the user through a full login, the library offers silent refresh via a hidden iframe and, more modern, refresh tokens with the code flow. Third-party-cookie restrictions in current browsers have made iframe-based silent refresh unreliable, so angular oidc oauth2 deployments increasingly use rotating refresh tokens instead. Configure the provider to issue them and let the library call the token endpoint when the access token nears expiry.

Watch two things: enable refresh-token rotation on the provider so a leaked refresh token is single-use, and handle the refresh failure path by sending the user to a clean re-login rather than looping.

Logout that actually ends the session

logOut() clears the local token store, but a real logout should also end the session at the identity provider so the next login is not silently re-authenticated. angular-oauth2-oidc supports RP-initiated logout by redirecting to the provider's end_session_endpoint with an ID-token hint. Wire that up, and set a postLogoutRedirectUri you control, or users appear logged out in your app while their provider session stays open.

FAQ

Is angular-oauth2-oidc still maintained?

Yes. The angular-oauth2-oidc npm package tracks Angular major releases, with the current line at version 22.x and regular publishes. It remains the most widely adopted OAuth2/OIDC client in the Angular ecosystem.

Should I use implicit flow or code flow with PKCE?

Code flow with PKCE. Implicit flow is deprecated by current OAuth2 security guidance because it exposes tokens in the URL. Call initCodeFlow() and the library handles PKCE for you.

Where should tokens be stored?

sessionStorage is the safer default of the browser options, but no browser storage resists XSS fully. Pair it with a strict CSP, short token lifetimes, and ideally a backend-for-frontend that keeps refresh tokens in HttpOnly cookies.

How do I keep dependencies like this secure over time?

Pin versions, watch advisories for the library and its transitive dependencies, and run automated scanning in CI. An SCA tool such as Safeguard can flag a vulnerable transitive package before it ships. See our SCA product and the Academy for deeper walkthroughs.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.