@civic/auth 0.6.1-beta.4 → 0.7.0-beta.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/CHANGELOG.md +7 -0
- package/dist/nextjs/config.d.ts.map +1 -1
- package/dist/nextjs/config.js +3 -1
- package/dist/nextjs/config.js.map +1 -1
- package/dist/nextjs/hooks/useUserCookie.d.ts.map +1 -1
- package/dist/nextjs/hooks/useUserCookie.js.map +1 -1
- package/dist/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
- package/dist/nextjs/providers/NextAuthProvider.js +1 -0
- package/dist/nextjs/providers/NextAuthProvider.js.map +1 -1
- package/dist/shared/hooks/useSignIn.d.ts +9 -4
- package/dist/shared/hooks/useSignIn.d.ts.map +1 -1
- package/dist/shared/hooks/useSignIn.js +75 -42
- package/dist/shared/hooks/useSignIn.js.map +1 -1
- package/dist/shared/providers/AuthContext.d.ts +7 -2
- package/dist/shared/providers/AuthContext.d.ts.map +1 -1
- package/dist/shared/providers/AuthContext.js.map +1 -1
- package/dist/shared/providers/UserProvider.d.ts +5 -1
- package/dist/shared/providers/UserProvider.d.ts.map +1 -1
- package/dist/shared/providers/UserProvider.js.map +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.js +1 -1
- package/dist/shared/version.js.map +1 -1
- package/dist/vanillajs/auth/AuthenticationEvents.d.ts.map +1 -1
- package/dist/vanillajs/auth/AuthenticationEvents.js +2 -2
- package/dist/vanillajs/auth/AuthenticationEvents.js.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.d.ts +69 -107
- package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.js +415 -440
- package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
- package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
- package/dist/vanillajs/auth/SessionManager.js +2 -2
- package/dist/vanillajs/auth/SessionManager.js.map +1 -1
- package/dist/vanillajs/auth/TokenRefresher.d.ts.map +1 -1
- package/dist/vanillajs/auth/TokenRefresher.js +2 -2
- package/dist/vanillajs/auth/TokenRefresher.js.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.d.ts +6 -0
- package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -0
- package/dist/vanillajs/auth/config/ConfigProcessor.js +68 -0
- package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -0
- package/dist/vanillajs/auth/handlers/IframeAuthHandler.d.ts +40 -0
- package/dist/vanillajs/auth/handlers/IframeAuthHandler.d.ts.map +1 -0
- package/dist/vanillajs/auth/handlers/IframeAuthHandler.js +388 -0
- package/dist/vanillajs/auth/handlers/IframeAuthHandler.js.map +1 -0
- package/dist/vanillajs/auth/handlers/MessageHandler.d.ts +170 -0
- package/dist/vanillajs/auth/handlers/MessageHandler.d.ts.map +1 -0
- package/dist/vanillajs/auth/handlers/MessageHandler.js +367 -0
- package/dist/vanillajs/auth/handlers/MessageHandler.js.map +1 -0
- package/dist/vanillajs/auth/{OAuthCallbackHandler.d.ts → handlers/OAuthCallbackHandler.d.ts} +18 -27
- package/dist/vanillajs/auth/handlers/OAuthCallbackHandler.d.ts.map +1 -0
- package/dist/vanillajs/auth/handlers/OAuthCallbackHandler.js +292 -0
- package/dist/vanillajs/auth/handlers/OAuthCallbackHandler.js.map +1 -0
- package/dist/vanillajs/auth/handlers/PopupHandler.d.ts +108 -0
- package/dist/vanillajs/auth/handlers/PopupHandler.d.ts.map +1 -0
- package/dist/vanillajs/auth/handlers/PopupHandler.js +333 -0
- package/dist/vanillajs/auth/handlers/PopupHandler.js.map +1 -0
- package/dist/vanillajs/auth/types/AuthTypes.d.ts +135 -0
- package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -0
- package/dist/vanillajs/auth/types/AuthTypes.js +40 -0
- package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -0
- package/dist/vanillajs/iframe/IframeManager.d.ts +33 -0
- package/dist/vanillajs/iframe/IframeManager.d.ts.map +1 -1
- package/dist/vanillajs/iframe/IframeManager.js +163 -36
- package/dist/vanillajs/iframe/IframeManager.js.map +1 -1
- package/dist/vanillajs/index.d.ts +2 -2
- package/dist/vanillajs/index.d.ts.map +1 -1
- package/dist/vanillajs/index.js +2 -2
- package/dist/vanillajs/index.js.map +1 -1
- package/dist/vanillajs/services/ApiService.d.ts.map +1 -1
- package/dist/vanillajs/services/ApiService.js +2 -2
- package/dist/vanillajs/services/ApiService.js.map +1 -1
- package/dist/vanillajs/types/index.d.ts +15 -10
- package/dist/vanillajs/types/index.d.ts.map +1 -1
- package/dist/vanillajs/types/index.js +15 -10
- package/dist/vanillajs/types/index.js.map +1 -1
- package/dist/vanillajs/utils/auth-utils.d.ts +2 -1
- package/dist/vanillajs/utils/auth-utils.d.ts.map +1 -1
- package/dist/vanillajs/utils/auth-utils.js +6 -3
- package/dist/vanillajs/utils/auth-utils.js.map +1 -1
- package/dist/vanillajs/utils/logger.d.ts +16 -15
- package/dist/vanillajs/utils/logger.d.ts.map +1 -1
- package/dist/vanillajs/utils/logger.js +35 -19
- package/dist/vanillajs/utils/logger.js.map +1 -1
- package/package.json +6 -1
- package/dist/vanillajs/auth/OAuthCallbackHandler.d.ts.map +0 -1
- package/dist/vanillajs/auth/OAuthCallbackHandler.js +0 -143
- package/dist/vanillajs/auth/OAuthCallbackHandler.js.map +0 -1
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { AuthEvent } from "../../types/index.js";
|
|
2
|
+
import { CivicAuthError, CivicAuthErrorCode } from "../types/AuthTypes.js";
|
|
3
|
+
import { createLogger as createLoggerFn } from "../../utils/logger.js";
|
|
4
|
+
/**
|
|
5
|
+
* MessageHandler - Handles postMessage communication and authentication flow logic
|
|
6
|
+
* Processes messages from iframe, validates origins, and manages auth state transitions
|
|
7
|
+
*/
|
|
8
|
+
export class MessageHandler {
|
|
9
|
+
config;
|
|
10
|
+
logger = createLoggerFn("message-handler");
|
|
11
|
+
iframeElement;
|
|
12
|
+
onAuthSuccess;
|
|
13
|
+
onAuthError;
|
|
14
|
+
onPopupFailure;
|
|
15
|
+
cleanup;
|
|
16
|
+
constructor(handlerConfig) {
|
|
17
|
+
this.config = handlerConfig.config;
|
|
18
|
+
this.iframeElement = handlerConfig.iframeElement;
|
|
19
|
+
this.onAuthSuccess = handlerConfig.onAuthSuccess;
|
|
20
|
+
this.onAuthError = handlerConfig.onAuthError;
|
|
21
|
+
this.onPopupFailure = handlerConfig.onPopupFailure;
|
|
22
|
+
this.cleanup = handlerConfig.cleanup;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Updates the iframe element reference used for message validation.
|
|
26
|
+
*
|
|
27
|
+
* This method allows updating the iframe element after the MessageHandler
|
|
28
|
+
* has been instantiated, which is useful when the iframe is created
|
|
29
|
+
* dynamically after the handler setup.
|
|
30
|
+
*
|
|
31
|
+
* @param iframeElement - The new iframe element to associate with this handler
|
|
32
|
+
*/
|
|
33
|
+
updateIframeElement(iframeElement) {
|
|
34
|
+
this.iframeElement = iframeElement;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Main message handler for processing postMessage events.
|
|
38
|
+
*
|
|
39
|
+
* Validates message origin and source, then routes valid messages to
|
|
40
|
+
* appropriate handlers. This is the entry point for all iframe communication.
|
|
41
|
+
*
|
|
42
|
+
* @param event - The MessageEvent received from the iframe or other sources
|
|
43
|
+
*/
|
|
44
|
+
handleMessage = (event) => {
|
|
45
|
+
const expectedOrigin = new URL(this.config.oauthServerBaseUrl).origin;
|
|
46
|
+
this.logIncomingMessage(event, expectedOrigin);
|
|
47
|
+
if (!this.isValidMessageSource(event, expectedOrigin)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.handleValidMessage(event);
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Logs incoming message details for debugging purposes.
|
|
54
|
+
*
|
|
55
|
+
* Provides comprehensive logging of message properties including origin,
|
|
56
|
+
* source validation, and iframe state for troubleshooting communication issues.
|
|
57
|
+
*
|
|
58
|
+
* @param event - The MessageEvent to log
|
|
59
|
+
* @param expectedOrigin - The expected origin for comparison
|
|
60
|
+
*/
|
|
61
|
+
logIncomingMessage(event, expectedOrigin) {
|
|
62
|
+
this.logger.debug("Global window received message:", {
|
|
63
|
+
data: event.data,
|
|
64
|
+
origin: event.origin,
|
|
65
|
+
sourceProvided: !!event.source,
|
|
66
|
+
iframeContentWindow: this.iframeElement?.contentWindow,
|
|
67
|
+
expectedIframeOrigin: expectedOrigin,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Validates that a message comes from the expected origin and source.
|
|
72
|
+
*
|
|
73
|
+
* Performs security checks to ensure messages are only processed from
|
|
74
|
+
* the configured OAuth server origin and the designated iframe element.
|
|
75
|
+
*
|
|
76
|
+
* @param event - The MessageEvent to validate
|
|
77
|
+
* @param expectedOrigin - The expected origin URL for the message
|
|
78
|
+
* @returns True if the message source and origin are valid, false otherwise
|
|
79
|
+
*/
|
|
80
|
+
isValidMessageSource(event, expectedOrigin) {
|
|
81
|
+
const isValidOrigin = event.origin === expectedOrigin;
|
|
82
|
+
const isValidSource = event.source === this.iframeElement?.contentWindow;
|
|
83
|
+
if (!isValidOrigin) {
|
|
84
|
+
this.logger.warn("Ignored message from unexpected origin.", {
|
|
85
|
+
receivedOrigin: event.origin,
|
|
86
|
+
expectedOrigin,
|
|
87
|
+
iframeSrc: this.iframeElement?.src,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (!isValidSource) {
|
|
91
|
+
this.logger.warn("Ignored message from unexpected source.", {
|
|
92
|
+
isSourceProvided: !!event.source,
|
|
93
|
+
isIframeContentWindowAvailable: !!this.iframeElement?.contentWindow,
|
|
94
|
+
iframeSrc: this.iframeElement?.src,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return isValidOrigin && isValidSource;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Processes messages that have passed origin and source validation.
|
|
101
|
+
*
|
|
102
|
+
* Routes validated messages to specific handlers based on message type,
|
|
103
|
+
* including civicloginApp messages, iframe resizer messages, and standard auth messages.
|
|
104
|
+
*
|
|
105
|
+
* @param event - The validated MessageEvent to process
|
|
106
|
+
*/
|
|
107
|
+
handleValidMessage(event) {
|
|
108
|
+
this.logger.info("Message from configured iframe source and origin received", {
|
|
109
|
+
data: event.data,
|
|
110
|
+
iframeSrc: this.iframeElement?.src,
|
|
111
|
+
});
|
|
112
|
+
const message = event.data;
|
|
113
|
+
this.logger.debug("Processing iframe message", {
|
|
114
|
+
messageType: typeof message,
|
|
115
|
+
hasType: message && typeof message === "object" && "type" in message,
|
|
116
|
+
hasSource: message && typeof message === "object" && "source" in message,
|
|
117
|
+
messageKeys: message && typeof message === "object" ? Object.keys(message) : [],
|
|
118
|
+
rawData: message,
|
|
119
|
+
});
|
|
120
|
+
// Handle civicloginApp messages
|
|
121
|
+
if (this.isCivicLoginAppMessage(message)) {
|
|
122
|
+
this.handleCivicLoginAppMessage(message);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// Handle iframe resizer messages
|
|
126
|
+
if (this.isIframeResizerMessage(message)) {
|
|
127
|
+
this.handleIframeResizerMessage(message);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
// Handle standard auth messages
|
|
131
|
+
this.handleStandardAuthMessage(message);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Type guard to identify civicloginApp messages.
|
|
135
|
+
*
|
|
136
|
+
* Checks if a message object has the structure and source property
|
|
137
|
+
* that identifies it as coming from the civicloginApp.
|
|
138
|
+
*
|
|
139
|
+
* @param message - The message object to check
|
|
140
|
+
* @returns True if the message is a LoginAppMessage, false otherwise
|
|
141
|
+
*/
|
|
142
|
+
isCivicLoginAppMessage(message) {
|
|
143
|
+
return (message !== null &&
|
|
144
|
+
typeof message === "object" &&
|
|
145
|
+
"source" in message &&
|
|
146
|
+
message.source === "civicloginApp");
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Handles messages originating from the civicloginApp.
|
|
150
|
+
*
|
|
151
|
+
* Processes various civicloginApp message types including authentication errors,
|
|
152
|
+
* popup failures, design updates, and other app-specific communications.
|
|
153
|
+
* Validates client ID matches before processing.
|
|
154
|
+
*
|
|
155
|
+
* @param message - The validated civicloginApp message to process
|
|
156
|
+
*/
|
|
157
|
+
handleCivicLoginAppMessage(message) {
|
|
158
|
+
this.logger.info("Received civicloginApp message", {
|
|
159
|
+
type: message.type,
|
|
160
|
+
clientId: message.clientId,
|
|
161
|
+
data: message.data,
|
|
162
|
+
});
|
|
163
|
+
// Validate clientId matches our config
|
|
164
|
+
if (message.clientId !== this.config.clientId) {
|
|
165
|
+
this.logger.warn("civicloginApp message clientId mismatch", {
|
|
166
|
+
received: message.clientId,
|
|
167
|
+
expected: this.config.clientId,
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
switch (message.type) {
|
|
172
|
+
case "auth_error":
|
|
173
|
+
case "auth_error_try_again":
|
|
174
|
+
this.handleCivicLoginAppError(message);
|
|
175
|
+
break;
|
|
176
|
+
case "generatePopupFailed":
|
|
177
|
+
this.handlePopupFailure(message);
|
|
178
|
+
break;
|
|
179
|
+
case "design":
|
|
180
|
+
this.logger.debug("civicloginApp design message", {
|
|
181
|
+
data: message.data,
|
|
182
|
+
});
|
|
183
|
+
break;
|
|
184
|
+
default:
|
|
185
|
+
this.handleUnknownCivicLoginAppMessage(message);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Handles authentication error messages from civicloginApp.
|
|
191
|
+
*
|
|
192
|
+
* Processes auth_error and auth_error_try_again messages, creates
|
|
193
|
+
* appropriate error objects, emits error events, and triggers cleanup.
|
|
194
|
+
*
|
|
195
|
+
* @param message - The civicloginApp error message to process
|
|
196
|
+
*/
|
|
197
|
+
handleCivicLoginAppError(message) {
|
|
198
|
+
this.logger.error("civicloginApp authentication error", {
|
|
199
|
+
type: message.type,
|
|
200
|
+
data: message.data,
|
|
201
|
+
});
|
|
202
|
+
const error = new CivicAuthError(`Login app error: ${message.type}`, CivicAuthErrorCode.INVALID_MESSAGE);
|
|
203
|
+
this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {
|
|
204
|
+
detail: error.message,
|
|
205
|
+
error: message.data,
|
|
206
|
+
});
|
|
207
|
+
this.onAuthError(error);
|
|
208
|
+
this.cleanup();
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Handles popup generation failure messages from civicloginApp.
|
|
212
|
+
*
|
|
213
|
+
* Processes generatePopupFailed messages, extracts the failed URL,
|
|
214
|
+
* emits appropriate events, and triggers the popup failure callback
|
|
215
|
+
* to enable fallback authentication methods.
|
|
216
|
+
*
|
|
217
|
+
* @param message - The civicloginApp popup failure message to process
|
|
218
|
+
*/
|
|
219
|
+
handlePopupFailure(message) {
|
|
220
|
+
this.logger.warn("civicloginApp popup generation failed", {
|
|
221
|
+
data: message.data,
|
|
222
|
+
});
|
|
223
|
+
const failedUrl = message.data
|
|
224
|
+
?.url;
|
|
225
|
+
if (failedUrl) {
|
|
226
|
+
this.logger.info("Popup failed for URL, considering fallback options", {
|
|
227
|
+
failedUrl,
|
|
228
|
+
displayMode: this.config.displayMode,
|
|
229
|
+
});
|
|
230
|
+
this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {
|
|
231
|
+
detail: "Popup blocked by browser - switching to redirect mode",
|
|
232
|
+
error: {
|
|
233
|
+
type: "popup_blocked",
|
|
234
|
+
failedUrl,
|
|
235
|
+
suggestion: "The browser blocked a popup window. Redirecting to complete authentication in a new page.",
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
this.onPopupFailure(failedUrl);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Handles unknown or unrecognized civicloginApp message types.
|
|
243
|
+
*
|
|
244
|
+
* Provides fallback handling for unexpected message types, with special
|
|
245
|
+
* logic to detect potential success messages that don't match standard types.
|
|
246
|
+
*
|
|
247
|
+
* @param message - The unrecognized civicloginApp message to process
|
|
248
|
+
*/
|
|
249
|
+
handleUnknownCivicLoginAppMessage(message) {
|
|
250
|
+
this.logger.debug("Unhandled civicloginApp message type", {
|
|
251
|
+
type: message.type,
|
|
252
|
+
data: message.data,
|
|
253
|
+
});
|
|
254
|
+
// Check if this might be a success message with a different type
|
|
255
|
+
if (message.type && message.type.toLowerCase().includes("success")) {
|
|
256
|
+
this.logger.info("Potential success message from civicloginApp", {
|
|
257
|
+
type: message.type,
|
|
258
|
+
data: message.data,
|
|
259
|
+
});
|
|
260
|
+
this.handleAuthSuccess({
|
|
261
|
+
type: "auth_success",
|
|
262
|
+
detail: `civicloginApp success: ${message.type}`,
|
|
263
|
+
data: message.data,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Type guard to identify iframe resizer messages.
|
|
269
|
+
*
|
|
270
|
+
* Checks if a message is related to iframe resizing functionality,
|
|
271
|
+
* including both civic-specific resize messages and iFrameResizerChild messages.
|
|
272
|
+
*
|
|
273
|
+
* @param message - The message object to check
|
|
274
|
+
* @returns True if the message is an iframe resizer message, false otherwise
|
|
275
|
+
*/
|
|
276
|
+
isIframeResizerMessage(message) {
|
|
277
|
+
return ((message !== null &&
|
|
278
|
+
typeof message === "object" &&
|
|
279
|
+
"type" in message &&
|
|
280
|
+
(message.type === "civic-iframe-resize" ||
|
|
281
|
+
message.type ===
|
|
282
|
+
"civic-iframe-ready")) ||
|
|
283
|
+
(typeof message === "string" && message.includes("iFrameResizerChild")));
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Handles iframe resizer messages for dynamic iframe sizing.
|
|
287
|
+
*
|
|
288
|
+
* Processes messages related to iframe resizing, including height adjustments
|
|
289
|
+
* and ready state notifications from the iframe resizer library.
|
|
290
|
+
*
|
|
291
|
+
* @param message - The iframe resizer message to process
|
|
292
|
+
*/
|
|
293
|
+
handleIframeResizerMessage(message) {
|
|
294
|
+
if (typeof message === "string") {
|
|
295
|
+
this.logger.debug("Received iframe resizer child message", { message });
|
|
296
|
+
}
|
|
297
|
+
else if (message && typeof message === "object" && message !== null) {
|
|
298
|
+
const messageObj = message;
|
|
299
|
+
this.logger.debug("Received iframe resizer message", {
|
|
300
|
+
type: messageObj.type,
|
|
301
|
+
height: messageObj.height,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Handles standard authentication messages.
|
|
307
|
+
*
|
|
308
|
+
* Processes auth_success and auth_error messages that follow the standard
|
|
309
|
+
* authentication message format, routing them to appropriate success or error handlers.
|
|
310
|
+
*
|
|
311
|
+
* @param message - The standard auth message to process
|
|
312
|
+
*/
|
|
313
|
+
handleStandardAuthMessage(message) {
|
|
314
|
+
const messageObj = message && typeof message === "object" && message !== null
|
|
315
|
+
? message
|
|
316
|
+
: null;
|
|
317
|
+
const messageType = messageObj?.type;
|
|
318
|
+
switch (messageType) {
|
|
319
|
+
case "auth_success":
|
|
320
|
+
this.handleAuthSuccess(message);
|
|
321
|
+
break;
|
|
322
|
+
case "auth_error":
|
|
323
|
+
this.handleAuthError(message);
|
|
324
|
+
break;
|
|
325
|
+
default:
|
|
326
|
+
this.logger.debug("Message from iframe did not match expected types (auth_success, auth_error, civicloginApp, iframe-resizer)", {
|
|
327
|
+
data: message,
|
|
328
|
+
messageType: typeof message,
|
|
329
|
+
hasType: messageObj?.type ?? "none",
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Handles successful authentication completion.
|
|
335
|
+
*
|
|
336
|
+
* Processes authentication success messages, emits success events,
|
|
337
|
+
* triggers the success callback with authentication results, and performs cleanup.
|
|
338
|
+
*
|
|
339
|
+
* @param data - The authentication success message containing result data
|
|
340
|
+
*/
|
|
341
|
+
handleAuthSuccess(data) {
|
|
342
|
+
this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {
|
|
343
|
+
detail: "Success signal received via postMessage",
|
|
344
|
+
data,
|
|
345
|
+
});
|
|
346
|
+
this.onAuthSuccess(data?.data || {});
|
|
347
|
+
this.cleanup();
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Handles authentication errors.
|
|
351
|
+
*
|
|
352
|
+
* Processes authentication error messages, creates appropriate error objects,
|
|
353
|
+
* emits error events, triggers the error callback, and performs cleanup.
|
|
354
|
+
*
|
|
355
|
+
* @param data - The authentication error message containing error details
|
|
356
|
+
*/
|
|
357
|
+
handleAuthError(data) {
|
|
358
|
+
this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {
|
|
359
|
+
detail: "Error signal received via postMessage",
|
|
360
|
+
error: data,
|
|
361
|
+
});
|
|
362
|
+
const error = new CivicAuthError(data?.detail || "Error signal received via postMessage", CivicAuthErrorCode.INVALID_MESSAGE);
|
|
363
|
+
this.onAuthError(error);
|
|
364
|
+
this.cleanup();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=MessageHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageHandler.js","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/MessageHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthEvent } from \"../../types/index.js\";\nimport type { AuthResult } from \"../../types/index.js\";\nimport type {\n IframeMessage,\n AuthMessage,\n LoginAppMessage,\n ProcessedCivicAuthConfig,\n} from \"../types/AuthTypes.js\";\nimport { CivicAuthError, CivicAuthErrorCode } from \"../types/AuthTypes.js\";\nimport type { createLogger } from \"../../utils/logger.js\";\nimport { createLogger as createLoggerFn } from \"../../utils/logger.js\";\n\nexport interface MessageHandlerConfig {\n config: ProcessedCivicAuthConfig;\n logger: ReturnType<typeof createLogger>;\n iframeElement?: HTMLIFrameElement;\n onAuthSuccess: (result: AuthResult) => void;\n onAuthError: (error: Error) => void;\n onPopupFailure: (failedUrl?: string) => void;\n cleanup: () => void;\n}\n\n/**\n * MessageHandler - Handles postMessage communication and authentication flow logic\n * Processes messages from iframe, validates origins, and manages auth state transitions\n */\nexport class MessageHandler {\n private config: ProcessedCivicAuthConfig;\n private logger = createLoggerFn(\"message-handler\");\n private iframeElement?: HTMLIFrameElement;\n private onAuthSuccess: (result: AuthResult) => void;\n private onAuthError: (error: Error) => void;\n private onPopupFailure: (failedUrl?: string) => void;\n private cleanup: () => void;\n\n constructor(handlerConfig: MessageHandlerConfig) {\n this.config = handlerConfig.config;\n this.iframeElement = handlerConfig.iframeElement;\n this.onAuthSuccess = handlerConfig.onAuthSuccess;\n this.onAuthError = handlerConfig.onAuthError;\n this.onPopupFailure = handlerConfig.onPopupFailure;\n this.cleanup = handlerConfig.cleanup;\n }\n\n /**\n * Updates the iframe element reference used for message validation.\n *\n * This method allows updating the iframe element after the MessageHandler\n * has been instantiated, which is useful when the iframe is created\n * dynamically after the handler setup.\n *\n * @param iframeElement - The new iframe element to associate with this handler\n */\n public updateIframeElement(iframeElement: HTMLIFrameElement): void {\n this.iframeElement = iframeElement;\n }\n\n /**\n * Main message handler for processing postMessage events.\n *\n * Validates message origin and source, then routes valid messages to\n * appropriate handlers. This is the entry point for all iframe communication.\n *\n * @param event - The MessageEvent received from the iframe or other sources\n */\n public handleMessage = (event: MessageEvent): void => {\n const expectedOrigin = new URL(this.config.oauthServerBaseUrl).origin;\n this.logIncomingMessage(event, expectedOrigin);\n\n if (!this.isValidMessageSource(event, expectedOrigin)) {\n return;\n }\n\n this.handleValidMessage(event);\n };\n\n /**\n * Logs incoming message details for debugging purposes.\n *\n * Provides comprehensive logging of message properties including origin,\n * source validation, and iframe state for troubleshooting communication issues.\n *\n * @param event - The MessageEvent to log\n * @param expectedOrigin - The expected origin for comparison\n */\n private logIncomingMessage(\n event: MessageEvent,\n expectedOrigin: string,\n ): void {\n this.logger.debug(\"Global window received message:\", {\n data: event.data,\n origin: event.origin,\n sourceProvided: !!event.source,\n iframeContentWindow: this.iframeElement?.contentWindow,\n expectedIframeOrigin: expectedOrigin,\n });\n }\n\n /**\n * Validates that a message comes from the expected origin and source.\n *\n * Performs security checks to ensure messages are only processed from\n * the configured OAuth server origin and the designated iframe element.\n *\n * @param event - The MessageEvent to validate\n * @param expectedOrigin - The expected origin URL for the message\n * @returns True if the message source and origin are valid, false otherwise\n */\n private isValidMessageSource(\n event: MessageEvent,\n expectedOrigin: string,\n ): boolean {\n const isValidOrigin = event.origin === expectedOrigin;\n const isValidSource = event.source === this.iframeElement?.contentWindow;\n\n if (!isValidOrigin) {\n this.logger.warn(\"Ignored message from unexpected origin.\", {\n receivedOrigin: event.origin,\n expectedOrigin,\n iframeSrc: this.iframeElement?.src,\n });\n }\n\n if (!isValidSource) {\n this.logger.warn(\"Ignored message from unexpected source.\", {\n isSourceProvided: !!event.source,\n isIframeContentWindowAvailable: !!this.iframeElement?.contentWindow,\n iframeSrc: this.iframeElement?.src,\n });\n }\n\n return isValidOrigin && isValidSource;\n }\n\n /**\n * Processes messages that have passed origin and source validation.\n *\n * Routes validated messages to specific handlers based on message type,\n * including civicloginApp messages, iframe resizer messages, and standard auth messages.\n *\n * @param event - The validated MessageEvent to process\n */\n private handleValidMessage(event: MessageEvent): void {\n this.logger.info(\n \"Message from configured iframe source and origin received\",\n {\n data: event.data,\n iframeSrc: this.iframeElement?.src,\n },\n );\n\n const message = event.data as IframeMessage;\n\n this.logger.debug(\"Processing iframe message\", {\n messageType: typeof message,\n hasType: message && typeof message === \"object\" && \"type\" in message,\n hasSource: message && typeof message === \"object\" && \"source\" in message,\n messageKeys:\n message && typeof message === \"object\" ? Object.keys(message) : [],\n rawData: message,\n });\n\n // Handle civicloginApp messages\n if (this.isCivicLoginAppMessage(message)) {\n this.handleCivicLoginAppMessage(message);\n return;\n }\n\n // Handle iframe resizer messages\n if (this.isIframeResizerMessage(message)) {\n this.handleIframeResizerMessage(message);\n return;\n }\n\n // Handle standard auth messages\n this.handleStandardAuthMessage(message);\n }\n\n /**\n * Type guard to identify civicloginApp messages.\n *\n * Checks if a message object has the structure and source property\n * that identifies it as coming from the civicloginApp.\n *\n * @param message - The message object to check\n * @returns True if the message is a LoginAppMessage, false otherwise\n */\n private isCivicLoginAppMessage(message: unknown): message is LoginAppMessage {\n return (\n message !== null &&\n typeof message === \"object\" &&\n \"source\" in message &&\n (message as Record<string, unknown>).source === \"civicloginApp\"\n );\n }\n\n /**\n * Handles messages originating from the civicloginApp.\n *\n * Processes various civicloginApp message types including authentication errors,\n * popup failures, design updates, and other app-specific communications.\n * Validates client ID matches before processing.\n *\n * @param message - The validated civicloginApp message to process\n */\n private handleCivicLoginAppMessage(message: LoginAppMessage): void {\n this.logger.info(\"Received civicloginApp message\", {\n type: message.type,\n clientId: message.clientId,\n data: message.data,\n });\n\n // Validate clientId matches our config\n if (message.clientId !== this.config.clientId) {\n this.logger.warn(\"civicloginApp message clientId mismatch\", {\n received: message.clientId,\n expected: this.config.clientId,\n });\n return;\n }\n\n switch (message.type) {\n case \"auth_error\":\n case \"auth_error_try_again\":\n this.handleCivicLoginAppError(message);\n break;\n case \"generatePopupFailed\":\n this.handlePopupFailure(message);\n break;\n case \"design\":\n this.logger.debug(\"civicloginApp design message\", {\n data: message.data,\n });\n break;\n default:\n this.handleUnknownCivicLoginAppMessage(message);\n break;\n }\n }\n\n /**\n * Handles authentication error messages from civicloginApp.\n *\n * Processes auth_error and auth_error_try_again messages, creates\n * appropriate error objects, emits error events, and triggers cleanup.\n *\n * @param message - The civicloginApp error message to process\n */\n private handleCivicLoginAppError(message: LoginAppMessage): void {\n this.logger.error(\"civicloginApp authentication error\", {\n type: message.type,\n data: message.data,\n });\n\n const error = new CivicAuthError(\n `Login app error: ${message.type}`,\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: error.message,\n error: message.data,\n });\n\n this.onAuthError(error);\n this.cleanup();\n }\n\n /**\n * Handles popup generation failure messages from civicloginApp.\n *\n * Processes generatePopupFailed messages, extracts the failed URL,\n * emits appropriate events, and triggers the popup failure callback\n * to enable fallback authentication methods.\n *\n * @param message - The civicloginApp popup failure message to process\n */\n private handlePopupFailure(message: LoginAppMessage): void {\n this.logger.warn(\"civicloginApp popup generation failed\", {\n data: message.data,\n });\n\n const failedUrl = (message.data as Record<string, unknown> | undefined)\n ?.url as string | undefined;\n if (failedUrl) {\n this.logger.info(\"Popup failed for URL, considering fallback options\", {\n failedUrl,\n displayMode: this.config.displayMode,\n });\n\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Popup blocked by browser - switching to redirect mode\",\n error: {\n type: \"popup_blocked\",\n failedUrl,\n suggestion:\n \"The browser blocked a popup window. Redirecting to complete authentication in a new page.\",\n },\n });\n }\n\n this.onPopupFailure(failedUrl);\n }\n\n /**\n * Handles unknown or unrecognized civicloginApp message types.\n *\n * Provides fallback handling for unexpected message types, with special\n * logic to detect potential success messages that don't match standard types.\n *\n * @param message - The unrecognized civicloginApp message to process\n */\n private handleUnknownCivicLoginAppMessage(message: LoginAppMessage): void {\n this.logger.debug(\"Unhandled civicloginApp message type\", {\n type: message.type,\n data: message.data,\n });\n\n // Check if this might be a success message with a different type\n if (message.type && message.type.toLowerCase().includes(\"success\")) {\n this.logger.info(\"Potential success message from civicloginApp\", {\n type: message.type,\n data: message.data,\n });\n\n this.handleAuthSuccess({\n type: \"auth_success\",\n detail: `civicloginApp success: ${message.type}`,\n data: message.data,\n });\n }\n }\n\n /**\n * Type guard to identify iframe resizer messages.\n *\n * Checks if a message is related to iframe resizing functionality,\n * including both civic-specific resize messages and iFrameResizerChild messages.\n *\n * @param message - The message object to check\n * @returns True if the message is an iframe resizer message, false otherwise\n */\n private isIframeResizerMessage(message: unknown): boolean {\n return (\n (message !== null &&\n typeof message === \"object\" &&\n \"type\" in message &&\n ((message as Record<string, unknown>).type === \"civic-iframe-resize\" ||\n (message as Record<string, unknown>).type ===\n \"civic-iframe-ready\")) ||\n (typeof message === \"string\" && message.includes(\"iFrameResizerChild\"))\n );\n }\n\n /**\n * Handles iframe resizer messages for dynamic iframe sizing.\n *\n * Processes messages related to iframe resizing, including height adjustments\n * and ready state notifications from the iframe resizer library.\n *\n * @param message - The iframe resizer message to process\n */\n private handleIframeResizerMessage(message: unknown): void {\n if (typeof message === \"string\") {\n this.logger.debug(\"Received iframe resizer child message\", { message });\n } else if (message && typeof message === \"object\" && message !== null) {\n const messageObj = message as Record<string, unknown>;\n this.logger.debug(\"Received iframe resizer message\", {\n type: messageObj.type,\n height: messageObj.height,\n });\n }\n }\n\n /**\n * Handles standard authentication messages.\n *\n * Processes auth_success and auth_error messages that follow the standard\n * authentication message format, routing them to appropriate success or error handlers.\n *\n * @param message - The standard auth message to process\n */\n private handleStandardAuthMessage(message: unknown): void {\n const messageObj =\n message && typeof message === \"object\" && message !== null\n ? (message as Record<string, unknown>)\n : null;\n const messageType = messageObj?.type;\n\n switch (messageType) {\n case \"auth_success\":\n this.handleAuthSuccess(message as AuthMessage);\n break;\n case \"auth_error\":\n this.handleAuthError(message as AuthMessage);\n break;\n default:\n this.logger.debug(\n \"Message from iframe did not match expected types (auth_success, auth_error, civicloginApp, iframe-resizer)\",\n {\n data: message,\n messageType: typeof message,\n hasType: messageObj?.type ?? \"none\",\n },\n );\n }\n }\n\n /**\n * Handles successful authentication completion.\n *\n * Processes authentication success messages, emits success events,\n * triggers the success callback with authentication results, and performs cleanup.\n *\n * @param data - The authentication success message containing result data\n */\n private handleAuthSuccess(data: AuthMessage): void {\n this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {\n detail: \"Success signal received via postMessage\",\n data,\n });\n this.onAuthSuccess((data?.data as AuthResult) || {});\n this.cleanup();\n }\n\n /**\n * Handles authentication errors.\n *\n * Processes authentication error messages, creates appropriate error objects,\n * emits error events, triggers the error callback, and performs cleanup.\n *\n * @param data - The authentication error message containing error details\n */\n private handleAuthError(data: AuthMessage): void {\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Error signal received via postMessage\",\n error: data,\n });\n\n const error = new CivicAuthError(\n data?.detail || \"Error signal received via postMessage\",\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.onAuthError(error);\n this.cleanup();\n }\n}\n"]}
|
package/dist/vanillajs/auth/{OAuthCallbackHandler.d.ts → handlers/OAuthCallbackHandler.d.ts}
RENAMED
|
@@ -18,24 +18,19 @@
|
|
|
18
18
|
* - Shared token storage utilities for consistent state management
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
|
-
* ```
|
|
22
|
-
* //
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* const handled = await handleOAuthRedirectPage({
|
|
21
|
+
* ```javascript
|
|
22
|
+
* // Basic usage
|
|
23
|
+
* const config = {
|
|
26
24
|
* clientId: 'your-client-id',
|
|
27
|
-
* redirectUrl: 'https://
|
|
28
|
-
* oauthServer: 'https://auth.civic.com/oauth
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* },
|
|
33
|
-
* storageAdapter: new LocalStorageAdapter()
|
|
34
|
-
* });
|
|
25
|
+
* redirectUrl: 'https://yourapp.com/callback',
|
|
26
|
+
* oauthServer: 'https://auth.civic.com/oauth',
|
|
27
|
+
* scopes: ['openid', 'profile', 'email']
|
|
28
|
+
* };
|
|
29
|
+
* const result = await handleOAuthRedirectPage(config);
|
|
35
30
|
* ```
|
|
36
31
|
*/
|
|
37
|
-
import { getCurrentLogger } from "
|
|
38
|
-
import type { AuthStorage, OIDCTokenResponseBody } from "
|
|
32
|
+
import type { getCurrentLogger } from "../../utils/logger.js";
|
|
33
|
+
import type { AuthStorage, OIDCTokenResponseBody } from "../../../types.js";
|
|
39
34
|
/**
|
|
40
35
|
* Store tokens using the shared utilities from /shared/lib
|
|
41
36
|
* This ensures consistency with the React implementation and also handles user session storage
|
|
@@ -71,19 +66,15 @@ export interface HandleOAuthRedirectConfig {
|
|
|
71
66
|
* @returns Promise<boolean> - Returns true if callback was handled, false otherwise
|
|
72
67
|
*
|
|
73
68
|
* @example
|
|
74
|
-
* ```
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* const handled = await handleOAuthRedirectPage({
|
|
69
|
+
* ```javascript
|
|
70
|
+
* // Using storeTokens with default iframe mode
|
|
71
|
+
* const config = {
|
|
78
72
|
* clientId: 'your-client-id',
|
|
79
|
-
* redirectUrl: 'https://
|
|
80
|
-
* oauthServer: 'https://auth.civic.com/oauth
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* },
|
|
85
|
-
* storageAdapter: new LocalStorageAdapter()
|
|
86
|
-
* });
|
|
73
|
+
* redirectUrl: 'https://yourapp.com/callback',
|
|
74
|
+
* oauthServer: 'https://auth.civic.com/oauth',
|
|
75
|
+
* scopes: ['openid', 'profile', 'email']
|
|
76
|
+
* };
|
|
77
|
+
* await storeTokens(params, config);
|
|
87
78
|
* ```
|
|
88
79
|
*/
|
|
89
80
|
export declare function handleOAuthRedirectPage(config: HandleOAuthRedirectConfig): Promise<boolean>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuthCallbackHandler.d.ts","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/OAuthCallbackHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAWH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE5E;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,qBAAqB,EAC7B,cAAc,EAAE,WAAW,EAC3B,cAAc;;;;;CAAiC,GAC9C,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyBxB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,EAAE,WAAW,CAAC;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;CAC9C;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,OAAO,CAAC,CA2PlB"}
|