2.48.0 • Published 5 months ago

@memberjunction/ng-auth-services v2.48.0

Weekly downloads
-
License
ISC
Repository
-
Last release
5 months ago

@memberjunction/ng-auth-services

The @memberjunction/ng-auth-services package provides authentication services for MemberJunction Explorer Angular applications. It offers a unified abstraction layer that supports multiple authentication providers including Auth0 and Microsoft Authentication Library (MSAL) for Azure Active Directory.

Overview

This package implements a provider pattern that allows seamless switching between different authentication services through configuration. It provides a consistent API regardless of which authentication provider is being used, making it easy to change authentication strategies without modifying application code.

Features

  • Unified Authentication Interface: Abstract base class (MJAuthBase) provides consistent API across providers
  • Multiple Provider Support:
    • Auth0 authentication provider
    • Microsoft Authentication Library (MSAL) for Azure AD
  • Easy Provider Switching: Change providers via configuration without code changes
  • Reactive State Management: Observable-based authentication state and user information
  • Token Management: Built-in token refresh and expiration handling
  • TypeScript Support: Full TypeScript definitions for type safety
  • Angular 18+ Compatible: Built for modern Angular applications

Installation

npm install @memberjunction/ng-auth-services

Requirements

Peer Dependencies

  • @angular/common: ^18.0.2
  • @angular/core: ^18.0.2
  • @angular/forms: ^18.0.2
  • @angular/router: ^18.0.2
  • @auth0/auth0-angular: ^2.2.1 (required when using Auth0)
  • @azure/msal-angular: ^3.0.11 (required when using MSAL)

Dependencies

  • @memberjunction/core: ^2.43.0
  • tslib: ^2.3.0

Configuration

Environment Setup

Configure your authentication provider in your environment files:

Auth0 Configuration

// environment.ts
export const environment = {
  AUTH_TYPE: 'auth0',
  AUTH0_DOMAIN: 'your-domain.auth0.com',
  AUTH0_CLIENTID: 'your-auth0-client-id',
  // Other environment variables...
};

MSAL (Azure AD) Configuration

// environment.ts
export const environment = {
  AUTH_TYPE: 'msal',
  CLIENT_ID: 'your-azure-ad-client-id',
  CLIENT_AUTHORITY: 'https://login.microsoftonline.com/your-tenant-id',
  // Other environment variables...
};

Module Setup

Import and configure the AuthServicesModule in your app module:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AuthServicesModule } from '@memberjunction/ng-auth-services';
import { environment } from '../environments/environment';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AuthServicesModule.forRoot(environment), // Configure auth module
    // Other imports...
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Routing Configuration (MSAL only)

When using MSAL, add the redirect component to your routes:

import { Routes } from '@angular/router';
import { RedirectComponent } from '@memberjunction/ng-auth-services';

const routes: Routes = [
  // Your application routes...
  { path: 'auth', component: RedirectComponent } // Required for MSAL
];

Usage Examples

Basic Authentication Operations

import { Component, OnInit } from '@angular/core';
import { MJAuthBase } from '@memberjunction/ng-auth-services';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-header',
  template: `
    <div class="header">
      <button *ngIf="!(isAuthenticated$ | async)" (click)="login()">Login</button>
      <button *ngIf="isAuthenticated$ | async" (click)="logout()">Logout</button>
      <span *ngIf="user$ | async as user">Welcome, {{ user.name }}!</span>
    </div>
  `
})
export class HeaderComponent implements OnInit {
  isAuthenticated$!: Observable<boolean>;
  user$!: Observable<any>;

  constructor(private authService: MJAuthBase) {}

  async ngOnInit() {
    this.isAuthenticated$ = await this.authService.isAuthenticated();
    this.user$ = await this.authService.getUser();
  }

  login() {
    this.authService.login();
  }

  logout() {
    this.authService.logout();
  }
}

Getting User Claims

