@memberjunction/ng-auth-services 2.42.1 → 2.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +257 -103
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,15 +1,22 @@
1
1
  # @memberjunction/ng-auth-services
2
2
 
3
- The `@memberjunction/ng-auth-services` package provides authentication services for MemberJunction Explorer applications. It offers an abstraction layer that supports multiple authentication providers like Auth0 and Microsoft Authentication Library (MSAL).
3
+ 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.
4
+
5
+ ## Overview
6
+
7
+ 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.
4
8
 
5
9
  ## Features
6
10
 
7
- - Unified authentication service interface through an abstract base class
8
- - Support for Auth0 authentication provider
9
- - Support for Microsoft Authentication Library (MSAL) authentication provider
10
- - Easy switching between providers via configuration
11
- - Standardized methods for authentication operations (login, logout, token refresh)
12
- - Reactive user and authentication state management
11
+ - **Unified Authentication Interface**: Abstract base class (`MJAuthBase`) provides consistent API across providers
12
+ - **Multiple Provider Support**:
13
+ - Auth0 authentication provider
14
+ - Microsoft Authentication Library (MSAL) for Azure AD
15
+ - **Easy Provider Switching**: Change providers via configuration without code changes
16
+ - **Reactive State Management**: Observable-based authentication state and user information
17
+ - **Token Management**: Built-in token refresh and expiration handling
18
+ - **TypeScript Support**: Full TypeScript definitions for type safety
19
+ - **Angular 18+ Compatible**: Built for modern Angular applications
13
20
 
14
21
  ## Installation
15
22
 
@@ -19,47 +26,65 @@ npm install @memberjunction/ng-auth-services
19
26
 
20
27
  ## Requirements
21
28
 
22
- - Angular 18+
23
- - @memberjunction/core
24
- - @auth0/auth0-angular (when using Auth0)
25
- - @azure/msal-angular (when using MSAL)
29
+ ### Peer Dependencies
30
+ - `@angular/common`: ^18.0.2
31
+ - `@angular/core`: ^18.0.2
32
+ - `@angular/forms`: ^18.0.2
33
+ - `@angular/router`: ^18.0.2
34
+ - `@auth0/auth0-angular`: ^2.2.1 (required when using Auth0)
35
+ - `@azure/msal-angular`: ^3.0.11 (required when using MSAL)
36
+
37
+ ### Dependencies
38
+ - `@memberjunction/core`: ^2.43.0
39
+ - `tslib`: ^2.3.0
26
40
 
27
- ## Usage
41
+ ## Configuration
28
42
 
29
- ### Setup and Configuration
43
+ ### Environment Setup
30
44
 
31
- First, set up your authentication environment configuration:
45
+ Configure your authentication provider in your environment files:
32
46
 
47
+ #### Auth0 Configuration
33
48
  ```typescript
34
49
  // environment.ts
35
50
  export const environment = {
36
- // For Auth0
37
51
  AUTH_TYPE: 'auth0',
38
- AUTH0_DOMAIN: 'your-auth0-domain.auth0.com',
52
+ AUTH0_DOMAIN: 'your-domain.auth0.com',
39
53
  AUTH0_CLIENTID: 'your-auth0-client-id',
40
-
41
- // For MSAL (Azure AD)
42
- // AUTH_TYPE: 'msal',
43
- // CLIENT_ID: 'your-azure-client-id',
44
- // CLIENT_AUTHORITY: 'https://login.microsoftonline.com/your-tenant-id',
54
+ // Other environment variables...
55
+ };
56
+ ```
57
+
58
+ #### MSAL (Azure AD) Configuration
59
+ ```typescript
60
+ // environment.ts
61
+ export const environment = {
62
+ AUTH_TYPE: 'msal',
63
+ CLIENT_ID: 'your-azure-ad-client-id',
64
+ CLIENT_AUTHORITY: 'https://login.microsoftonline.com/your-tenant-id',
65
+ // Other environment variables...
45
66
  };
46
67
  ```
47
68
 
