@memberjunction/ng-auth-services 2.129.0 → 2.130.1
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 +179 -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 +225 -49
- package/dist/lib/mjexplorer-auth-base.service.d.ts.map +1 -1
- package/dist/lib/mjexplorer-auth-base.service.js +189 -54
- package/dist/lib/mjexplorer-auth-base.service.js.map +1 -1
- package/dist/lib/providers/mjexplorer-auth0-provider.service.d.ts +69 -17
- package/dist/lib/providers/mjexplorer-auth0-provider.service.d.ts.map +1 -1
- package/dist/lib/providers/mjexplorer-auth0-provider.service.js +255 -75
- package/dist/lib/providers/mjexplorer-auth0-provider.service.js.map +1 -1
- package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts +65 -16
- package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts.map +1 -1
- package/dist/lib/providers/mjexplorer-msal-provider.service.js +345 -113
- package/dist/lib/providers/mjexplorer-msal-provider.service.js.map +1 -1
- package/dist/lib/providers/mjexplorer-okta-provider.service.d.ts +63 -30
- package/dist/lib/providers/mjexplorer-okta-provider.service.d.ts.map +1 -1
- package/dist/lib/providers/mjexplorer-okta-provider.service.js +273 -234
- 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,55 +1,217 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
2
|
import { AuthProviderConfig } from '@memberjunction/core';
|
|
3
|
+
import { StandardUserInfo, StandardAuthToken, StandardAuthError } from './auth-types';
|
|
3
4
|
export interface AngularAuthProviderConfig extends AuthProviderConfig {
|
|
4
5
|
}
|
|
5
6
|
/**
|
|
6
|
-
* Interface for Angular authentication providers
|
|
7
|
-
*
|
|
7
|
+
* Interface for Angular authentication providers - v3.0.0
|
|
8
|
+
*
|
|
9
|
+
* This interface defines the contract that all auth providers must implement.
|
|
10
|
+
* It ensures consistent behavior across different OAuth providers while hiding
|
|
11
|
+
* provider-specific implementation details.
|
|
12
|
+
*
|
|
13
|
+
* ## Breaking Changes from v2.x:
|
|
14
|
+
* - Removed: getUserProfile() - Use getUserInfo() instead
|
|
15
|
+
* - Removed: getUser() - Use getUserInfo() instead
|
|
16
|
+
* - Removed: getUserClaims() - Use getTokenInfo() instead
|
|
17
|
+
* - Removed: getToken() - Use getIdToken() instead
|
|
18
|
+
* - Removed: refresh() - Use refreshToken() instead
|
|
19
|
+
* - Removed: checkExpiredTokenError() - Use classifyError() instead
|
|
20
|
+
*
|
|
21
|
+
* @version 3.0.0
|
|
8
22
|
*/
|
|
9
23
|
export interface IAngularAuthProvider {
|
|
10
24
|
/**
|
|
11
25
|
* Provider type identifier (e.g., 'msal', 'auth0', 'okta')
|
|
12
26
|
*/
|
|
13
|
-
type: string;
|
|
27
|
+
readonly type: string;
|
|
14
28
|
/**
|
|
15
29
|
* Initialize the authentication provider
|
|
30
|
+
*
|
|
31
|
+
* This should handle callback processing, session restoration, etc.
|
|
32
|
+
* Called automatically during app startup.
|
|
16
33
|
*/
|
|
17
34
|
initialize(): Promise<void>;
|
|
18
35
|
/**
|
|
19
|
-
*
|
|
36
|
+
* Initiate login flow
|
|
37
|
+
*
|
|
38
|
+
* @param options Optional provider-specific login options
|
|
39
|
+
* @returns Observable for backward compatibility, can also return Promise
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* await this.authBase.login({ appState: { target: '/dashboard' } });
|
|
44
|
+
* ```
|
|
20
45
|
*/
|
|
21
|
-
login(options?:
|
|
46
|
+
login(options?: Record<string, unknown>): Observable<void> | Promise<void>;
|
|
22
47
|
/**
|
|
23
|
-
*
|
|
48
|
+
* Log out the current user
|
|
49
|
+
*
|
|
50
|
+
* Clears local session and redirects to provider's logout endpoint.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* await this.authBase.logout();
|
|
55
|
+
* ```
|
|
24
56
|
*/
|
|
25
57
|
logout(): Promise<void>;
|
|
26
58
|
/**
|
|
27
|
-
*
|
|
59
|
+
* Handle OAuth callback after redirect
|
|
60
|
+
*
|
|
61
|
+
* This is called automatically by the redirect component.
|
|
62
|
+
* Application code typically doesn't need to call this directly.
|
|
28
63
|
*/
|
|
29
|
-
|
|
64
|
+
handleCallback(): Promise<void>;
|
|
30
65
|
/**
|
|
31
|
-
*
|
|
66
|
+
* Observable stream of authentication state
|
|
67
|
+
*
|
|
68
|
+
* Emits true when user is authenticated, false otherwise.
|
|
69
|
+
* Subscribe to this for reactive UI updates.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* this.authBase.isAuthenticated().subscribe(isAuth => {
|
|
74
|
+
* this.showLoginButton = !isAuth;
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
32
77
|
*/
|
|
33
|
-
|
|
78
|
+
isAuthenticated(): Observable<boolean>;
|
|
34
79
|
/**
|
|
35
|
-
*
|
|
80
|
+
* Observable stream of user profile information
|
|
81
|
+
*
|
|
82
|
+
* Emits StandardUserInfo when authenticated, null otherwise.
|
|
83
|
+
* This replaces the old getUserProfile() which returned 'any'.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* this.authBase.getUserInfo().subscribe(user => {
|
|
88
|
+
* if (user) {
|
|
89
|
+
* console.log(`Welcome ${user.name}!`);
|
|
90
|
+
* }
|
|
91
|
+
* });
|
|
92
|
+
* ```
|
|
36
93
|
*/
|
|
37
|
-
|
|
94
|
+
getUserInfo(): Observable<StandardUserInfo | null>;
|
|
38
95
|
/**
|
|
39
|
-
*
|
|
96
|
+
* Observable stream of user's email address
|
|
97
|
+
*
|
|
98
|
+
* Emits email string when authenticated, empty string otherwise.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* this.userEmail$ = this.authBase.getUserEmail();
|
|
103
|
+
* ```
|
|
40
104
|
*/
|
|
41
105
|
getUserEmail(): Observable<string>;
|
|
42
106
|
/**
|
|
43
|
-
*
|
|
107
|
+
* Get the current ID token as a string
|
|
108
|
+
*
|
|
109
|
+
* This is the primary method applications should use to get the token
|
|
110
|
+
* for backend API calls. It abstracts away provider-specific token storage
|
|
111
|
+
* (Auth0's __raw vs MSAL's idToken).
|
|
112
|
+
*
|
|
113
|
+
* @returns Promise resolving to the ID token string, or null if not authenticated
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const token = await this.authBase.getIdToken();
|
|
118
|
+
* if (token) {
|
|
119
|
+
* // Use token for GraphQL or REST API calls
|
|
120
|
+
* setupGraphQLClient(token, apiUrl);
|
|
121
|
+
* }
|
|
122
|
+
* ```
|
|
44
123
|
*/
|
|
45
|
-
|
|
124
|
+
getIdToken(): Promise<string | null>;
|
|
125
|
+
/**
|
|
126
|
+
* Get complete token information
|
|
127
|
+
*
|
|
128
|
+
* Returns a standardized token object with ID token, access token, and expiration.
|
|
129
|
+
* Use this when you need more than just the token string.
|
|
130
|
+
*
|
|
131
|
+
* @returns Promise resolving to StandardAuthToken or null if not authenticated
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const tokenInfo = await this.authBase.getTokenInfo();
|
|
136
|
+
* if (tokenInfo) {
|
|
137
|
+
* console.log(`Token expires at: ${new Date(tokenInfo.expiresAt)}`);
|
|
138
|
+
* }
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
getTokenInfo(): Promise<StandardAuthToken | null>;
|
|
142
|
+
/**
|
|
143
|
+
* Refresh the current authentication token
|
|
144
|
+
*
|
|
145
|
+
* Attempts to obtain a fresh authentication token using the provider's
|
|
146
|
+
* refresh mechanism. If silent refresh fails due to session expiry, the
|
|
147
|
+
* provider will handle re-authentication automatically (which may involve
|
|
148
|
+
* redirecting to the auth provider's login page).
|
|
149
|
+
*
|
|
150
|
+
* Returns a fresh token on success, or throws on complete failure.
|
|
151
|
+
*
|
|
152
|
+
* IMPORTANT: If the provider requires interactive re-authentication (redirect
|
|
153
|
+
* or popup), this method may never return. The app will reload after
|
|
154
|
+
* authentication completes and re-initialize with a fresh token.
|
|
155
|
+
*
|
|
156
|
+
* @returns Promise resolving to StandardAuthToken or throws on failure
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const token = await this.authBase.refreshToken();
|
|
161
|
+
* return token.idToken; // Always succeeds or throws
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
refreshToken(): Promise<StandardAuthToken>;
|
|
165
|
+
/**
|
|
166
|
+
* Classify an error into a standard error type
|
|
167
|
+
*
|
|
168
|
+
* This method converts provider-specific errors into semantic error types
|
|
169
|
+
* that application code can handle consistently. Eliminates the need for
|
|
170
|
+
* consumers to check provider-specific error names like 'BrowserAuthError'.
|
|
171
|
+
*
|
|
172
|
+
* @param error The error to classify (can be any type)
|
|
173
|
+
* @returns StandardAuthError with categorized error type
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* try {
|
|
178
|
+
* await this.authBase.login();
|
|
179
|
+
* } catch (err) {
|
|
180
|
+
* const authError = this.authBase.classifyError(err);
|
|
181
|
+
*
|
|
182
|
+
* switch (authError.type) {
|
|
183
|
+
* case AuthErrorType.TOKEN_EXPIRED:
|
|
184
|
+
* // Show "session expired" message
|
|
185
|
+
* break;
|
|
186
|
+
* case AuthErrorType.USER_CANCELLED:
|
|
187
|
+
* // User cancelled - don't show error
|
|
188
|
+
* break;
|
|
189
|
+
* default:
|
|
190
|
+
* // Show generic error
|
|
191
|
+
* alert(authError.userMessage);
|
|
192
|
+
* }
|
|
193
|
+
* }
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
classifyError(error: unknown): StandardAuthError;
|
|
46
197
|
/**
|
|
47
|
-
* Get
|
|
198
|
+
* Get list of required configuration fields for this provider
|
|
199
|
+
*
|
|
200
|
+
* @returns Array of required config field names
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```typescript
|
|
204
|
+
* // Auth0 requires: ['clientId', 'domain']
|
|
205
|
+
* // MSAL requires: ['clientId', 'tenantId']
|
|
206
|
+
* ```
|
|
48
207
|
*/
|
|
49
208
|
getRequiredConfig(): string[];
|
|
50
209
|
/**
|
|
51
210
|
* Validate provider configuration
|
|
211
|
+
*
|
|
212
|
+
* @param config Configuration object to validate
|
|
213
|
+
* @returns True if configuration is valid
|
|
52
214
|
*/
|
|
53
|
-
validateConfig(config:
|
|
215
|
+
validateConfig(config: Record<string, unknown>): boolean;
|
|
54
216
|
}
|
|
55
217
|
//# sourceMappingURL=IAuthProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IAuthProvider.d.ts","sourceRoot":"","sources":["../../src/lib/IAuthProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"IAuthProvider.d.ts","sourceRoot":"","sources":["../../src/lib/IAuthProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EAElB,MAAM,cAAc,CAAC;AAGtB,MAAM,WAAW,yBAA0B,SAAQ,kBAAkB;CAEpE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAMtB;;;;;OAKG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;;;;;;;OAUG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3E;;;;;;;;;OASG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAExB;;;;;OAKG;IACH,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAMhC;;;;;;;;;;;;OAYG;IACH,eAAe,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;IAEvC;;;;;;;;;;;;;;OAcG;IACH,WAAW,IAAI,UAAU,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAEnD;;;;;;;;;OASG;IACH,YAAY,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAMnC;;;;;;;;;;;;;;;;;OAiBG;IACH,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAErC;;;;;;;;;;;;;;;OAeG;IACH,YAAY,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAElD;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,YAAY,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAM3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAAC;IAMjD;;;;;;;;;;OAUG;IACH,iBAAiB,IAAI,MAAM,EAAE,CAAC;IAE9B;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;CAC1D"}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standardized authentication types for v3.0.0
|
|
3
|
+
*
|
|
4
|
+
* These types ensure consistent interfaces across all auth providers,
|
|
5
|
+
* eliminating leaky abstractions where consumers needed to know about
|
|
6
|
+
* provider-specific token storage (__raw vs idToken) or claim structures.
|
|
7
|
+
*
|
|
8
|
+
* @module @memberjunction/ng-auth-services
|
|
9
|
+
* @version 3.0.0
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Standardized user information returned by all auth providers
|
|
13
|
+
*
|
|
14
|
+
* Maps provider-specific claims to a consistent structure.
|
|
15
|
+
* Each provider implements extractUserInfoInternal() to convert their
|
|
16
|
+
* claim format to this standard structure.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const userInfo = await firstValueFrom(this.authBase.getUserInfo());
|
|
21
|
+
* console.log(`Welcome ${userInfo.name}!`);
|
|
22
|
+
* console.log(`Email: ${userInfo.email}`);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export interface StandardUserInfo {
|
|
26
|
+
/**
|
|
27
|
+
* Unique user identifier from the auth provider
|
|
28
|
+
* (e.g., Auth0: user.sub, MSAL: account.localAccountId)
|
|
29
|
+
*/
|
|
30
|
+
id: string;
|
|
31
|
+
/**
|
|
32
|
+
* User's email address
|
|
33
|
+
*/
|
|
34
|
+
email: string;
|
|
35
|
+
/**
|
|
36
|
+
* User's full display name
|
|
37
|
+
*/
|
|
38
|
+
name: string;
|
|
39
|
+
/**
|
|
40
|
+
* User's given name / first name
|
|
41
|
+
*/
|
|
42
|
+
givenName?: string;
|
|
43
|
+
/**
|
|
44
|
+
* User's family name / last name
|
|
45
|
+
*/
|
|
46
|
+
familyName?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Preferred username or handle
|
|
49
|
+
* Often the same as email for most providers
|
|
50
|
+
*/
|
|
51
|
+
preferredUsername?: string;
|
|
52
|
+
/**
|
|
53
|
+
* URL to user's profile picture (if available)
|
|
54
|
+
*/
|
|
55
|
+
pictureUrl?: string;
|
|
56
|
+
/**
|
|
57
|
+
* User's locale/language preference
|
|
58
|
+
* (e.g., "en-US", "fr-FR")
|
|
59
|
+
*/
|
|
60
|
+
locale?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Email verification status
|
|
63
|
+
* True if the auth provider has verified the user's email
|
|
64
|
+
*/
|
|
65
|
+
emailVerified?: boolean;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Standardized token information returned by all auth providers
|
|
69
|
+
*
|
|
70
|
+
* Provides access to tokens without exposing provider-specific claim structures.
|
|
71
|
+
* Each provider implements extractTokenInfoInternal() to extract tokens from
|
|
72
|
+
* their specific storage format.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const tokenInfo = await this.authBase.getTokenInfo();
|
|
77
|
+
* console.log(`Token expires at: ${new Date(tokenInfo.expiresAt)}`);
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export interface StandardAuthToken {
|
|
81
|
+
/**
|
|
82
|
+
* The ID token as a JWT string
|
|
83
|
+
*
|
|
84
|
+
* This is what should be sent to the backend GraphQL API in the
|
|
85
|
+
* Authorization header as "Bearer {idToken}"
|
|
86
|
+
*/
|
|
87
|
+
idToken: string;
|
|
88
|
+
/**
|
|
89
|
+
* Access token for calling APIs (if different from ID token)
|
|
90
|
+
*
|
|
91
|
+
* Some providers (like Auth0) use the same token for both authentication
|
|
92
|
+
* and API access. Others (like MSAL) provide separate tokens.
|
|
93
|
+
*/
|
|
94
|
+
accessToken?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Token expiration timestamp (milliseconds since epoch)
|
|
97
|
+
*
|
|
98
|
+
* Use this to determine if the token needs to be refreshed.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const isExpired = Date.now() >= tokenInfo.expiresAt;
|
|
103
|
+
* if (isExpired) {
|
|
104
|
+
* await this.authBase.refreshToken();
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
expiresAt: number;
|
|
109
|
+
/**
|
|
110
|
+
* OAuth scopes granted with this token
|
|
111
|
+
*
|
|
112
|
+
* @example ["openid", "profile", "email", "User.Read"]
|
|
113
|
+
*/
|
|
114
|
+
scopes?: string[];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Standardized authentication error types
|
|
118
|
+
*
|
|
119
|
+
* Abstracts provider-specific error names (like "BrowserAuthError",
|
|
120
|
+
* "InteractionRequiredAuthError") into semantic categories that
|
|
121
|
+
* application code can handle consistently.
|
|
122
|
+
*
|
|
123
|
+
* This eliminates the need for consumers to check provider-specific
|
|
124
|
+
* error properties like `err.name === 'BrowserAuthError'`.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* try {
|
|
129
|
+
* await this.authBase.login();
|
|
130
|
+
* } catch (err) {
|
|
131
|
+
* const authError = this.authBase.classifyError(err);
|
|
132
|
+
*
|
|
133
|
+
* switch (authError.type) {
|
|
134
|
+
* case AuthErrorType.TOKEN_EXPIRED:
|
|
135
|
+
* this.showMessage('Session expired. Please log in again.');
|
|
136
|
+
* break;
|
|
137
|
+
* case AuthErrorType.USER_CANCELLED:
|
|
138
|
+
* // User cancelled - don't show error
|
|
139
|
+
* break;
|
|
140
|
+
* default:
|
|
141
|
+
* this.showError(authError.userMessage);
|
|
142
|
+
* }
|
|
143
|
+
* }
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export declare enum AuthErrorType {
|
|
147
|
+
/**
|
|
148
|
+
* Token has expired - user needs to refresh or re-authenticate
|
|
149
|
+
*
|
|
150
|
+
* Mapped from:
|
|
151
|
+
* - Auth0: "jwt expired", "token expired"
|
|
152
|
+
* - MSAL: InteractionRequiredAuthError (when token expired)
|
|
153
|
+
* - Okta: "token_expired"
|
|
154
|
+
*/
|
|
155
|
+
TOKEN_EXPIRED = "TOKEN_EXPIRED",
|
|
156
|
+
/**
|
|
157
|
+
* No active user session found - user needs to log in
|
|
158
|
+
*
|
|
159
|
+
* Mapped from:
|
|
160
|
+
* - Auth0: "login_required", "no active session"
|
|
161
|
+
* - MSAL: BrowserAuthError (no accounts)
|
|
162
|
+
* - Okta: "login_required"
|
|
163
|
+
*/
|
|
164
|
+
NO_ACTIVE_SESSION = "NO_ACTIVE_SESSION",
|
|
165
|
+
/**
|
|
166
|
+
* User interaction required (e.g., consent, MFA)
|
|
167
|
+
*
|
|
168
|
+
* Mapped from:
|
|
169
|
+
* - Auth0: "consent_required", "interaction_required"
|
|
170
|
+
* - MSAL: InteractionRequiredAuthError
|
|
171
|
+
* - Okta: "consent_required"
|
|
172
|
+
*/
|
|
173
|
+
INTERACTION_REQUIRED = "INTERACTION_REQUIRED",
|
|
174
|
+
/**
|
|
175
|
+
* User cancelled the authentication flow
|
|
176
|
+
*
|
|
177
|
+
* Typically doesn't require showing an error message to the user,
|
|
178
|
+
* as the cancellation was intentional.
|
|
179
|
+
*/
|
|
180
|
+
USER_CANCELLED = "USER_CANCELLED",
|
|
181
|
+
/**
|
|
182
|
+
* Network error communicating with auth provider
|
|
183
|
+
*
|
|
184
|
+
* Could be DNS failure, timeout, or other connectivity issues.
|
|
185
|
+
*/
|
|
186
|
+
NETWORK_ERROR = "NETWORK_ERROR",
|
|
187
|
+
/**
|
|
188
|
+
* Invalid configuration or setup error
|
|
189
|
+
*
|
|
190
|
+
* Usually indicates a problem with the auth provider configuration
|
|
191
|
+
* (wrong client ID, invalid redirect URI, etc.)
|
|
192
|
+
*/
|
|
193
|
+
CONFIGURATION_ERROR = "CONFIGURATION_ERROR",
|
|
194
|
+
/**
|
|
195
|
+
* Generic/unknown error
|
|
196
|
+
*
|
|
197
|
+
* Used when the error doesn't fit into any other category.
|
|
198
|
+
* The error message and originalError should provide more details.
|
|
199
|
+
*/
|
|
200
|
+
UNKNOWN_ERROR = "UNKNOWN_ERROR"
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Standardized auth error with categorization
|
|
204
|
+
*
|
|
205
|
+
* Provides both machine-readable error types and human-readable messages.
|
|
206
|
+
* Each provider implements classifyErrorInternal() to map their specific
|
|
207
|
+
* errors to this standard format.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* const authError = this.authBase.classifyError(err);
|
|
212
|
+
*
|
|
213
|
+
* // Log for debugging
|
|
214
|
+
* console.error(`Auth error (${authError.type}):`, authError.message);
|
|
215
|
+
*
|
|
216
|
+
* // Show to user
|
|
217
|
+
* this.showErrorMessage(authError.userMessage || authError.message);
|
|
218
|
+
*
|
|
219
|
+
* // Access original error for detailed debugging
|
|
220
|
+
* if (environment.debug) {
|
|
221
|
+
* console.error('Original error:', authError.originalError);
|
|
222
|
+
* }
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
export interface StandardAuthError {
|
|
226
|
+
/**
|
|
227
|
+
* Semantic error type for programmatic handling
|
|
228
|
+
*
|
|
229
|
+
* Use this in switch statements or if conditions to handle
|
|
230
|
+
* different error scenarios appropriately.
|
|
231
|
+
*/
|
|
232
|
+
type: AuthErrorType;
|
|
233
|
+
/**
|
|
234
|
+
* Technical error message
|
|
235
|
+
*
|
|
236
|
+
* Suitable for logging and debugging. May contain technical details
|
|
237
|
+
* not appropriate for end users.
|
|
238
|
+
*/
|
|
239
|
+
message: string;
|
|
240
|
+
/**
|
|
241
|
+
* Original error from the provider (for debugging)
|
|
242
|
+
*
|
|
243
|
+
* Preserved for detailed error analysis and debugging.
|
|
244
|
+
* Can be any type (Error, object, string, etc.)
|
|
245
|
+
*/
|
|
246
|
+
originalError?: unknown;
|
|
247
|
+
/**
|
|
248
|
+
* User-friendly error message
|
|
249
|
+
*
|
|
250
|
+
* A message suitable for displaying to end users.
|
|
251
|
+
* Explains the error in plain language and may suggest next steps.
|
|
252
|
+
*
|
|
253
|
+
* @example "Your session has expired. Please log in again."
|
|
254
|
+
*/
|
|
255
|
+
userMessage?: string;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Token refresh result
|
|
259
|
+
*
|
|
260
|
+
* Returned by refreshToken() to indicate success or failure.
|
|
261
|
+
* Consumers should check the success property before accessing the token.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* const result = await this.authBase.refreshToken();
|
|
266
|
+
*
|
|
267
|
+
* if (result.success && result.token) {
|
|
268
|
+
* // Use the refreshed token
|
|
269
|
+
* const newIdToken = result.token.idToken;
|
|
270
|
+
* await this.updateGraphQLClient(newIdToken);
|
|
271
|
+
* } else {
|
|
272
|
+
* // Handle refresh failure
|
|
273
|
+
* console.error('Token refresh failed:', result.error?.message);
|
|
274
|
+
*
|
|
275
|
+
* if (result.error?.type === AuthErrorType.TOKEN_EXPIRED) {
|
|
276
|
+
* // Token is expired and can't be refreshed - need re-login
|
|
277
|
+
* await this.authBase.login();
|
|
278
|
+
* }
|
|
279
|
+
* }
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
export interface TokenRefreshResult {
|
|
283
|
+
/**
|
|
284
|
+
* Whether the refresh was successful
|
|
285
|
+
*
|
|
286
|
+
* If true, the token property will contain the new token.
|
|
287
|
+
* If false, the error property will explain why.
|
|
288
|
+
*/
|
|
289
|
+
success: boolean;
|
|
290
|
+
/**
|
|
291
|
+
* New token if refresh succeeded
|
|
292
|
+
*
|
|
293
|
+
* Only present when success is true.
|
|
294
|
+
*/
|
|
295
|
+
token?: StandardAuthToken;
|
|
296
|
+
/**
|
|
297
|
+
* Error if refresh failed
|
|
298
|
+
*
|
|
299
|
+
* Only present when success is false.
|
|
300
|
+
* Contains details about why the refresh failed.
|
|
301
|
+
*/
|
|
302
|
+
error?: StandardAuthError;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Authentication state snapshot
|
|
306
|
+
*
|
|
307
|
+
* Represents the current authentication state of the application.
|
|
308
|
+
* This is useful for components that need to react to auth state changes.
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* ```typescript
|
|
312
|
+
* // Subscribe to complete auth state
|
|
313
|
+
* this.authState$ = this.authBase.getAuthState();
|
|
314
|
+
*
|
|
315
|
+
* this.authState$.subscribe(state => {
|
|
316
|
+
* if (state.isLoading) {
|
|
317
|
+
* this.showLoadingSpinner();
|
|
318
|
+
* } else if (state.isAuthenticated && state.user) {
|
|
319
|
+
* this.showWelcomeMessage(state.user.name);
|
|
320
|
+
* } else if (state.error) {
|
|
321
|
+
* this.showError(state.error.userMessage);
|
|
322
|
+
* }
|
|
323
|
+
* });
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
326
|
+
export interface AuthState {
|
|
327
|
+
/**
|
|
328
|
+
* Whether user is currently authenticated
|
|
329
|
+
*/
|
|
330
|
+
isAuthenticated: boolean;
|
|
331
|
+
/**
|
|
332
|
+
* Current user info (if authenticated)
|
|
333
|
+
*
|
|
334
|
+
* Undefined if not authenticated or still loading.
|
|
335
|
+
*/
|
|
336
|
+
user?: StandardUserInfo;
|
|
337
|
+
/**
|
|
338
|
+
* Whether auth state is still being determined
|
|
339
|
+
*
|
|
340
|
+
* True during initial authentication check or token refresh.
|
|
341
|
+
* Useful for showing loading spinners.
|
|
342
|
+
*/
|
|
343
|
+
isLoading: boolean;
|
|
344
|
+
/**
|
|
345
|
+
* Current error (if any)
|
|
346
|
+
*
|
|
347
|
+
* Present if there was an error during authentication or token refresh.
|
|
348
|
+
*/
|
|
349
|
+
error?: StandardAuthError;
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=auth-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-types.d.ts","sourceRoot":"","sources":["../../src/lib/auth-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;;;;;;OAYG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,oBAAY,aAAa;IACvB;;;;;;;OAOG;IACH,aAAa,kBAAkB;IAE/B;;;;;;;OAOG;IACH,iBAAiB,sBAAsB;IAEvC;;;;;;;OAOG;IACH,oBAAoB,yBAAyB;IAE7C;;;;;OAKG;IACH,cAAc,mBAAmB;IAEjC;;;;OAIG;IACH,aAAa,kBAAkB;IAE/B;;;;;OAKG;IACH,mBAAmB,wBAAwB;IAE3C;;;;;OAKG;IACH,aAAa,kBAAkB;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAE1B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,eAAe,EAAE,OAAO,CAAC;IAEzB;;;;OAIG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC;IAExB;;;;;OAKG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standardized authentication types for v3.0.0
|
|
3
|
+
*
|
|
4
|
+
* These types ensure consistent interfaces across all auth providers,
|
|
5
|
+
* eliminating leaky abstractions where consumers needed to know about
|
|
6
|
+
* provider-specific token storage (__raw vs idToken) or claim structures.
|
|
7
|
+
*
|
|
8
|
+
* @module @memberjunction/ng-auth-services
|
|
9
|
+
* @version 3.0.0
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Standardized authentication error types
|
|
13
|
+
*
|
|
14
|
+
* Abstracts provider-specific error names (like "BrowserAuthError",
|
|
15
|
+
* "InteractionRequiredAuthError") into semantic categories that
|
|
16
|
+
* application code can handle consistently.
|
|
17
|
+
*
|
|
18
|
+
* This eliminates the need for consumers to check provider-specific
|
|
19
|
+
* error properties like `err.name === 'BrowserAuthError'`.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* try {
|
|
24
|
+
* await this.authBase.login();
|
|
25
|
+
* } catch (err) {
|
|
26
|
+
* const authError = this.authBase.classifyError(err);
|
|
27
|
+
*
|
|
28
|
+
* switch (authError.type) {
|
|
29
|
+
* case AuthErrorType.TOKEN_EXPIRED:
|
|
30
|
+
* this.showMessage('Session expired. Please log in again.');
|
|
31
|
+
* break;
|
|
32
|
+
* case AuthErrorType.USER_CANCELLED:
|
|
33
|
+
* // User cancelled - don't show error
|
|
34
|
+
* break;
|
|
35
|
+
* default:
|
|
36
|
+
* this.showError(authError.userMessage);
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export var AuthErrorType;
|
|
42
|
+
(function (AuthErrorType) {
|
|
43
|
+
/**
|
|
44
|
+
* Token has expired - user needs to refresh or re-authenticate
|
|
45
|
+
*
|
|
46
|
+
* Mapped from:
|
|
47
|
+
* - Auth0: "jwt expired", "token expired"
|
|
48
|
+
* - MSAL: InteractionRequiredAuthError (when token expired)
|
|
49
|
+
* - Okta: "token_expired"
|
|
50
|
+
*/
|
|
51
|
+
AuthErrorType["TOKEN_EXPIRED"] = "TOKEN_EXPIRED";
|
|
52
|
+
/**
|
|
53
|
+
* No active user session found - user needs to log in
|
|
54
|
+
*
|
|
55
|
+
* Mapped from:
|
|
56
|
+
* - Auth0: "login_required", "no active session"
|
|
57
|
+
* - MSAL: BrowserAuthError (no accounts)
|
|
58
|
+
* - Okta: "login_required"
|
|
59
|
+
*/
|
|
60
|
+
AuthErrorType["NO_ACTIVE_SESSION"] = "NO_ACTIVE_SESSION";
|
|
61
|
+
/**
|
|
62
|
+
* User interaction required (e.g., consent, MFA)
|
|
63
|
+
*
|
|
64
|
+
* Mapped from:
|
|
65
|
+
* - Auth0: "consent_required", "interaction_required"
|
|
66
|
+
* - MSAL: InteractionRequiredAuthError
|
|
67
|
+
* - Okta: "consent_required"
|
|
68
|
+
*/
|
|
69
|
+
AuthErrorType["INTERACTION_REQUIRED"] = "INTERACTION_REQUIRED";
|
|
70
|
+
/**
|
|
71
|
+
* User cancelled the authentication flow
|
|
72
|
+
*
|
|
73
|
+
* Typically doesn't require showing an error message to the user,
|
|
74
|
+
* as the cancellation was intentional.
|
|
75
|
+
*/
|
|
76
|
+
AuthErrorType["USER_CANCELLED"] = "USER_CANCELLED";
|
|
77
|
+
/**
|
|
78
|
+
* Network error communicating with auth provider
|
|
79
|
+
*
|
|
80
|
+
* Could be DNS failure, timeout, or other connectivity issues.
|
|
81
|
+
*/
|
|
82
|
+
AuthErrorType["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
83
|
+
/**
|
|
84
|
+
* Invalid configuration or setup error
|
|
85
|
+
*
|
|
86
|
+
* Usually indicates a problem with the auth provider configuration
|
|
87
|
+
* (wrong client ID, invalid redirect URI, etc.)
|
|
88
|
+
*/
|
|
89
|
+
AuthErrorType["CONFIGURATION_ERROR"] = "CONFIGURATION_ERROR";
|
|
90
|
+
/**
|
|
91
|
+
* Generic/unknown error
|
|
92
|
+
*
|
|
93
|
+
* Used when the error doesn't fit into any other category.
|
|
94
|
+
* The error message and originalError should provide more details.
|
|
95
|
+
*/
|
|
96
|
+
AuthErrorType["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
|
|
97
|
+
})(AuthErrorType || (AuthErrorType = {}));
|
|
98
|
+
//# sourceMappingURL=auth-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-types.js","sourceRoot":"","sources":["../../src/lib/auth-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAwHH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAN,IAAY,aA6DX;AA7DD,WAAY,aAAa;IACvB;;;;;;;OAOG;IACH,gDAA+B,CAAA;IAE/B;;;;;;;OAOG;IACH,wDAAuC,CAAA;IAEvC;;;;;;;OAOG;IACH,8DAA6C,CAAA;IAE7C;;;;;OAKG;IACH,kDAAiC,CAAA;IAEjC;;;;OAIG;IACH,gDAA+B,CAAA;IAE/B;;;;;OAKG;IACH,4DAA2C,CAAA;IAE3C;;;;;OAKG;IACH,gDAA+B,CAAA;AACjC,CAAC,EA7DW,aAAa,KAAb,aAAa,QA6DxB"}
|