@jskit-ai/auth-web 0.1.8 → 0.1.10
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/package.descriptor.mjs +11 -7
- package/package.json +5 -5
- package/src/client/composables/loginView/constants.js +42 -0
- package/src/client/composables/loginView/identityHelpers.js +23 -0
- package/src/client/composables/loginView/oauthCallbackUrl.js +90 -0
- package/src/client/composables/loginView/registerCompletion.js +18 -0
- package/src/client/composables/loginView/rememberedAccountStorage.js +95 -0
- package/src/client/composables/loginView/useLoginViewActions.js +489 -0
- package/src/client/composables/loginView/useLoginViewState.js +262 -0
- package/src/client/composables/loginView/useLoginViewValidation.js +124 -0
- package/src/client/composables/loginView/validationHelpers.js +65 -0
- package/src/client/runtime/authGuardRuntime.js +83 -15
- package/src/client/runtime/useLoginView.js +69 -3
- package/src/client/views/DefaultLoginView.vue +215 -134
- package/src/server/constants/authActionIds.js +1 -0
- package/src/server/controllers/AuthController.js +6 -0
- package/src/server/routes/authRoutes.js +35 -11
- package/src/server/services/AuthWebService.js +7 -0
- package/test/authGuardRuntime.test.js +44 -0
- package/test/clientSurface.test.js +9 -4
- package/test/providerRuntime.test.js +15 -0
- package/test/registerFlow.test.js +40 -0
- package/src/client/composables/useDefaultLoginView.js +0 -935
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import { mdiGoogle } from "@mdi/js";
|
|
2
|
+
import { authRegisterCommand } from "@jskit-ai/auth-core/shared/commands/authRegisterCommand";
|
|
3
|
+
import { authRegisterConfirmationResendCommand } from "@jskit-ai/auth-core/shared/commands/authRegisterConfirmationResendCommand";
|
|
4
|
+
import { authLoginPasswordCommand } from "@jskit-ai/auth-core/shared/commands/authLoginPasswordCommand";
|
|
5
|
+
import { authLoginOtpRequestCommand } from "@jskit-ai/auth-core/shared/commands/authLoginOtpRequestCommand";
|
|
6
|
+
import { authLoginOtpVerifyCommand } from "@jskit-ai/auth-core/shared/commands/authLoginOtpVerifyCommand";
|
|
7
|
+
import { authLoginOAuthStartCommand } from "@jskit-ai/auth-core/shared/commands/authLoginOAuthStartCommand";
|
|
8
|
+
import { authLoginOAuthCompleteCommand } from "@jskit-ai/auth-core/shared/commands/authLoginOAuthCompleteCommand";
|
|
9
|
+
import { authPasswordResetRequestCommand } from "@jskit-ai/auth-core/shared/commands/authPasswordResetRequestCommand";
|
|
10
|
+
import { AUTH_PATHS, buildAuthOauthStartPath } from "@jskit-ai/auth-core/shared/authPaths";
|
|
11
|
+
import { authHttpRequest } from "../../runtime/authHttpClient.js";
|
|
12
|
+
import { normalizeAuthReturnToPath } from "../../lib/returnToPath.js";
|
|
13
|
+
import { normalizeEmailAddress } from "./identityHelpers.js";
|
|
14
|
+
import { readRememberedAccountHint } from "./rememberedAccountStorage.js";
|
|
15
|
+
import {
|
|
16
|
+
stripOAuthParamsFromLocation,
|
|
17
|
+
readOAuthCallbackParamsFromLocation
|
|
18
|
+
} from "./oauthCallbackUrl.js";
|
|
19
|
+
import { ensureCommandSectionValid } from "./validationHelpers.js";
|
|
20
|
+
import { resolveRegisterCompletionState } from "./registerCompletion.js";
|
|
21
|
+
|
|
22
|
+
const SESSION_QUERY_KEY = Object.freeze(["auth-web", "session"]);
|
|
23
|
+
|
|
24
|
+
export function useLoginViewActions({
|
|
25
|
+
state,
|
|
26
|
+
validation,
|
|
27
|
+
queryClient,
|
|
28
|
+
errorRuntime
|
|
29
|
+
} = {}) {
|
|
30
|
+
function reportAuthFeedback({
|
|
31
|
+
message,
|
|
32
|
+
severity = "error",
|
|
33
|
+
channel = "banner",
|
|
34
|
+
dedupeKey = ""
|
|
35
|
+
} = {}) {
|
|
36
|
+
const normalizedMessage = String(message || "").trim();
|
|
37
|
+
if (!normalizedMessage) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
errorRuntime.report({
|
|
42
|
+
source: "auth-web.default-login-view",
|
|
43
|
+
message: normalizedMessage,
|
|
44
|
+
severity,
|
|
45
|
+
channel,
|
|
46
|
+
dedupeKey: dedupeKey || `auth-web.default-login-view:${severity}:${normalizedMessage}`,
|
|
47
|
+
dedupeWindowMs: 3000
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function setErrorMessage(message, dedupeKey = "") {
|
|
52
|
+
const normalizedMessage = String(message || "").trim();
|
|
53
|
+
state.errorMessage.value = normalizedMessage;
|
|
54
|
+
if (!normalizedMessage) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
reportAuthFeedback({
|
|
59
|
+
message: normalizedMessage,
|
|
60
|
+
severity: "error",
|
|
61
|
+
channel: "banner",
|
|
62
|
+
dedupeKey
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function setInfoMessage(message, dedupeKey = "") {
|
|
67
|
+
const normalizedMessage = String(message || "").trim();
|
|
68
|
+
state.infoMessage.value = normalizedMessage;
|
|
69
|
+
if (!normalizedMessage) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
reportAuthFeedback({
|
|
74
|
+
message: normalizedMessage,
|
|
75
|
+
severity: "info",
|
|
76
|
+
channel: "snackbar",
|
|
77
|
+
dedupeKey
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function clearTransientMessages() {
|
|
82
|
+
state.clearTransientMessages();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function request(path, options = {}) {
|
|
86
|
+
return authHttpRequest(path, {
|
|
87
|
+
method: options.method || "GET",
|
|
88
|
+
...(options.body ? { body: options.body } : {})
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function applySessionPayload(payload) {
|
|
93
|
+
state.oauthProviders.value = Array.isArray(payload?.oauthProviders)
|
|
94
|
+
? payload.oauthProviders
|
|
95
|
+
.map((provider) => {
|
|
96
|
+
if (!provider || typeof provider !== "object") {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const id = String(provider.id || "")
|
|
100
|
+
.trim()
|
|
101
|
+
.toLowerCase();
|
|
102
|
+
if (!id) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
id,
|
|
107
|
+
label: String(provider.label || id).trim() || id
|
|
108
|
+
};
|
|
109
|
+
})
|
|
110
|
+
.filter(Boolean)
|
|
111
|
+
: [];
|
|
112
|
+
|
|
113
|
+
state.oauthDefaultProvider.value = String(payload?.oauthDefaultProvider || "")
|
|
114
|
+
.trim()
|
|
115
|
+
.toLowerCase();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function resolveDefaultOAuthProvider() {
|
|
119
|
+
const explicit = state.oauthDefaultProvider.value;
|
|
120
|
+
if (explicit) {
|
|
121
|
+
return explicit;
|
|
122
|
+
}
|
|
123
|
+
return String(state.oauthProviders.value[0]?.id || "")
|
|
124
|
+
.trim()
|
|
125
|
+
.toLowerCase();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function refreshSession() {
|
|
129
|
+
const session = await queryClient.fetchQuery({
|
|
130
|
+
queryKey: SESSION_QUERY_KEY,
|
|
131
|
+
queryFn: () => request(AUTH_PATHS.SESSION),
|
|
132
|
+
staleTime: 0
|
|
133
|
+
});
|
|
134
|
+
applySessionPayload(session);
|
|
135
|
+
return session;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function completeLogin() {
|
|
139
|
+
const session = await refreshSession();
|
|
140
|
+
if (!session?.authenticated) {
|
|
141
|
+
throw new Error("Login succeeded but the session is not active yet. Please retry.");
|
|
142
|
+
}
|
|
143
|
+
if (typeof window === "object" && window.location) {
|
|
144
|
+
window.location.replace(state.requestedReturnTo.value);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function submitRegister({ normalizedEmail, shouldRememberAccount }) {
|
|
149
|
+
const registerPayload = {
|
|
150
|
+
email: normalizedEmail,
|
|
151
|
+
password: String(state.password.value || "")
|
|
152
|
+
};
|
|
153
|
+
ensureCommandSectionValid(authRegisterCommand, "bodyValidator", registerPayload, "Unable to register.");
|
|
154
|
+
|
|
155
|
+
const registerResult = await request(AUTH_PATHS.REGISTER, {
|
|
156
|
+
method: "POST",
|
|
157
|
+
body: registerPayload
|
|
158
|
+
});
|
|
159
|
+
state.applyRememberedAccountPreference({
|
|
160
|
+
email: normalizedEmail,
|
|
161
|
+
displayName: registerResult?.username || normalizedEmail,
|
|
162
|
+
shouldRemember: shouldRememberAccount
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const registerCompletion = resolveRegisterCompletionState(registerResult);
|
|
166
|
+
if (!registerCompletion.shouldCompleteLogin) {
|
|
167
|
+
state.enterEmailConfirmationPendingState({
|
|
168
|
+
emailAddress: normalizedEmail,
|
|
169
|
+
message: registerCompletion.message
|
|
170
|
+
});
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
await completeLogin();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function submitForgot({ normalizedEmail }) {
|
|
178
|
+
const forgotPayload = { email: normalizedEmail };
|
|
179
|
+
ensureCommandSectionValid(
|
|
180
|
+
authPasswordResetRequestCommand,
|
|
181
|
+
"bodyValidator",
|
|
182
|
+
forgotPayload,
|
|
183
|
+
"Unable to request password reset."
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
await request(AUTH_PATHS.PASSWORD_FORGOT, {
|
|
187
|
+
method: "POST",
|
|
188
|
+
body: forgotPayload
|
|
189
|
+
});
|
|
190
|
+
setInfoMessage("Password reset instructions sent.", "auth-web.default-login-view:password-reset-sent");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function submitOtp({ normalizedEmail, shouldRememberAccount }) {
|
|
194
|
+
const otpPayload = {
|
|
195
|
+
email: normalizedEmail,
|
|
196
|
+
token: String(state.otpCode.value || "").trim(),
|
|
197
|
+
type: "email"
|
|
198
|
+
};
|
|
199
|
+
ensureCommandSectionValid(authLoginOtpVerifyCommand, "bodyValidator", otpPayload, "Unable to verify one-time code.");
|
|
200
|
+
|
|
201
|
+
const otpResult = await request(AUTH_PATHS.LOGIN_OTP_VERIFY, {
|
|
202
|
+
method: "POST",
|
|
203
|
+
body: otpPayload
|
|
204
|
+
});
|
|
205
|
+
state.applyRememberedAccountPreference({
|
|
206
|
+
email: normalizedEmail,
|
|
207
|
+
displayName: otpResult?.username || normalizedEmail,
|
|
208
|
+
shouldRemember: shouldRememberAccount
|
|
209
|
+
});
|
|
210
|
+
await completeLogin();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function submitLogin({ normalizedEmail, shouldRememberAccount }) {
|
|
214
|
+
const loginPayload = {
|
|
215
|
+
email: normalizedEmail,
|
|
216
|
+
password: String(state.password.value || "")
|
|
217
|
+
};
|
|
218
|
+
ensureCommandSectionValid(authLoginPasswordCommand, "bodyValidator", loginPayload, "Unable to sign in.");
|
|
219
|
+
|
|
220
|
+
const loginResult = await request(AUTH_PATHS.LOGIN, {
|
|
221
|
+
method: "POST",
|
|
222
|
+
body: loginPayload
|
|
223
|
+
});
|
|
224
|
+
state.applyRememberedAccountPreference({
|
|
225
|
+
email: normalizedEmail,
|
|
226
|
+
displayName: loginResult?.username || normalizedEmail,
|
|
227
|
+
shouldRemember: shouldRememberAccount
|
|
228
|
+
});
|
|
229
|
+
await completeLogin();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function buildOAuthCompletePayload({ callbackParams, provider, hasSessionPair }) {
|
|
233
|
+
const payload = {};
|
|
234
|
+
if (provider) {
|
|
235
|
+
payload.provider = provider;
|
|
236
|
+
}
|
|
237
|
+
if (callbackParams.code) {
|
|
238
|
+
payload.code = callbackParams.code;
|
|
239
|
+
}
|
|
240
|
+
if (hasSessionPair) {
|
|
241
|
+
payload.accessToken = callbackParams.accessToken;
|
|
242
|
+
payload.refreshToken = callbackParams.refreshToken;
|
|
243
|
+
}
|
|
244
|
+
return payload;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async function handleOAuthCallbackIfPresent() {
|
|
248
|
+
const callbackParams = readOAuthCallbackParamsFromLocation();
|
|
249
|
+
if (!callbackParams) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
state.requestedReturnTo.value = normalizeAuthReturnToPath(callbackParams.returnTo, state.requestedReturnTo.value, {
|
|
254
|
+
allowedOrigins: state.allowedReturnToOrigins.value
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const provider = String(callbackParams.provider || resolveDefaultOAuthProvider() || "")
|
|
258
|
+
.trim()
|
|
259
|
+
.toLowerCase();
|
|
260
|
+
const oauthError = callbackParams.errorCode;
|
|
261
|
+
const oauthErrorDescription = callbackParams.errorDescription;
|
|
262
|
+
const hasSessionPair = callbackParams.hasSessionPair === true;
|
|
263
|
+
|
|
264
|
+
if (!provider && !hasSessionPair) {
|
|
265
|
+
setErrorMessage("OAuth provider is missing from callback.", "auth-web.default-login-view:oauth-missing-provider");
|
|
266
|
+
stripOAuthParamsFromLocation();
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (oauthError) {
|
|
271
|
+
setErrorMessage(oauthErrorDescription || oauthError, "auth-web.default-login-view:oauth-callback-error");
|
|
272
|
+
stripOAuthParamsFromLocation();
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
state.loading.value = true;
|
|
277
|
+
clearTransientMessages();
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
const payload = buildOAuthCompletePayload({
|
|
281
|
+
callbackParams,
|
|
282
|
+
provider,
|
|
283
|
+
hasSessionPair
|
|
284
|
+
});
|
|
285
|
+
ensureCommandSectionValid(
|
|
286
|
+
authLoginOAuthCompleteCommand,
|
|
287
|
+
"bodyValidator",
|
|
288
|
+
payload,
|
|
289
|
+
"Invalid OAuth callback payload."
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const oauthResult = await request(AUTH_PATHS.OAUTH_COMPLETE, {
|
|
293
|
+
method: "POST",
|
|
294
|
+
body: payload
|
|
295
|
+
});
|
|
296
|
+
state.applyRememberedAccountPreference({
|
|
297
|
+
email: oauthResult?.email || state.email.value,
|
|
298
|
+
displayName: oauthResult?.username || oauthResult?.email || state.email.value,
|
|
299
|
+
shouldRemember: state.rememberAccountOnDevice.value !== false
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
stripOAuthParamsFromLocation();
|
|
303
|
+
await completeLogin();
|
|
304
|
+
} catch (error) {
|
|
305
|
+
setErrorMessage(String(error?.message || "Unable to complete OAuth sign-in."));
|
|
306
|
+
stripOAuthParamsFromLocation();
|
|
307
|
+
} finally {
|
|
308
|
+
state.loading.value = false;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async function submitAuth() {
|
|
315
|
+
state.submitAttempted.value = true;
|
|
316
|
+
clearTransientMessages();
|
|
317
|
+
if (!validation.canSubmit.value) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
state.loading.value = true;
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
const normalizedEmail = state.resolveNormalizedEmail();
|
|
325
|
+
const shouldRememberAccount = state.rememberAccountOnDevice.value !== false;
|
|
326
|
+
|
|
327
|
+
if (state.isRegister.value) {
|
|
328
|
+
await submitRegister({ normalizedEmail, shouldRememberAccount });
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (state.isForgot.value) {
|
|
333
|
+
await submitForgot({ normalizedEmail });
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (state.isOtp.value) {
|
|
338
|
+
await submitOtp({ normalizedEmail, shouldRememberAccount });
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
await submitLogin({ normalizedEmail, shouldRememberAccount });
|
|
343
|
+
} catch (error) {
|
|
344
|
+
setErrorMessage(String(error?.message || "Authentication failed."));
|
|
345
|
+
} finally {
|
|
346
|
+
state.loading.value = false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
async function requestOtpCode() {
|
|
351
|
+
state.otpRequestPending.value = true;
|
|
352
|
+
clearTransientMessages();
|
|
353
|
+
try {
|
|
354
|
+
const normalizedEmail = state.resolveNormalizedEmail();
|
|
355
|
+
const otpRequestPayload = {
|
|
356
|
+
email: normalizedEmail,
|
|
357
|
+
returnTo: state.requestedReturnTo.value
|
|
358
|
+
};
|
|
359
|
+
ensureCommandSectionValid(
|
|
360
|
+
authLoginOtpRequestCommand,
|
|
361
|
+
"bodyValidator",
|
|
362
|
+
otpRequestPayload,
|
|
363
|
+
"Unable to request one-time code."
|
|
364
|
+
);
|
|
365
|
+
await request(AUTH_PATHS.LOGIN_OTP_REQUEST, {
|
|
366
|
+
method: "POST",
|
|
367
|
+
body: otpRequestPayload
|
|
368
|
+
});
|
|
369
|
+
setInfoMessage("One-time code sent. Check your inbox.", "auth-web.default-login-view:otp-code-sent");
|
|
370
|
+
} catch (error) {
|
|
371
|
+
setErrorMessage(String(error?.message || "Unable to request one-time code."));
|
|
372
|
+
} finally {
|
|
373
|
+
state.otpRequestPending.value = false;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
async function resendRegisterConfirmationEmail() {
|
|
378
|
+
const normalizedEmail = normalizeEmailAddress(state.pendingEmailConfirmationAddress.value || state.email.value);
|
|
379
|
+
if (!normalizedEmail) {
|
|
380
|
+
setErrorMessage("Enter an email address before requesting confirmation.");
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
state.registerConfirmationResendPending.value = true;
|
|
385
|
+
clearTransientMessages();
|
|
386
|
+
try {
|
|
387
|
+
const resendPayload = {
|
|
388
|
+
email: normalizedEmail
|
|
389
|
+
};
|
|
390
|
+
ensureCommandSectionValid(
|
|
391
|
+
authRegisterConfirmationResendCommand,
|
|
392
|
+
"bodyValidator",
|
|
393
|
+
resendPayload,
|
|
394
|
+
"Unable to resend confirmation email."
|
|
395
|
+
);
|
|
396
|
+
const resendResult = await request(AUTH_PATHS.REGISTER_CONFIRMATION_RESEND, {
|
|
397
|
+
method: "POST",
|
|
398
|
+
body: resendPayload
|
|
399
|
+
});
|
|
400
|
+
const info =
|
|
401
|
+
String(resendResult?.message || "").trim() ||
|
|
402
|
+
"If an account exists for that email, a confirmation email has been sent.";
|
|
403
|
+
setInfoMessage(info, "auth-web.default-login-view:register-confirmation-resend");
|
|
404
|
+
} catch (error) {
|
|
405
|
+
setErrorMessage(String(error?.message || "Unable to resend confirmation email."));
|
|
406
|
+
} finally {
|
|
407
|
+
state.registerConfirmationResendPending.value = false;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function oauthProviderButtonLabel(provider) {
|
|
412
|
+
const providerLabel = String(provider?.label || provider?.id || "OAuth provider");
|
|
413
|
+
if (state.isRegister.value) {
|
|
414
|
+
return `Register with ${providerLabel}`;
|
|
415
|
+
}
|
|
416
|
+
if (state.showRememberedAccount.value) {
|
|
417
|
+
return `Continue with ${providerLabel} as ${state.rememberedAccountDisplayName.value}`;
|
|
418
|
+
}
|
|
419
|
+
return `Continue with ${providerLabel}`;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function oauthProviderIcon(provider) {
|
|
423
|
+
if (String(provider?.id || "").toLowerCase() === "google") {
|
|
424
|
+
return mdiGoogle;
|
|
425
|
+
}
|
|
426
|
+
return undefined;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function startOAuthSignIn(providerId) {
|
|
430
|
+
const provider = String(providerId || "").trim().toLowerCase();
|
|
431
|
+
if (!provider || typeof window !== "object" || !window.location) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const paramsPayload = {
|
|
436
|
+
provider
|
|
437
|
+
};
|
|
438
|
+
const queryPayload = {
|
|
439
|
+
returnTo: state.requestedReturnTo.value
|
|
440
|
+
};
|
|
441
|
+
try {
|
|
442
|
+
ensureCommandSectionValid(
|
|
443
|
+
authLoginOAuthStartCommand,
|
|
444
|
+
"paramsValidator",
|
|
445
|
+
paramsPayload,
|
|
446
|
+
"OAuth provider id is invalid."
|
|
447
|
+
);
|
|
448
|
+
ensureCommandSectionValid(
|
|
449
|
+
authLoginOAuthStartCommand,
|
|
450
|
+
"queryValidator",
|
|
451
|
+
queryPayload,
|
|
452
|
+
"OAuth return path is invalid."
|
|
453
|
+
);
|
|
454
|
+
} catch (error) {
|
|
455
|
+
setErrorMessage(String(error?.message || "Unable to start OAuth sign-in."));
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const params = new URLSearchParams(queryPayload);
|
|
460
|
+
const oauthStartPath = buildAuthOauthStartPath(provider);
|
|
461
|
+
window.location.assign(`${oauthStartPath}?${params.toString()}`);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
async function initializeOnMounted() {
|
|
465
|
+
state.applyRememberedAccountHint(readRememberedAccountHint());
|
|
466
|
+
state.loading.value = true;
|
|
467
|
+
try {
|
|
468
|
+
const session = await refreshSession();
|
|
469
|
+
const callbackHandled = await handleOAuthCallbackIfPresent();
|
|
470
|
+
if (!callbackHandled && session?.authenticated && typeof window === "object" && window.location) {
|
|
471
|
+
window.location.replace(state.requestedReturnTo.value);
|
|
472
|
+
}
|
|
473
|
+
} catch (error) {
|
|
474
|
+
setErrorMessage(String(error?.message || "Unable to initialize sign in."));
|
|
475
|
+
} finally {
|
|
476
|
+
state.loading.value = false;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return {
|
|
481
|
+
submitAuth,
|
|
482
|
+
requestOtpCode,
|
|
483
|
+
resendRegisterConfirmationEmail,
|
|
484
|
+
oauthProviderButtonLabel,
|
|
485
|
+
oauthProviderIcon,
|
|
486
|
+
startOAuthSignIn,
|
|
487
|
+
initializeOnMounted
|
|
488
|
+
};
|
|
489
|
+
}
|