48
- Import and configure the AuthServicesModule in your app module:
69
+ ### Module Setup
70
+
71
+ Import and configure the `AuthServicesModule` in your app module:
49
72
 
50
73
  ```typescript
51
- import { AuthServicesModule, RedirectComponent } from '@memberjunction/ng-auth-services';
74
+ import { NgModule } from '@angular/core';
75
+ import { BrowserModule } from '@angular/platform-browser';
76
+ import { AuthServicesModule } from '@memberjunction/ng-auth-services';
52
77
  import { environment } from '../environments/environment';
78
+ import { AppComponent } from './app.component';
53
79
 
54
80
  @NgModule({
55
81
  declarations: [
56
- AppComponent,
57
- // other components
82
+ AppComponent
58
83
  ],
59
84
  imports: [
60
85
  BrowserModule,
61
- // other imports
62
- AuthServicesModule.forRoot(environment),
86
+ AuthServicesModule.forRoot(environment), // Configure auth module
87
+ // Other imports...
63
88
  ],
64
89
  providers: [],
65
90
  bootstrap: [AppComponent]
@@ -67,99 +92,152 @@ import { environment } from '../environments/environment';
67
92
  export class AppModule { }
68
93
  ```
69
94
 
70
- If using MSAL, add the MsalRedirectComponent to your routes:
95
+ ### Routing Configuration (MSAL only)
96
+
97
+ When using MSAL, add the redirect component to your routes:
71
98
 
72
99
  ```typescript
100
+ import { Routes } from '@angular/router';
73
101
  import { RedirectComponent } from '@memberjunction/ng-auth-services';
74
102
 
75
103
  const routes: Routes = [
76
- // Your app routes
77
- { path: 'auth', component: RedirectComponent }
104
+ // Your application routes...
105
+ { path: 'auth', component: RedirectComponent } // Required for MSAL
78
106
  ];
79
107
  ```
80
108
 
81
- ### Basic Usage
109
+ ## Usage Examples
82
110
 
83
- Inject the `MJAuthBase` service in your components:
111
+ ### Basic Authentication Operations
84
112
 
85
113
  ```typescript
86
114
  import { Component, OnInit } from '@angular/core';
87
115
  import { MJAuthBase } from '@memberjunction/ng-auth-services';
116
+ import { Observable } from 'rxjs';
88
117
 
89
118
  @Component({
90
- selector: 'app-user-profile',
91
- templateUrl: './user-profile.component.html',
119
+ selector: 'app-header',
120
+ template: `
121
+ <div class="header">
122
+ <button *ngIf="!(isAuthenticated$ | async)" (click)="login()">Login</button>
123
+ <button *ngIf="isAuthenticated$ | async" (click)="logout()">Logout</button>
124
+ <span *ngIf="user$ | async as user">Welcome, {{ user.name }}!</span>
125
+ </div>
126
+ `
92
127
  })
93
- export class UserProfileComponent implements OnInit {
94
- user: any;
95
-
128
+ export class HeaderComponent implements OnInit {
129
+ isAuthenticated$!: Observable<boolean>;
130
+ user$!: Observable<any>;
131
+
96
132
  constructor(private authService: MJAuthBase) {}
97
-
133
+
98
134
  async ngOnInit() {
99
- // Check if the user is authenticated
100
- const isAuthenticated = await this.authService.isAuthenticated();
101
- isAuthenticated.subscribe(authenticated => {
102
- if (authenticated) {
103
- this.loadUserProfile();
104
- }
105
- });
135
+ this.isAuthenticated$ = await this.authService.isAuthenticated();
136
+ this.user$ = await this.authService.getUser();
106
137
  }
107
-
108
- async loadUserProfile() {
109
- const userObs = await this.authService.getUser();
110
- userObs.subscribe(user => {
111
- this.user = user;
112
- });
113
- }
114
-
138
+
115
139
  login() {
116
140
  this.authService.login();
117
141
  }
118
-
142
+
119
143
  logout() {
120
144
  this.authService.logout();
121
145
  }
122
146
  }
123
147
  ```
124
148
 