import { Component, OnInit } from '@angular/core';
import { MJAuthBase } from '@memberjunction/ng-auth-services';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Component({
  selector: 'app-user-profile',
  template: `
    <div *ngIf="userClaims$ | async as claims">
      <h3>User Profile</h3>
      <p>Email: {{ claims.email }}</p>
      <p>Name: {{ claims.name }}</p>
      <p>Roles: {{ claims.roles?.join(', ') }}</p>
    </div>
  `
})
export class UserProfileComponent implements OnInit {
  userClaims$!: Observable<any>;

  constructor(private authService: MJAuthBase) {}

  async ngOnInit() {
    this.userClaims$ = await this.authService.getUserClaims();
  }
}

Token Refresh and Error Handling

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { MJAuthBase } from '@memberjunction/ng-auth-services';
import { catchError, switchMap } from 'rxjs/operators';
import { throwError } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  constructor(
    private http: HttpClient,
    private authService: MJAuthBase
  ) {}

  getData() {
    return this.http.get('/api/data').pipe(
      catchError((error: HttpErrorResponse) => this.handleError(error))
    );
  }

  private async handleError(error: HttpErrorResponse) {
    if (error.status === 401 && this.authService.checkExpiredTokenError(error.message)) {
      // Token expired, try to refresh
      const tokenObs = await this.authService.refresh();
      return tokenObs.pipe(
        switchMap(() => this.http.get('/api/data')) // Retry the request
      );
    }
    return throwError(() => error);
  }
}

Protected Routes with Guards

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { MJAuthBase } from '@memberjunction/ng-auth-services';
import { map, tap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(
    private authService: MJAuthBase,
    private router: Router
  ) {}

  async canActivate() {
    const isAuthenticated$ = await this.authService.isAuthenticated();
    return isAuthenticated$.pipe(
      tap(authenticated => {
        if (!authenticated) {
          this.authService.login();
        }
      })
    );
  }
}

API Reference

MJAuthBase (Abstract Class)

The base authentication service that all providers implement.

Properties

PropertyTypeDescription
authenticatedbooleanCurrent authentication state

Methods

MethodParametersReturn TypeDescription
loginoptions?: anyPromise<any>Initiates the login flow. Options vary by provider.
logoutNonePromise<any>Logs the user out and clears authentication state
refreshNonePromise<Observable<any>>Refreshes the authentication token
isAuthenticatedNonePromise<any>Returns an Observable of the authentication state
getUserNonePromise<any>Returns user information (format varies by provider)
getUserClaimsNonePromise<Observable<any>>Returns the user's token claims
checkExpiredTokenErrorerror: stringbooleanChecks if an error indicates an expired token

MJAuth0Provider

Auth0-specific implementation of MJAuthBase. Internally uses @auth0/auth0-angular.

Provider-Specific Behavior

  • Uses Auth0's redirect flow for authentication
  • Returns Auth0 User object from getUser()
  • Token expiration check looks for "jwt expired" in error messages

MJMSALProvider

MSAL-specific implementation of MJAuthBase. Internally uses @azure/msal-angular.

Provider-Specific Behavior

  • Implements initialization handling to ensure MSAL is ready
  • Uses redirect flow with automatic account selection
  • Returns MSAL AccountInfo from getUser()
  • Includes refresh token policy in token operations
  • Token expiration check looks for authorization errors

AuthServicesModule

The main module for configuring authentication services.

Static Methods

MethodParametersReturn TypeDescription
forRootenvironment: AuthEnvironmentModuleWithProviders<AuthServicesModule>Configures the authentication module with environment settings

AuthEnvironment Type

type AuthEnvironment = {
  AUTH_TYPE: string;           // 'auth0' or 'msal'
  CLIENT_ID: string;           // MSAL client ID
  CLIENT_AUTHORITY: string;    // MSAL authority URL
  AUTH0_CLIENTID: string;      // Auth0 client ID
  AUTH0_DOMAIN: string;        // Auth0 domain
};

RedirectComponent

Re-exported from @azure/msal-angular. Required for MSAL redirect flow handling.

Integration with Other MemberJunction Packages

This package integrates with:

  • @memberjunction/core: Uses core logging utilities (LogError)
  • MemberJunction Explorer: Provides authentication for all Explorer UI components
  • MemberJunction API: Token management for API authentication

