@memberjunction/ng-auth-services 2.129.0 → 2.130.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 (27) hide show
  1. package/dist/lib/IAuthProvider.d.ts +177 -17
  2. package/dist/lib/IAuthProvider.d.ts.map +1 -1
  3. package/dist/lib/auth-types.d.ts +351 -0
  4. package/dist/lib/auth-types.d.ts.map +1 -0
  5. package/dist/lib/auth-types.js +98 -0
  6. package/dist/lib/auth-types.js.map +1 -0
  7. package/dist/lib/mjexplorer-auth-base.service.d.ts +204 -49
  8. package/dist/lib/mjexplorer-auth-base.service.d.ts.map +1 -1
  9. package/dist/lib/mjexplorer-auth-base.service.js +173 -67
  10. package/dist/lib/mjexplorer-auth-base.service.js.map +1 -1
  11. package/dist/lib/providers/mjexplorer-auth0-provider.service.d.ts +61 -17
  12. package/dist/lib/providers/mjexplorer-auth0-provider.service.d.ts.map +1 -1
  13. package/dist/lib/providers/mjexplorer-auth0-provider.service.js +245 -76
  14. package/dist/lib/providers/mjexplorer-auth0-provider.service.js.map +1 -1
  15. package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts +57 -16
  16. package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts.map +1 -1
  17. package/dist/lib/providers/mjexplorer-msal-provider.service.js +311 -114
  18. package/dist/lib/providers/mjexplorer-msal-provider.service.js.map +1 -1
  19. package/dist/lib/providers/mjexplorer-okta-provider.service.d.ts +55 -30
  20. package/dist/lib/providers/mjexplorer-okta-provider.service.d.ts.map +1 -1
  21. package/dist/lib/providers/mjexplorer-okta-provider.service.js +263 -235
  22. package/dist/lib/providers/mjexplorer-okta-provider.service.js.map +1 -1
  23. package/dist/public-api.d.ts +1 -0
  24. package/dist/public-api.d.ts.map +1 -1
  25. package/dist/public-api.js +2 -0
  26. package/dist/public-api.js.map +1 -1
  27. package/package.json +3 -3
@@ -1,14 +1,33 @@
1
1
  import { Observable, BehaviorSubject } from 'rxjs';
2
2
  import { IAngularAuthProvider, AngularAuthProviderConfig } from './IAuthProvider';
3
+ import { StandardUserInfo, StandardAuthToken, StandardAuthError, TokenRefreshResult } from './auth-types';
3
4
  import * as i0 from "@angular/core";
4
5
  /**
5
- * Base class for Angular authentication providers
6
- * Provides common functionality and enforces the provider interface
6
+ * Base class for Angular authentication providers - v3.0.0
7
+ *
8
+ * Provides common functionality and enforces the provider interface.
9
+ * All concrete providers (MSAL, Auth0, Okta) should extend this class.
10
+ *
11
+ * ## Key Improvements in v3.0:
12
+ * - Proper abstraction - no more leaky provider-specific logic
13
+ * - Standardized types - no more `any` types
14
+ * - Clean token access - no more `__raw || idToken` patterns
15
+ * - Semantic error handling - no more provider-specific error checks
16
+ *
17
+ * ## For Provider Implementers:
18
+ * Extend this class and implement the abstract methods:
19
+ * - `extractIdTokenInternal()` - Extract token from provider storage
20
+ * - `extractTokenInfoInternal()` - Extract full token info
21
+ * - `extractUserInfoInternal()` - Map claims to StandardUserInfo
22
+ * - `refreshTokenInternal()` - Implement refresh mechanism
23
+ * - `classifyErrorInternal()` - Map errors to AuthErrorType
24
+ *
25
+ * @version 3.0.0
7
26
  */