125
- ### Advanced Usage
149
+ ### Getting User Claims
150
+
151
+ ```typescript
152
+ import { Component, OnInit } from '@angular/core';
153
+ import { MJAuthBase } from '@memberjunction/ng-auth-services';
154
+ import { Observable } from 'rxjs';
155
+ import { map } from 'rxjs/operators';
156
+
157
+ @Component({
158
+ selector: 'app-user-profile',
159
+ template: `
160
+ <div *ngIf="userClaims$ | async as claims">
161
+ <h3>User Profile</h3>
162
+ <p>Email: {{ claims.email }}</p>
163
+ <p>Name: {{ claims.name }}</p>
164
+ <p>Roles: {{ claims.roles?.join(', ') }}</p>
165
+ </div>
166
+ `
167
+ })
168
+ export class UserProfileComponent implements OnInit {
169
+ userClaims$!: Observable<any>;
170
+
171
+ constructor(private authService: MJAuthBase) {}
172
+
173
+ async ngOnInit() {
174
+ this.userClaims$ = await this.authService.getUserClaims();
175
+ }
176
+ }
177
+ ```
126
178
 
127
- #### Token Refresh and Expired Token Handling
179
+ ### Token Refresh and Error Handling
128
180
 
129
181
  ```typescript
130
- import { HttpErrorResponse } from '@angular/common/http';
182
+ import { Injectable } from '@angular/core';
183
+ import { HttpClient, HttpErrorResponse } from '@angular/common/http';
131
184
  import { MJAuthBase } from '@memberjunction/ng-auth-services';
185
+ import { catchError, switchMap } from 'rxjs/operators';
186
+ import { throwError } from 'rxjs';
132
187
 
188
+ @Injectable({
189
+ providedIn: 'root'
190
+ })
133
191
  export class ApiService {
134
- constructor(private authService: MJAuthBase) {}
135
-
136
- handleApiError(error: HttpErrorResponse) {
137
- // Check if token is expired
138
- if (error.status === 401 && this.authService.checkExpiredTokenError(error.error)) {
139
- // Refresh the token
140
- this.authService.refresh().then(tokenObs => {
141
- tokenObs.subscribe(() => {
142
- // Retry the API call
143
- // ...
144
- });
145
- });
192
+ constructor(
193
+ private http: HttpClient,
194
+ private authService: MJAuthBase
195
+ ) {}
196
+
197
+ getData() {
198
+ return this.http.get('/api/data').pipe(
199
+ catchError((error: HttpErrorResponse) => this.handleError(error))
200
+ );
201
+ }
202
+
203
+ private async handleError(error: HttpErrorResponse) {
204
+ if (error.status === 401 && this.authService.checkExpiredTokenError(error.message)) {
205
+ // Token expired, try to refresh
206
+ const tokenObs = await this.authService.refresh();
207
+ return tokenObs.pipe(
208
+ switchMap(() => this.http.get('/api/data')) // Retry the request
209
+ );
146
210
  }
211
+ return throwError(() => error);
147
212
  }
148
213
  }
149
214
  ```
150
215
 
151
- #### Getting User Claims
216
+ ### Protected Routes with Guards
152
217
 