Build and Development

Building the Package

# From the package directory
npm run build

# From the repository root
npm run build -- --filter="@memberjunction/ng-auth-services"

Development Notes

  • The package uses Angular Package Format (APF)
  • Compiled with Angular Compiler (ngc)
  • No side effects - tree-shakeable
  • Distributed files are in the /dist directory

Migration Guide

Switching Between Providers

To switch authentication providers:

  1. Update your environment configuration:

    // From Auth0 to MSAL
    AUTH_TYPE: 'msal', // was 'auth0'
    CLIENT_ID: 'your-azure-client-id',
    CLIENT_AUTHORITY: 'https://login.microsoftonline.com/your-tenant',
  2. Add redirect route (if switching to MSAL):

    { path: 'auth', component: RedirectComponent }
  3. No other code changes required - the MJAuthBase interface remains the same

Troubleshooting

Common Issues

  1. MSAL Initialization Errors: Ensure the MSAL redirect component is properly configured in routes
  2. Token Refresh Failures: Check that refresh token is enabled in your auth provider configuration
  3. CORS Issues: Verify redirect URIs are properly configured in your auth provider dashboard

Debug Tips

  • Check browser console for authentication errors
  • Verify localStorage contains auth tokens
  • Use browser dev tools to inspect network requests for auth headers
  • Enable verbose logging in your auth provider configuration

License

ISC

2.23.2

9 months ago

2.46.0

5 months ago

2.23.1

9 months ago

2.34.0

6 months ago

2.19.4

9 months ago

2.19.5

9 months ago

2.19.2

9 months ago

2.19.3

9 months ago

2.19.0

9 months ago

2.19.1

9 months ago

2.34.2

6 months ago

2.34.1

6 months ago

2.45.0

5 months ago

2.22.1

9 months ago

2.22.0

9 months ago

2.22.2

9 months ago

2.33.0

6 months ago

2.18.3

9 months ago

2.18.1

9 months ago

2.18.2

9 months ago

2.18.0

9 months ago

2.21.0

9 months ago

2.44.0

5 months ago

2.29.0

8 months ago

2.29.2

8 months ago

2.29.1

8 months ago

2.32.0

7 months ago

2.32.2

7 months ago

2.32.1

7 months ago

2.17.0

9 months ago

2.43.0

5 months ago

2.20.2

9 months ago

2.20.3

9 months ago

2.20.0

9 months ago

2.20.1

9 months ago

2.28.0

8 months ago

2.31.0

7 months ago

2.39.0

5 months ago

2.16.1

9 months ago

2.16.0

9 months ago

2.42.1

5 months ago

2.42.0

5 months ago

2.27.1

8 months ago

2.27.0

8 months ago

2.30.0

7 months ago

2.15.2

9 months ago

2.15.1

9 months ago

2.38.0

5 months ago

2.41.0

5 months ago

2.26.1

8 months ago

2.26.0

8 months ago

2.37.1

6 months ago

2.37.0

6 months ago

2.14.0

10 months ago

2.40.0

5 months ago

2.25.0

8 months ago

2.48.0

5 months ago

2.13.4

10 months ago

2.36.0

6 months ago

2.13.2

11 months ago

2.13.3

10 months ago

2.13.0

11 months ago

2.36.1

6 months ago

2.13.1

11 months ago

2.47.0

5 months ago

2.24.1

8 months ago

2.24.0

8 months ago

2.12.0

12 months ago

2.35.1

6 months ago

2.35.0

6 months ago

2.23.0

9 months ago

2.11.0

1 year ago

2.10.0

1 year ago

2.9.0

1 year ago

2.8.0

1 year ago

2.7.0

1 year ago

2.7.1

1 year ago

2.6.1

1 year ago

2.6.0

1 year ago

2.5.2

1 year ago

1.6.1

1 year ago

1.6.0

1 year ago

2.4.1

1 year ago

2.4.0

1 year ago

2.0.0

1 year ago

1.5.3

1 year ago

1.5.2

1 year ago