8
27
  export declare abstract class MJAuthBase implements IAngularAuthProvider {
9
28
  protected config: AngularAuthProviderConfig;
10
29
  protected isAuthenticated$: BehaviorSubject<boolean>;
11
- protected userProfile$: BehaviorSubject<any>;
30
+ protected userInfo$: BehaviorSubject<StandardUserInfo | null>;
12
31
  protected userEmail$: BehaviorSubject<string>;
13
32
  private _initialPath;
14
33
  private _initialSearch;
@@ -20,92 +39,228 @@ export declare abstract class MJAuthBase implements IAngularAuthProvider {
20
39
  * Contains the initial search/query string from window.location.search before any work was done by auth services
21
40
  */
22
41
  get initialSearch(): string | null;
23
- abstract type: string;
42
+ /**
43
+ * Provider type identifier
44
+ * Must be implemented by concrete providers
45
+ */
46
+ abstract readonly type: string;
24
47
  constructor(config: AngularAuthProviderConfig);
25
48
  /**
26
- * Initialize the authentication provider
27
- * Override in subclasses to setup provider-specific initialization
49
+ * Initialize the provider
50
+ *
51
+ * Subclasses should override to set up provider-specific initialization,
52
+ * handle redirect callbacks, restore sessions, etc.
28
53
  */
29
54
  abstract initialize(): Promise<void>;
30
55
  /**
31
- * Login the user - internal implementation
32
- * Override to implement provider-specific login flow
56
+ * Internal login implementation
57
+ *
58
+ * Subclasses implement provider-specific login flow.
59
+ * This is called by the public login() method.
33
60
  */
34
- protected abstract loginInternal(options?: any): Promise<void>;
61
+ protected abstract loginInternal(options?: Record<string, unknown>): Promise<void>;
35
62
  /**
36
- * Login the user - public API that returns Observable for backward compatibility
63
+ * Logout implementation
64
+ *
65
+ * Subclasses implement provider-specific logout flow.
37
66
  */
38
- login(options?: any): Observable<void>;
67
+ abstract logout(): Promise<void>;
39
68
  /**
40
- * Logout the user
41
- * Override to implement provider-specific logout flow
69
+ * Handle OAuth callback
70
+ *
71
+ * Subclasses implement provider-specific callback handling.
42
72
  */
43
- abstract logout(): Promise<void>;
73
+ abstract handleCallback(): Promise<void>;
44
74
  /**
45
- * Get the current access token
46
- * Override to retrieve token from provider-specific storage
75
+ * Extract ID token from provider-specific storage
76
+ *
77
+ * This is where providers hide their implementation details.
78
+ * - Auth0: Extracts from claims.__raw
79
+ * - MSAL: Extracts from response.idToken
80
+ * - Okta: Extracts from authState.idToken
81
+ *
82
+ * @returns Promise resolving to token string or null if not authenticated
47
83
  */
48
- abstract getToken(): Promise<string | null>;
84
+ protected abstract extractIdTokenInternal(): Promise<string | null>;
49
85
  /**
50
- * Handle callback after redirect
51
- * Override to process provider-specific callback logic
86
+ * Extract complete token info from provider-specific storage
87
+ *
88
+ * Maps provider-specific token structure to StandardAuthToken.
89
+ *
90
+ * @returns Promise resolving to StandardAuthToken or null if not authenticated
52
91
  */
53
- abstract handleCallback(): Promise<void>;
92
+ protected abstract extractTokenInfoInternal(): Promise<StandardAuthToken | null>;
54
93
  /**
55
- * Check if user is authenticated
94
+ * Extract user info from provider-specific claims
95
+ *
96
+ * Maps provider-specific claim structure to StandardUserInfo.
97
+ * This is where providers translate their claims (sub, email, name, etc.)
98
+ * into the standard structure.
99
+ *
100
+ * @returns Promise resolving to StandardUserInfo or null if not authenticated
56
101
  */
57
- isAuthenticated(): Observable<boolean>;
102
+ protected abstract extractUserInfoInternal(): Promise<StandardUserInfo | null>;
58
103
  /**
59
- * Get user profile information
104
+ * Refresh token using provider-specific mechanism
105
+ *
106
+ * Implements the provider's token refresh logic.
107
+ * - Auth0: Uses getAccessTokenSilently with ignoreCache
108
+ * - MSAL: Uses acquireTokenSilent with forceRefresh
109
+ * - Okta: Uses tokenManager.renew
110
+ *
111
+ * @returns Promise resolving to TokenRefreshResult indicating success/failure
60
112
  */
61
- getUserProfile(): Observable<any>;
113
+ protected abstract refreshTokenInternal(): Promise<TokenRefreshResult>;
62
114
  /**
63
- * Get user email
115
+ * Classify provider-specific error into standard error type
116
+ *
117
+ * Maps provider-specific errors to semantic AuthErrorType values.
118
+ * Examples:
119
+ * - Auth0: "jwt expired" → TOKEN_EXPIRED
120
+ * - MSAL: BrowserAuthError → NO_ACTIVE_SESSION
121
+ * - MSAL: InteractionRequiredAuthError → INTERACTION_REQUIRED
122
+ *
123
+ * @param error The error to classify
124
+ * @returns StandardAuthError with categorized type and user-friendly message
64
125
  */
65
- getUserEmail(): Observable<string>;
126
+ protected abstract classifyErrorInternal(error: unknown): StandardAuthError;
66
127
  /**
67
- * Get provider-specific configuration requirements
68
- * Override to specify required config fields
128
+ * Get profile picture URL from auth provider
129
+ *
130
+ * Each provider implements its own logic:
131
+ * - MSAL: Fetches from Microsoft Graph API using access token
132
+ * - Auth0/Okta: Returns pictureUrl from user claims (already available)
133
+ *
134
+ * @returns Promise resolving to image URL or null if not available
69
135
  */
70
- getRequiredConfig(): string[];
136
+ protected abstract getProfilePictureUrlInternal(): Promise<string | null>;
71
137
  /**
72
- * Validate provider configuration
73
- * Override to add provider-specific validation
138
+ * Public login method with Observable wrapper for backward compatibility
139
+ *
140
+ * Consumers can use either:
141
+ * - `await this.authBase.login()` (Promise)
142
+ * - `this.authBase.login().subscribe()` (Observable)
74
143
  */
75
- validateConfig(config: any): boolean;
144
+ login(options?: Record<string, unknown>): Observable<void>;
76
145
  /**
77
- * Helper method to update authentication state
146
+ * Check if user is authenticated (Observable stream)
147
+ *
148
+ * Returns a reactive stream that emits authentication state changes.
149
+ * Consumers can subscribe to react to login/logout events.
78
150
  */
79
- protected updateAuthState(isAuthenticated: boolean): void;
151
+ isAuthenticated(): Observable<boolean>;
80
152
  /**
81
- * Helper method to update user profile
153
+ * Get user info as Observable stream
154
+ *
155
+ * Returns standardized user info, hiding provider-specific claim structures.
156
+ * No more need for consumers to merge claims or check provider-specific fields!
82
157
  */
83
- protected updateUserProfile(profile: any): void;
158
+ getUserInfo(): Observable<StandardUserInfo | null>;
84
159
  /**
85
- * Legacy property for authentication state
160
+ * Get user email as Observable stream
86
161
  */
87
- get authenticated(): boolean;
162
+ getUserEmail(): Observable<string>;
163
+ /**
164
+ * Get ID token string (primary token method)
165
+ *
166
+ * This is the clean abstraction - no provider-specific logic needed!
167
+ * Replaces the old pattern of: `claims?.__raw || claims?.idToken`
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const token = await this.authBase.getIdToken();
172
+ * if (token) {
173
+ * setupGraphQLClient(token, apiUrl);
174
+ * }
175
+ * ```
176
+ */
177
+ getIdToken(): Promise<string | null>;
178
+ /**
179
+ * Get complete token information
180
+ *
181
+ * Returns full token details including expiration and scopes.
182
+ * Use this when you need more than just the token string.
183
+ */
184
+ getTokenInfo(): Promise<StandardAuthToken | null>;
185
+ /**
186
+ * Refresh authentication token
187
+ *
188
+ * Attempts to refresh the token without user interaction.
189
+ * Returns a result object indicating success or failure with details.
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * const result = await this.authBase.refreshToken();
194
+ * if (result.success && result.token) {
195
+ * return result.token.idToken;
196
+ * } else {
197
+ * throw new Error(result.error?.userMessage || 'Refresh failed');
198
+ * }
199
+ * ```
200
+ */
201
+ refreshToken(): Promise<TokenRefreshResult>;
202
+ /**
203
+ * Classify an error into standard error type
204
+ *
205
+ * Converts provider-specific errors into semantic categories.
206
+ * Eliminates need for consumers to check error.name or error types.
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * const authError = this.authBase.classifyError(err);
211
+ * if (authError.type === AuthErrorType.TOKEN_EXPIRED) {
212
+ * this.showMessage(authError.userMessage);
213
+ * }
214
+ * ```
215
+ */
216
+ classifyError(error: unknown): StandardAuthError;
88
217
  /**
89
- * Legacy setter for authentication state
90
- * Used by MJExplorer for backward compatibility
218
+ * Get profile picture URL from auth provider
219
+ *
220
+ * Returns the user's profile picture URL if available from the auth provider.
221
+ * This abstracts away provider-specific logic:
222
+ * - Microsoft/MSAL: Fetches from Graph API
223
+ * - Auth0/Okta: Returns from user claims
224
+ *
225
+ * @returns Promise resolving to image URL or null if not available
226
+ *
227
+ * @example
228
+ * ```typescript
229
+ * const pictureUrl = await this.authBase.getProfilePictureUrl();
230
+ * if (pictureUrl) {
231
+ * this.userAvatar = pictureUrl;
232
+ * }
233
+ * ```
91
234
  */
92
- set authenticated(value: boolean);
235
+ getProfilePictureUrl(): Promise<string | null>;
93
236
  /**
94
- * Legacy method to get user
237
+ * Update authentication state
238
+ *
239
+ * Subclasses should call this when authentication state changes
240
+ * (after login, logout, session check, etc.)
95
241
  */
96
- getUser(): Promise<any>;
242
+ protected updateAuthState(isAuthenticated: boolean): void;
97
243
  /**
98
- * Legacy method to get user claims
244
+ * Update user info
245
+ *
246
+ * Subclasses should call this when user info is retrieved or updated.
247
+ * This automatically updates the email stream as well.
99
248
  */
100
- getUserClaims(): Promise<Observable<any>>;
249
+ protected updateUserInfo(userInfo: StandardUserInfo | null): void;
101
250
  /**
102
- * Legacy method to check expired token error
251
+ * Get required configuration fields
252
+ *
253
+ * Default implementation requires clientId.
254
+ * Subclasses can override to add provider-specific requirements.
103
255
  */
104
- checkExpiredTokenError(error: string): boolean;
256
+ getRequiredConfig(): string[];
105
257
  /**
106
- * Legacy refresh method
258
+ * Validate provider configuration
259
+ *
260
+ * Checks that all required fields are present and non-empty.
261
+ * Subclasses can override to add custom validation logic.
107
262
  */
108
- refresh(): Promise<Observable<any>>;
263
+ validateConfig(config: Record<string, unknown>): boolean;
109
264
  static ɵfac: i0.ɵɵFactoryDeclaration<MJAuthBase, never>;
110
265
  static ɵprov: i0.ɵɵInjectableDeclaration<MJAuthBase>;
111
266
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mjexplorer-auth-base.service.d.ts","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAQ,MAAM,MAAM,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;;AAElF;;;GAGG;AACH,8BACsB,UAAW,YAAW,oBAAoB;IAC9D,SAAS,CAAC,MAAM,EAAE,yBAAyB,CAAC;IAC5C,SAAS,CAAC,gBAAgB,2BAAuC;IACjE,SAAS,CAAC,YAAY,uBAAkC;IACxD,SAAS,CAAC,UAAU,0BAAmC;IAEvD,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,cAAc,CAAuB;IAC7C;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IACD;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,GAAG,IAAI,CAEjC;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,MAAM,EAAE,yBAAyB;IAM7C;;;OAGG;IACH,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAEpC;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAE9D;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC;IAItC;;;OAGG;IACH,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAE3C;;;OAGG;IACH,QAAQ,CAAC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAExC;;OAEG;IACH,eAAe,IAAI,UAAU,CAAC,OAAO,CAAC;IAItC;;OAEG;IACH,cAAc,IAAI,UAAU,CAAC,GAAG,CAAC;IAIjC;;OAEG;IACH,YAAY,IAAI,UAAU,CAAC,MAAM,CAAC;IAIlC;;;OAGG;IACH,iBAAiB,IAAI,MAAM,EAAE;IAI7B;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO;IAKpC;;OAEG;IACH,SAAS,CAAC,eAAe,CAAC,eAAe,EAAE,OAAO,GAAG,IAAI;IAIzD;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAS/C;;OAEG;IACH,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED;;;OAGG;IACH,IAAI,aAAa,CAAC,KAAK,EAAE,OAAO,EAE/B;IAED;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC;IAI7B;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAI/C;;OAEG;IACH,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAO9C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;yCArKrB,UAAU;6CAAV,UAAU;CA0K/B"}
1
+ {"version":3,"file":"mjexplorer-auth-base.service.d.ts","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"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"}
@@ -2,13 +2,32 @@ import { Injectable } from '@angular/core';
2
2
  import { BehaviorSubject, from } from 'rxjs';
3
3
  import * as i0 from "@angular/core";
4
4
  /**
5
- * Base class for Angular authentication providers
6
- * Provides common functionality and enforces the provider interface
5
+ * Base class for Angular authentication providers - v3.0.0
6
+ *
7
+ * Provides common functionality and enforces the provider interface.
8
+ * All concrete providers (MSAL, Auth0, Okta) should extend this class.
9
+ *
10
+ * ## Key Improvements in v3.0:
11
+ * - Proper abstraction - no more leaky provider-specific logic
12
+ * - Standardized types - no more `any` types
13
+ * - Clean token access - no more `__raw || idToken` patterns
14
+ * - Semantic error handling - no more provider-specific error checks
15
+ *
16
+ * ## For Provider Implementers:
17
+ * Extend this class and implement the abstract methods:
18
+ * - `extractIdTokenInternal()` - Extract token from provider storage
19
+ * - `extractTokenInfoInternal()` - Extract full token info
20
+ * - `extractUserInfoInternal()` - Map claims to StandardUserInfo
21
+ * - `refreshTokenInternal()` - Implement refresh mechanism
22
+ * - `classifyErrorInternal()` - Map errors to AuthErrorType
23
+ *
24
+ * @version 3.0.0
7
25
  */
8
26
  export class MJAuthBase {
9
27
  config;
28
+ // State management with proper types (no more 'any'!)
10
29
  isAuthenticated$ = new BehaviorSubject(false);
11
- userProfile$ = new BehaviorSubject(null);
30
+ userInfo$ = new BehaviorSubject(null);
12
31
  userEmail$ = new BehaviorSubject('');
13
32
  _initialPath = null;
14
33
  _initialSearch = null;
@@ -29,102 +48,189 @@ export class MJAuthBase {
29
48
  this._initialPath = window.location.pathname;
30
49
  this._initialSearch = window.location.search;
31
50
  }
51
+ // ============================================================================
52
+ // PUBLIC API (Concrete implementations using abstract internals)
53
+ // ============================================================================
32
54
  /**
33
- * Login the user - public API that returns Observable for backward compatibility
55
+ * Public login method with Observable wrapper for backward compatibility
56
+ *
57
+ * Consumers can use either:
58
+ * - `await this.authBase.login()` (Promise)
59
+ * - `this.authBase.login().subscribe()` (Observable)
34
60
  */
35
61
  login(options) {
36
62
  return from(this.loginInternal(options));
37
63
  }
38
64
  /**
39
- * Check if user is authenticated
65
+ * Check if user is authenticated (Observable stream)
66
+ *
67
+ * Returns a reactive stream that emits authentication state changes.
68
+ * Consumers can subscribe to react to login/logout events.
40
69
  */
41
70
  isAuthenticated() {
42
71
  return this.isAuthenticated$.asObservable();
43
72
  }
44
73
  /**
45
- * Get user profile information
74
+ * Get user info as Observable stream
75
+ *
76
+ * Returns standardized user info, hiding provider-specific claim structures.
77
+ * No more need for consumers to merge claims or check provider-specific fields!
46
78
  */
47
- getUserProfile() {
48
- return this.userProfile$.asObservable();
79
+ getUserInfo() {
80
+ return this.userInfo$.asObservable();
49
81
  }
50
82
  /**
51
- * Get user email
83
+ * Get user email as Observable stream
52
84
  */
53
85
  getUserEmail() {
54
86
  return this.userEmail$.asObservable();
55
87
  }
56
88
  /**
57
- * Get provider-specific configuration requirements
58
- * Override to specify required config fields
59
- */
60
- getRequiredConfig() {
61
- return ['clientId'];
62
- }
63
- /**
64
- * Validate provider configuration
65
- * Override to add provider-specific validation
66
- */
67
- validateConfig(config) {
68
- const requiredFields = this.getRequiredConfig();
69
- return requiredFields.every(field => config[field] !== undefined && config[field] !== '');
70
- }
71
- /**
72
- * Helper method to update authentication state
89
+ * Get ID token string (primary token method)
90
+ *
91
+ * This is the clean abstraction - no provider-specific logic needed!
92
+ * Replaces the old pattern of: `claims?.__raw || claims?.idToken`
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * const token = await this.authBase.getIdToken();
97
+ * if (token) {
98
+ * setupGraphQLClient(token, apiUrl);
99
+ * }
100
+ * ```
101
+ */
102
+ async getIdToken() {
103
+ return this.extractIdTokenInternal();
104
+ }
105
+ /**
106
+ * Get complete token information
107
+ *
108
+ * Returns full token details including expiration and scopes.
109
+ * Use this when you need more than just the token string.
110
+ */
111
+ async getTokenInfo() {
112
+ return this.extractTokenInfoInternal();
113
+ }
114
+ /**
115
+ * Refresh authentication token
116
+ *
117
+ * Attempts to refresh the token without user interaction.
118
+ * Returns a result object indicating success or failure with details.
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * const result = await this.authBase.refreshToken();
123
+ * if (result.success && result.token) {
124
+ * return result.token.idToken;
125
+ * } else {
126
+ * throw new Error(result.error?.userMessage || 'Refresh failed');
127
+ * }
128
+ * ```
129
+ */
130
+ async refreshToken() {
131
+ const result = await this.refreshTokenInternal();
132
+ // Update state if refresh succeeded
133
+ if (result.success && result.token) {
134
+ // Optionally refresh user info to keep it in sync
135
+ try {
136
+ const userInfo = await this.extractUserInfoInternal();
137
+ if (userInfo) {
138
+ this.updateUserInfo(userInfo);
139
+ }
140
+ }
141
+ catch {
142
+ // User info update failed, but token refresh succeeded
143
+ // Don't fail the entire refresh for this
144
+ }
145
+ }
146
+ return result;
147
+ }
148
+ /**
149
+ * Classify an error into standard error type
150
+ *
151
+ * Converts provider-specific errors into semantic categories.
152
+ * Eliminates need for consumers to check error.name or error types.
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const authError = this.authBase.classifyError(err);
157
+ * if (authError.type === AuthErrorType.TOKEN_EXPIRED) {
158
+ * this.showMessage(authError.userMessage);
159
+ * }
160
+ * ```
161
+ */
162
+ classifyError(error) {
163
+ return this.classifyErrorInternal(error);
164
+ }
165
+ /**
166
+ * Get profile picture URL from auth provider
167
+ *
168
+ * Returns the user's profile picture URL if available from the auth provider.
169
+ * This abstracts away provider-specific logic:
170
+ * - Microsoft/MSAL: Fetches from Graph API
171
+ * - Auth0/Okta: Returns from user claims
172
+ *
173
+ * @returns Promise resolving to image URL or null if not available
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * const pictureUrl = await this.authBase.getProfilePictureUrl();
178
+ * if (pictureUrl) {
179
+ * this.userAvatar = pictureUrl;
180
+ * }
181
+ * ```
182
+ */
183
+ async getProfilePictureUrl() {
184
+ return this.getProfilePictureUrlInternal();
185
+ }
186
+ // ============================================================================
187
+ // HELPER METHODS (For subclasses to update state)
188
+ // ============================================================================
189
+ /**
190
+ * Update authentication state
191
+ *
192
+ * Subclasses should call this when authentication state changes
193
+ * (after login, logout, session check, etc.)
73
194
  */
74
195
  updateAuthState(isAuthenticated) {
75
196
  this.isAuthenticated$.next(isAuthenticated);
76
197
  }
77
198
  /**
78
- * Helper method to update user profile
199
+ * Update user info
200
+ *
201
+ * Subclasses should call this when user info is retrieved or updated.
202
+ * This automatically updates the email stream as well.
79
203
  */
80
- updateUserProfile(profile) {
81
- this.userProfile$.next(profile);
82
- if (profile?.email) {
83
- this.userEmail$.next(profile.email);
204
+ updateUserInfo(userInfo) {
205
+ this.userInfo$.next(userInfo);
206
+ if (userInfo?.email) {
207
+ this.userEmail$.next(userInfo.email);
208
+ }
209
+ else {
210
+ this.userEmail$.next('');
84
211
  }
85
212
  }
86
- // Backward compatibility methods for existing code
87
- /**
88
- * Legacy property for authentication state
89
- */
90
- get authenticated() {
91
- return this.isAuthenticated$.value;
92
- }
93
- /**
94
- * Legacy setter for authentication state
95
- * Used by MJExplorer for backward compatibility
96
- */
97
- set authenticated(value) {
98
- this.updateAuthState(value);
99
- }
100
- /**
101
- * Legacy method to get user
102
- */
103
- async getUser() {
104
- return this.userProfile$.value;
105
- }
106
- /**
107
- * Legacy method to get user claims
108
- */
109
- async getUserClaims() {
110
- return this.userProfile$.asObservable();
111
- }
213
+ // ============================================================================
214
+ // CONFIGURATION & VALIDATION
215
+ // ============================================================================
112
216
  /**
113
- * Legacy method to check expired token error
217
+ * Get required configuration fields
218
+ *
219
+ * Default implementation requires clientId.
220
+ * Subclasses can override to add provider-specific requirements.
114
221
  */
115
- checkExpiredTokenError(error) {
116
- // Check for common token expiration error messages
117
- return error?.toLowerCase().includes('expired') ||
118
- error?.toLowerCase().includes('invalid token') ||
119
- error?.toLowerCase().includes('unauthorized');
222
+ getRequiredConfig() {
223
+ return ['clientId'];
120
224
  }
121
225
  /**
122
- * Legacy refresh method
226
+ * Validate provider configuration
227
+ *
228
+ * Checks that all required fields are present and non-empty.
229
+ * Subclasses can override to add custom validation logic.
123
230
  */
124
- async refresh() {
125
- // Try to get a new token
126
- await this.getToken();
127
- return this.userProfile$.asObservable();
231
+ validateConfig(config) {
232
+ const requiredFields = this.getRequiredConfig();
233
+ return requiredFields.every(field => config[field] !== undefined && config[field] !== '');
128
234
  }
129
235
  static ɵfac = function MJAuthBase_Factory(t) { i0.ɵɵinvalidFactory(); };
130
236
  static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MJAuthBase, factory: MJAuthBase.ɵfac });
@@ -1 +1 @@
1
- {"version":3,"file":"mjexplorer-auth-base.service.js","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mjexplorer-auth-base.service.js","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"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"}