153
218
  ```typescript
219
+ import { Injectable } from '@angular/core';
220
+ import { CanActivate, Router } from '@angular/router';
154
221
  import { MJAuthBase } from '@memberjunction/ng-auth-services';
222
+ import { map, tap } from 'rxjs/operators';
155
223
 
156
- export class UserService {
157
- constructor(private authService: MJAuthBase) {}
158
-
159
- async getUserEmail() {
160
- const claimsObs = await this.authService.getUserClaims();
161
- return claimsObs.pipe(
162
- map(claims => claims?.email || '')
224
+ @Injectable({
225
+ providedIn: 'root'
226
+ })
227
+ export class AuthGuard implements CanActivate {
228
+ constructor(
229
+ private authService: MJAuthBase,
230
+ private router: Router
231
+ ) {}
232
+
233
+ async canActivate() {
234
+ const isAuthenticated$ = await this.authService.isAuthenticated();
235
+ return isAuthenticated$.pipe(
236
+ tap(authenticated => {
237
+ if (!authenticated) {
238
+ this.authService.login();
239
+ }
240
+ })
163
241
  );
164
242
  }
165
243
  }
@@ -169,56 +247,132 @@ export class UserService {
169
247
 
170
248
  ### MJAuthBase (Abstract Class)
171
249
 
250
+ The base authentication service that all providers implement.
251
+
172
252
  #### Properties
173
253
 
174
- | Name | Type | Description |
175
- |------|------|-------------|
254
+ | Property | Type | Description |
255
+ |----------|------|-------------|
176
256
  | `authenticated` | `boolean` | Current authentication state |
177
257
 
178
258
  #### Methods
179
259
 
180
- | Name | Parameters | Return Type | Description |
181
- |------|------------|-------------|-------------|
182
- | `login` | `options?: any` | `Promise<any>` | Initiates the login process |
183
- | `logout` | None | `Promise<any>` | Logs the user out |
260
+ | Method | Parameters | Return Type | Description |
261
+ |--------|------------|-------------|-------------|
262
+ | `login` | `options?: any` | `Promise<any>` | Initiates the login flow. Options vary by provider. |
263
+ | `logout` | None | `Promise<any>` | Logs the user out and clears authentication state |
184
264
  | `refresh` | None | `Promise<Observable<any>>` | Refreshes the authentication token |
185
- | `isAuthenticated` | None | `Promise<any>` | Checks if the user is authenticated |
186
- | `getUser` | None | `Promise<any>` | Gets the current user information |
187
- | `getUserClaims` | None | `Promise<Observable<any>>` | Gets the user claims from the token |
188
- | `checkExpiredTokenError` | `error: string` | `boolean` | Checks if an error is due to an expired token |
265
+ | `isAuthenticated` | None | `Promise<any>` | Returns an Observable of the authentication state |
266
+ | `getUser` | None | `Promise<any>` | Returns user information (format varies by provider) |
267
+ | `getUserClaims` | None | `Promise<Observable<any>>` | Returns the user's token claims |
268
+ | `checkExpiredTokenError` | `error: string` | `boolean` | Checks if an error indicates an expired token |
189
269
 
190
270
  ### MJAuth0Provider
191
271
 
192
- Auth0-specific implementation of MJAuthBase.
272
+ Auth0-specific implementation of `MJAuthBase`. Internally uses `@auth0/auth0-angular`.
273
+
274
+ #### Provider-Specific Behavior
275
+ - Uses Auth0's redirect flow for authentication
276
+ - Returns Auth0 `User` object from `getUser()`
277
+ - Token expiration check looks for "jwt expired" in error messages
193
278
 
194
279
  ### MJMSALProvider
195
280
 
196
- MSAL-specific implementation of MJAuthBase.
281
+ MSAL-specific implementation of `MJAuthBase`. Internally uses `@azure/msal-angular`.
282
+
283
+ #### Provider-Specific Behavior
284
+ - Implements initialization handling to ensure MSAL is ready
285
+ - Uses redirect flow with automatic account selection
286
+ - Returns MSAL `AccountInfo` from `getUser()`
287
+ - Includes refresh token policy in token operations
288
+ - Token expiration check looks for authorization errors
197
289
 
198
290
  ### AuthServicesModule
199
291
 
292
+ The main module for configuring authentication services.
293
+
200
294
  #### Static Methods
201
295
 
202
- | Name | Parameters | Return Type | Description |
203
- |------|------------|-------------|-------------|
204
- | `forRoot` | `environment: AuthEnvironment` | `ModuleWithProviders<AuthServicesModule>` | Configures the auth services module |
296
+ | Method | Parameters | Return Type | Description |
297
+ |--------|------------|-------------|-------------|
298
+ | `forRoot` | `environment: AuthEnvironment` | `ModuleWithProviders<AuthServicesModule>` | Configures the authentication module with environment settings |
205
299
 
206
300
  #### AuthEnvironment Type
207
301
 
208
302
  ```typescript