1.5.1

1 year ago

1.5.0

1 year ago

2.3.0

1 year ago

2.3.2

1 year ago

2.3.1

1 year ago

2.3.3

1 year ago

1.8.1

1 year ago

1.8.0

1 year ago

1.4.1

1 year ago

1.4.0

1 year ago

2.2.1

1 year ago

2.2.0

1 year ago

1.7.1

1 year ago

1.7.0

1 year ago

1.3.3

1 year ago

1.3.2

1 year ago

1.3.1

1 year ago

1.3.0

1 year ago

2.1.2

1 year ago

2.1.1

1 year ago

2.5.0

1 year ago

2.1.4

1 year ago

2.1.3

1 year ago

2.5.1

1 year ago

2.1.5

1 year ago

2.1.0

1 year ago

1.2.2

1 year ago

1.2.1

1 year ago

1.2.0

1 year ago

1.1.1

1 year ago

1.1.0

1 year ago

1.1.3

1 year ago

1.1.2

1 year ago

1.0.11

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.8-next.6

2 years ago

1.0.8-next.5

2 years ago

1.0.8-next.4

2 years ago

1.0.8-next.3

2 years ago

1.0.8-next.2

2 years ago

1.0.8-next.1

2 years ago

1.0.8-next.0

2 years ago

1.0.7-next.0

2 years ago

1.0.8-beta.0

2 years ago

1.0.6

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago

0.9.110

2 years ago

0.9.109

2 years ago

0.9.108

2 years ago

0.9.107

2 years ago

0.9.106

2 years ago

0.9.105

2 years ago

0.9.103

2 years ago

0.9.102

2 years ago

0.9.104

2 years ago

0.9.101

2 years ago

0.9.100

2 years ago

0.9.97

2 years ago

0.9.98

2 years ago

0.9.99

2 years ago

0.9.95

2 years ago

0.9.94

2 years ago

0.9.93

2 years ago

0.9.92

2 years ago

0.9.91

2 years ago

0.9.90

2 years ago

0.9.89

2 years ago

0.9.85

2 years ago

0.9.86

2 years ago

0.9.87

2 years ago

0.9.88

2 years ago

0.9.82

2 years ago

0.9.83

2 years ago

0.9.81

2 years ago

0.9.80

2 years ago

0.9.78

2 years ago

0.9.79

2 years ago

0.9.76

2 years ago

0.9.77

2 years ago

0.9.75

2 years ago

0.9.74

2 years ago

0.9.73

2 years ago

0.9.72

2 years ago

0.9.71

2 years ago

0.9.70

2 years ago

0.9.64

2 years ago

0.9.56

2 years ago

0.9.52

2 years ago

0.9.50

2 years ago

0.9.51

2 years ago

0.9.39

2 years ago

0.9.45

2 years ago

0.9.46

2 years ago

0.9.47

2 years ago

0.9.48

2 years ago

0.9.41

2 years ago

0.9.42

2 years ago

0.9.43

2 years ago

0.9.44

2 years ago

0.9.49

2 years ago

0.9.40

2 years ago

0.9.32

2 years ago

0.9.33

2 years ago

0.9.30

2 years ago

0.9.31

2 years ago

0.9.25

2 years ago

0.9.26

2 years ago

0.9.27

2 years ago

0.9.28

2 years ago

0.9.29

2 years ago

0.9.24

2 years ago

0.9.23

2 years ago

0.9.22

2 years ago

0.9.20

2 years ago

0.9.21

2 years ago

0.9.17

2 years ago

0.9.18

2 years ago

0.9.19

2 years ago

0.9.16

2 years ago

0.9.15

2 years ago

0.9.13

2 years ago

0.9.14

2 years ago

0.9.12

2 years ago

0.9.11

2 years ago

0.9.10

2 years ago

0.9.9

2 years ago

0.9.8

2 years ago

0.9.7

2 years ago

0.9.6

2 years ago

0.9.5

2 years ago

0.9.4

2 years ago

0.9.3

2 years ago

0.9.2

2 years ago

0.9.1

2 years ago