angular-auth-oidc-client

repository·main·Indexed 22 days ago

https://github.com/damienbod/angular-auth-oidc-client

An Angular library for implementing OpenID Connect (OIDC) and OAuth2 authentication. Version 21.0.3 supports modern flows including PKCE and refresh tokens. It provides tools for managing authentication state via OidcSecurityService, automatic token injection through AuthInterceptor, and route-based automatic login using functional guards like autoLoginPartialRoutesGuard. The library supports multiple static configurations via provideAuth and offers specific guidance for integrating with Azure B2C.

Tokens
38K
Snippets
100
Records
148
Agent score
78%

What's inside angular-auth-oidc-client

  1. Implement a custom storage provider

    main

    By default, the library uses sessionStorage. To use a different mechanism like localStorage or cookies, implement the AbstractSecurityStorage interface. Your implementation must include the following methods:

    • read(key: string): string | null
    • write(key: string, value: string): void
    • remove(key: string): void
    • clear(): void
    import { AbstractSecurityStorage } from 'angular-auth-oidc-client';
    
    @Injectable()
    export class MyStorageService implements AbstractSecurityStorage {
      read(key: string): string | null {
        return localStorage.getItem(key);
      }
    
      write(key: string, value: string): void {
        localStorage.setItem(key, value);
      }
    
      remove(key: string): void {
        localStorage.removeItem(key);
      }
    
      clear(): void {
        localStorage.clear();
      }
    }
  2. How the library bootstrapping and preloading works

    main

    Starting from version 14, the APP_INITIALIZER was removed. The library no longer performs any actions or pre-loading during the application's bootstrapping process. It remains idle until the application explicitly interacts with it.

    To explicitly preload the secure token server well-known endpoints, use the preloadAuthWellKnownDocument() method. Because configuration loading is now an asynchronous prerequisite for many operations, most core APIs have transitioned to a reactive pattern and return Observable instead of direct values.

  3. How to handle Login, Logout, and Authentication bootstrapping

    main

    Understanding the difference between checkAuth() and authorize() is critical for correct implementation:

    • checkAuth(): Call this once on every app load (e.g., in your root component's ngOnInit). It bootstraps the library by processing callbacks, restoring sessions from storage, and starting silent renewal. It does not redirect the user.
    • authorize(): Call this when the user initiates a login (e.g., clicking a 'Sign in' button). This method redirects the browser to the Identity Provider (IdP).
    • logoff(): Used to end the session.

    Special Bootstrap Scenarios

    • Multiple Configurations: If you have registered more than one configuration via provideAuth, use checkAuthMultiple() instead of checkAuth().
    • Single Sign-On (SSO): To detect an existing session at the IdP that this app hasn't seen yet (e.g., user signed into another app on the same IdP), use checkAuthIncludingServer(). This performs the standard bootstrap plus an iframe silent renew against the IdP.
    import { OidcSecurityService } from 'angular-auth-oidc-client';
    
    @Component({
      /* ... */
    })
    export class AppComponent implements OnInit {
      private readonly oidcSecurityService = inject(OidcSecurityService);
    
      ngOnInit() {
        // Bootstrap on every page load. Handles the IdP callback,
        // restores stored sessions, and starts silent renewal.
        this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated, userData}) => /* ... */);
      }
    
      login() {
        // User clicked sign-in: redirect to the identity provider.
        this.oidcSecurityService.authorize();
      }
    
      logout() {
        this.oidcSecurityService.logoff().subscribe((result) => console.log(result));
      }
    }
  4. Important considerations when using Azure B2C

    main

    When using Azure B2C with angular-auth-oidc-client, be aware of the following architectural constraints:

    • Identity Providers: Every policy in Azure B2C acts as a separate Identity Provider. If you are using multiple policies, you must configure multiple clients.
    • Access Tokens: In Azure, each access token for a specific API must be requested separately. This is typically handled by configuring multiple clients.
    • Logout Limitations: Full logout is not possible because Azure B2C does not support revocation endpoints or introspection. This means refresh tokens and access tokens remain valid until they expire, even after a user attempts to log out.

    Best Practices for Security: To mitigate the risk of tokens remaining valid in the browser after logout, keep token lifespans short:

    • Set access tokens to a short lifespan (e.g., 15 minutes).
    • Set refresh tokens to be as short as possible.
  5. Implement multiple OIDC configurations

    main
    The library supports multiple OIDC configurations within a single application. This is useful when your application needs to interact with multiple Identity Providers (e.g., Auth0 and IdentityServer4) or when you need to access different APIs (e.g., Microsoft Graph API alongside a custom API) using different authentication contexts. You can implement these using various flows, including PKCE with refresh tokens, popups, or iframe-based silent renewal.
  6. Handle authentication results via events instead of automatic routing

    main

    By default, the library performs automatic Angular route changes after authentication (e.g., to postLoginRoute, forbiddenRoute, or unauthorizedRoute).

    If you want to control the navigation yourself—for example, to save the original URL in sessionStorage and redirect the user back to it after login—set triggerAuthorizationResultEvent to true. This allows you to subscribe to the emitted event and perform custom logic instead of the library forcing a redirect.

  7. Replace AutoLoginAllRoutesGuard with AutoLoginPartialRoutesGuard

    main

    In version 16 and later, AutoLoginAllRoutesGuard is deprecated and scheduled for removal. You should migrate to AutoLoginPartialRoutesGuard for route protection.

    import { AutoLoginPartialRoutesGuard } from 'angular-auth-oidc-client';
    
    const routes: Routes = [
      {
        path: 'protected',
        component: ProtectedComponent,
        canActivate: [AutoLoginPartialRoutesGuard],
      },
    ];
  8. Configure AuthModule in a child module or library

    main

    You can configure the AuthModule using AuthModule.forRoot() when loading a child module or an Angular library.

    Note: This approach is not recommended. It is preferred to perform initialization at the root level of your application.

    When using this method, you provide a configuration object to forRoot() containing your OIDC settings such as authority, clientId, redirectUrl, and scope.

    import { NgModule } from '@angular/core';
    import { HttpClientModule } from '@angular/common/http';
    import { CommonModule } from '@angular/common';
    import { RouterModule } from '@angular/router';
    import { AuthModule, LogLevel } from 'angular-auth-oidc-client';
    
    @NgModule({
      declarations: [
        /*  */
      ],
      imports: [
        AuthModule.forRoot({
          config: {
            authority: '<your authority address here>',
            redirectUrl: window.location.origin,
            postLogoutRedirectUri: window.location.origin,
            clientId: 'angularClient',
            scope: 'openid profile email',
            responseType: 'code',
            silentRenew: true,
            silentRenewUrl: `${window.location.origin}/silent-renew.html`,
            renewTimeBeforeTokenExpiresInSeconds: 10,
            logLevel: LogLevel.Debug,
          },
        }),
        HttpClientModule,
        CommonModule,
        RouterModule,
      ],
      exports: [
        /* */
      ],
    })
    export class ChildModule {}
  9. Migrate configuration from `enableIdTokenExpiredValidationInRenew` to `triggerRefreshWhenIdTokenExpired`

    main

    In version 15, the configuration property enableIdTokenExpiredValidationInRenew was renamed to triggerRefreshWhenIdTokenExpired to better reflect its purpose. This parameter controls whether the renewal process is triggered when an id_token is expired. Setting it to false prevents the renewal process from being triggered by an expired id_token.

    // New configuration format in v15+
    const config = {
      //...
      triggerRefreshWhenIdTokenExpired: true|false
    }
  10. Use the built-in HTTP Interceptor with NgModule

    main

    If your application uses NgModule instead of standalone APIs, you must:

    1. Import AuthModule.forRoot() and define your secureRoutes within the configuration.
    2. Register the AuthInterceptor class in your providers array using the HTTP_INTERCEPTORS multi-provider token.
    import { AuthInterceptor, AuthModule } from 'angular-auth-oidc-client';
    
    @NgModule({
      // ...
      imports: [
        // ...
        AuthModule.forRoot({
          // ...
          secureRoutes: ['https://my-secure-url.com/', 'https://my-second-secure-url.com/'],
        }),
        HttpClientModule,
      ],
      providers: [
        { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
        // ...
      ],
    })
    export class AppModule {}
  11. Use the built-in HTTP Interceptor with Standalone APIs

    main

    To automatically add the access token to outgoing HTTP requests, use the provided authInterceptor. This is done by registering it with withInterceptors inside your provideHttpClient configuration.

    To control which requests receive the token, use the secureRoutes property in your provideAuth configuration. The interceptor will only add the Authorization header to requests that match the URLs defined in secureRoutes.

    Route Matching Rules:

    • Prefix Matching: If you protect https://example.org/api, all child routes (e.g., https://example.org/api/users) are also protected.
    • Wildcards: You can use * for wildcard matching. For example, https://example.org/api/*/token will match https://example.org/api/applications/token.
    • Multiple Configurations: If using multiple OIDC configurations, the interceptor collects all secureRoutes from all configurations. If a request matches a route from a specific configuration, the token from that configuration is applied.
    import { authInterceptor } from 'angular-auth-oidc-client';
    
    export const appConfig: ApplicationConfig = {
      providers: [
        provideHttpClient(withInterceptors([authInterceptor()])),
        provideAuth({
          config: {
            // ...
            secureRoutes: ['https://my-secure-url.com/', 'https://my-second-secure-url.com/'],
          },
        }),
      ],
    };