209
303
  type AuthEnvironment = {
210
- AUTH_TYPE: string; // 'auth0' or 'msal'
211
- CLIENT_ID: string; // For MSAL
212
- CLIENT_AUTHORITY: string; // For MSAL
213
- AUTH0_CLIENTID: string; // For Auth0
214
- AUTH0_DOMAIN: string; // For Auth0
304
+ AUTH_TYPE: string; // 'auth0' or 'msal'
305
+ CLIENT_ID: string; // MSAL client ID
306
+ CLIENT_AUTHORITY: string; // MSAL authority URL
307
+ AUTH0_CLIENTID: string; // Auth0 client ID
308
+ AUTH0_DOMAIN: string; // Auth0 domain
215
309
  };
216
310
  ```
217
311
 
218
- ## Dependencies
312
+ ### RedirectComponent
313
+
314
+ Re-exported from `@azure/msal-angular`. Required for MSAL redirect flow handling.
315
+
316
+ ## Integration with Other MemberJunction Packages
317
+
318
+ This package integrates with:
319
+ - **@memberjunction/core**: Uses core logging utilities (`LogError`)
320
+ - **MemberJunction Explorer**: Provides authentication for all Explorer UI components
321
+ - **MemberJunction API**: Token management for API authentication
322
+
323
+ ## Build and Development
324
+
325
+ ### Building the Package
326
+ ```bash
327
+ # From the package directory
328
+ npm run build
329
+
330
+ # From the repository root
331
+ npm run build -- --filter="@memberjunction/ng-auth-services"
332
+ ```
333
+
334
+ ### Development Notes
335
+ - The package uses Angular Package Format (APF)
336
+ - Compiled with Angular Compiler (`ngc`)
337
+ - No side effects - tree-shakeable
338
+ - Distributed files are in the `/dist` directory
339
+
340
+ ## Migration Guide
341
+
342
+ ### Switching Between Providers
343
+
344
+ To switch authentication providers:
345
+
346
+ 1. Update your environment configuration:
347
+ ```typescript
348
+ // From Auth0 to MSAL
349
+ AUTH_TYPE: 'msal', // was 'auth0'
350
+ CLIENT_ID: 'your-azure-client-id',
351
+ CLIENT_AUTHORITY: 'https://login.microsoftonline.com/your-tenant',
352
+ ```
353
+
354
+ 2. Add redirect route (if switching to MSAL):
355
+ ```typescript
356
+ { path: 'auth', component: RedirectComponent }
357
+ ```
358
+
359
+ 3. No other code changes required - the `MJAuthBase` interface remains the same
360
+
361
+ ## Troubleshooting
362
+
363
+ ### Common Issues
364
+
365
+ 1. **MSAL Initialization Errors**: Ensure the MSAL redirect component is properly configured in routes
366
+ 2. **Token Refresh Failures**: Check that refresh token is enabled in your auth provider configuration
367
+ 3. **CORS Issues**: Verify redirect URIs are properly configured in your auth provider dashboard
368
+
369
+ ### Debug Tips
370
+
371
+ - Check browser console for authentication errors
372
+ - Verify localStorage contains auth tokens
373
+ - Use browser dev tools to inspect network requests for auth headers
374
+ - Enable verbose logging in your auth provider configuration
375
+
376
+ ## License
219
377
 
220
- - @angular/common
221
- - @angular/core
222
- - @memberjunction/core
223
- - @auth0/auth0-angular (when using Auth0)
224
- - @azure/msal-angular (when using MSAL)
378
+ ISC
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-auth-services",
3
- "version": "2.42.1",
3
+ "version": "2.44.0",
4
4
  "description": "MemberJunction Explorer: Authentication Services",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -27,7 +27,7 @@
27
27
  "@azure/msal-angular": "^3.0.11"
28
28
  },
29
29
  "dependencies": {
30
- "@memberjunction/core": "2.42.1",
30
+ "@memberjunction/core": "2.44.0",
31
31
  "tslib": "^2.3.0"
32
32
  },
33
33
  "sideEffects": false