@memberjunction/ng-auth-services 2.128.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.
- package/dist/lib/IAuthProvider.d.ts +177 -17
- package/dist/lib/IAuthProvider.d.ts.map +1 -1
- package/dist/lib/auth-types.d.ts +351 -0
- package/dist/lib/auth-types.d.ts.map +1 -0
- package/dist/lib/auth-types.js +98 -0
- package/dist/lib/auth-types.js.map +1 -0
- package/dist/lib/mjexplorer-auth-base.service.d.ts +204 -49
- package/dist/lib/mjexplorer-auth-base.service.d.ts.map +1 -1
- package/dist/lib/mjexplorer-auth-base.service.js +173 -67
- package/dist/lib/mjexplorer-auth-base.service.js.map +1 -1
- package/dist/lib/providers/mjexplorer-auth0-provider.service.d.ts +61 -17
- package/dist/lib/providers/mjexplorer-auth0-provider.service.d.ts.map +1 -1
- package/dist/lib/providers/mjexplorer-auth0-provider.service.js +245 -76
- package/dist/lib/providers/mjexplorer-auth0-provider.service.js.map +1 -1
- package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts +57 -16
- package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts.map +1 -1
- package/dist/lib/providers/mjexplorer-msal-provider.service.js +311 -114
- package/dist/lib/providers/mjexplorer-msal-provider.service.js.map +1 -1
- package/dist/lib/providers/mjexplorer-okta-provider.service.d.ts +55 -30
- package/dist/lib/providers/mjexplorer-okta-provider.service.d.ts.map +1 -1
- package/dist/lib/providers/mjexplorer-okta-provider.service.js +263 -235
- package/dist/lib/providers/mjexplorer-okta-provider.service.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- 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
|
-
*
|
|
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
|
|
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
|
-
|
|
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
|
|
27
|
-
*
|
|
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
|
-
*
|
|
32
|
-
*
|
|
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?:
|
|
61
|
+
protected abstract loginInternal(options?: Record<string, unknown>): Promise<void>;
|
|
35
62
|
/**
|
|
36
|
-
*
|
|
63
|
+
* Logout implementation
|
|
64
|
+
*
|
|
65
|
+
* Subclasses implement provider-specific logout flow.
|
|
37
66
|
*/
|
|
38
|
-
|
|
67
|
+
abstract logout(): Promise<void>;
|
|
39
68
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
69
|
+
* Handle OAuth callback
|
|
70
|
+
*
|
|
71
|
+
* Subclasses implement provider-specific callback handling.
|
|
42
72
|
*/
|
|
43
|
-
abstract
|
|
73
|
+
abstract handleCallback(): Promise<void>;
|
|
44
74
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
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
|
|
84
|
+
protected abstract extractIdTokenInternal(): Promise<string | null>;
|
|
49
85
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
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
|
|
92
|
+
protected abstract extractTokenInfoInternal(): Promise<StandardAuthToken | null>;
|
|
54
93
|
/**
|
|
55
|
-
*
|
|
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
|
-
|
|
102
|
+
protected abstract extractUserInfoInternal(): Promise<StandardUserInfo | null>;
|
|
58
103
|
/**
|
|
59
|
-
*
|
|
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
|
-
|
|
113
|
+
protected abstract refreshTokenInternal(): Promise<TokenRefreshResult>;
|
|
62
114
|
/**
|
|
63
|
-
*
|
|
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
|
-
|
|
126
|
+
protected abstract classifyErrorInternal(error: unknown): StandardAuthError;
|
|
66
127
|
/**
|
|
67
|
-
* Get
|
|
68
|
-
*
|
|
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
|
-
|
|
136
|
+
protected abstract getProfilePictureUrlInternal(): Promise<string | null>;
|
|
71
137
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
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
|
-
|
|
144
|
+
login(options?: Record<string, unknown>): Observable<void>;
|
|
76
145
|
/**
|
|
77
|
-
*
|
|
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
|
-
|
|
151
|
+
isAuthenticated(): Observable<boolean>;
|
|
80
152
|
/**
|
|
81
|
-
*
|
|
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
|
-
|
|
158
|
+
getUserInfo(): Observable<StandardUserInfo | null>;
|
|
84
159
|
/**
|
|
85
|
-
*
|
|
160
|
+
* Get user email as Observable stream
|
|
86
161
|
*/
|
|
87
|
-
|
|
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
|
-
*
|
|
90
|
-
*
|
|
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
|
-
|
|
235
|
+
getProfilePictureUrl(): Promise<string | null>;
|
|
93
236
|
/**
|
|
94
|
-
*
|
|
237
|
+
* Update authentication state
|
|
238
|
+
*
|
|
239
|
+
* Subclasses should call this when authentication state changes
|
|
240
|
+
* (after login, logout, session check, etc.)
|
|
95
241
|
*/
|
|
96
|
-
|
|
242
|
+
protected updateAuthState(isAuthenticated: boolean): void;
|
|
97
243
|
/**
|
|
98
|
-
*
|
|
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
|
-
|
|
249
|
+
protected updateUserInfo(userInfo: StandardUserInfo | null): void;
|
|
101
250
|
/**
|
|
102
|
-
*
|
|
251
|
+
* Get required configuration fields
|
|
252
|
+
*
|
|
253
|
+
* Default implementation requires clientId.
|
|
254
|
+
* Subclasses can override to add provider-specific requirements.
|
|
103
255
|
*/
|
|
104
|
-
|
|
256
|
+
getRequiredConfig(): string[];
|
|
105
257
|
/**
|
|
106
|
-
*
|
|
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
|
-
|
|
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;;
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
48
|
-
return this.
|
|
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
|
|
58
|
-
*
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
81
|
-
this.
|
|
82
|
-
if (
|
|
83
|
-
this.userEmail$.next(
|
|
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
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
*
|
|
217
|
+
* Get required configuration fields
|
|
218
|
+
*
|
|
219
|
+
* Default implementation requires clientId.
|
|
220
|
+
* Subclasses can override to add provider-specific requirements.
|
|
114
221
|
*/
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAc,eAAe,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;;
|
|
1
|
+
{"version":3,"file":"mjexplorer-auth-base.service.js","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAc,eAAe,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;;AASzD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,OAAgB,UAAU;IACpB,MAAM,CAA4B;IAE5C,sDAAsD;IAC5C,gBAAgB,GAAG,IAAI,eAAe,CAAU,KAAK,CAAC,CAAC;IACvD,SAAS,GAAG,IAAI,eAAe,CAA0B,IAAI,CAAC,CAAC;IAC/D,UAAU,GAAG,IAAI,eAAe,CAAS,EAAE,CAAC,CAAC;IAE/C,YAAY,GAAkB,IAAI,CAAC;IACnC,cAAc,GAAkB,IAAI,CAAC;IAE7C;;OAEG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAQD,YAAY,MAAiC;QAC3C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7C,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IAC/C,CAAC;IAyGD,+EAA+E;IAC/E,iEAAiE;IACjE,+EAA+E;IAE/E;;;;;;OAMG;IACH,KAAK,CAAC,OAAiC;QACrC,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,CAAC;IAC9C,CAAC;IAED;;;;;OAKG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC;IACxC,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,sBAAsB,EAAE,CAAC;IACvC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,wBAAwB,EAAE,CAAC;IACzC,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,YAAY;QAChB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAEjD,oCAAoC;QACpC,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACnC,kDAAkD;YAClD,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;gBACtD,IAAI,QAAQ,EAAE,CAAC;oBACb,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,uDAAuD;gBACvD,yCAAyC;YAC3C,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,aAAa,CAAC,KAAc;QAC1B,OAAO,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,oBAAoB;QACxB,OAAO,IAAI,CAAC,4BAA4B,EAAE,CAAC;IAC7C,CAAC;IAED,+EAA+E;IAC/E,kDAAkD;IAClD,+EAA+E;IAE/E;;;;;OAKG;IACO,eAAe,CAAC,eAAwB;QAChD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;OAKG;IACO,cAAc,CAAC,QAAiC;QACxD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE9B,IAAI,QAAQ,EAAE,KAAK,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,+EAA+E;IAC/E,6BAA6B;IAC7B,+EAA+E;IAE/E;;;;;OAKG;IACH,iBAAiB;QACf,OAAO,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,MAA+B;QAC5C,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAChD,OAAO,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAClC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CACpD,CAAC;IACJ,CAAC;;gEArVmB,UAAU,WAAV,UAAU;;iFAAV,UAAU;cAD/B,UAAU"}
|