@micha.bigler/ui-core-micha 1.3.2 → 1.3.5
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/auth/authApi.js +14 -11
- package/dist/pages/LoginPage.js +19 -1
- package/package.json +1 -1
- package/src/auth/authApi.jsx +19 -15
- package/src/pages/LoginPage.jsx +18 -1
package/dist/auth/authApi.js
CHANGED
|
@@ -373,30 +373,33 @@ export async function authenticateWithMFA({ code, credential }) {
|
|
|
373
373
|
// Authentication: password (MODIFIZIERT)
|
|
374
374
|
// -----------------------------
|
|
375
375
|
export async function loginWithPassword(email, password) {
|
|
376
|
-
var _a;
|
|
376
|
+
var _a, _b, _c;
|
|
377
377
|
try {
|
|
378
378
|
await axios.post(`${HEADLESS_BASE}/auth/login`, { email, password }, { withCredentials: true });
|
|
379
379
|
}
|
|
380
380
|
catch (error) {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
381
|
+
const status = (_a = error.response) === null || _a === void 0 ? void 0 : _a.status;
|
|
382
|
+
const data = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data;
|
|
383
|
+
console.log('Login Error Debug:', { status, data });
|
|
384
|
+
// --- SKEPTISCHER CHECK (KORRIGIERT) ---
|
|
385
|
+
// Wir suchen in der Liste 'flows' nach einem Eintrag mit id='mfa_authenticate'
|
|
386
|
+
// und prüfen, ob er 'is_pending' ist.
|
|
387
|
+
const mfaFlow = (_c = data === null || data === void 0 ? void 0 : data.flows) === null || _c === void 0 ? void 0 : _c.find(f => f.id === 'mfa_authenticate');
|
|
388
|
+
if (status === 401 && mfaFlow && mfaFlow.is_pending) {
|
|
386
389
|
return {
|
|
387
390
|
needsMfa: true,
|
|
388
|
-
availableTypes:
|
|
391
|
+
availableTypes: mfaFlow.types || [], // ["recovery_codes", "webauthn"]
|
|
389
392
|
};
|
|
390
393
|
}
|
|
391
|
-
//
|
|
392
|
-
if (
|
|
393
|
-
//
|
|
394
|
+
// --- Already Logged In ---
|
|
395
|
+
if (status === 409) {
|
|
396
|
+
// user ist schon eingeloggt
|
|
394
397
|
}
|
|
395
398
|
else {
|
|
396
399
|
throw new Error(extractErrorMessage(error));
|
|
397
400
|
}
|
|
398
401
|
}
|
|
399
|
-
//
|
|
402
|
+
// Erfolg ohne MFA
|
|
400
403
|
const user = await fetchCurrentUser();
|
|
401
404
|
return { user, needsMfa: false };
|
|
402
405
|
}
|
package/dist/pages/LoginPage.js
CHANGED
|
@@ -76,7 +76,25 @@ export function LoginPage() {
|
|
|
76
76
|
};
|
|
77
77
|
// ... (Social & Sign Up Handler bleiben gleich) ...
|
|
78
78
|
const handleSocialLogin = (provider) => authApi.startSocialLogin(provider);
|
|
79
|
-
const handlePasskeyLoginInitial = async () => {
|
|
79
|
+
const handlePasskeyLoginInitial = async () => {
|
|
80
|
+
var _a, _b;
|
|
81
|
+
setError('');
|
|
82
|
+
setSubmitting(true);
|
|
83
|
+
try {
|
|
84
|
+
// Wir rufen die existierende Passkey-Login Funktion auf
|
|
85
|
+
const { user } = await authApi.loginWithPasskey();
|
|
86
|
+
login(user);
|
|
87
|
+
navigate('/');
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
setError(((_b = (_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.detail) ||
|
|
91
|
+
(err === null || err === void 0 ? void 0 : err.message) ||
|
|
92
|
+
'Passkey login failed.');
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
setSubmitting(false);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
80
98
|
const handleSignUp = () => navigate('/signup');
|
|
81
99
|
const handleForgotPassword = () => navigate('/reset-request-password');
|
|
82
100
|
return (_jsxs(NarrowPage, { title: "Login", children: [_jsx(Helmet, { children: _jsx("title", { children: "Login" }) }), error && _jsx(Alert, { severity: "error", sx: { mb: 2 }, children: error }), step === 'credentials' && (_jsx(LoginForm, { onSubmit: handleSubmitCredentials, onForgotPassword: handleForgotPassword, onSocialLogin: handleSocialLogin, onPasskeyLogin: handlePasskeyLoginInitial, onSignUp: handleSignUp, disabled: submitting })), step === 'mfa' && (_jsxs(Box, { children: [_jsx(Typography, { variant: "body1", gutterBottom: true, children: "Two-Factor Authentication required." }), _jsxs(Stack, { spacing: 2, sx: { mt: 2 }, children: [mfaTypes.includes('webauthn') && (_jsx(Button, { variant: "outlined", onClick: handleMfaPasskey, fullWidth: true, children: "Use Passkey / Security Key" })), (mfaTypes.includes('totp') || mfaTypes.includes('recovery_codes')) && (_jsxs("form", { onSubmit: handleMfaTotpSubmit, children: [_jsx(TextField, { label: "Authenticator Code (or Recovery Code)", value: totpCode, onChange: (e) => setTotpCode(e.target.value), fullWidth: true, autoFocus: true, disabled: submitting, sx: { mb: 2 } }), _jsx(Button, { type: "submit", variant: "contained", fullWidth: true, disabled: submitting, children: "Verify" })] })), _jsx(Button, { size: "small", onClick: () => setStep('credentials'), children: "Back to Login" })] })] }))] }));
|
package/package.json
CHANGED
package/src/auth/authApi.jsx
CHANGED
|
@@ -489,31 +489,35 @@ export async function loginWithPassword(email, password) {
|
|
|
489
489
|
await axios.post(
|
|
490
490
|
`${HEADLESS_BASE}/auth/login`,
|
|
491
491
|
{ email, password },
|
|
492
|
-
{ withCredentials: true }
|
|
492
|
+
{ withCredentials: true },
|
|
493
493
|
);
|
|
494
494
|
} catch (error) {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
)
|
|
501
|
-
|
|
495
|
+
const status = error.response?.status;
|
|
496
|
+
const data = error.response?.data;
|
|
497
|
+
|
|
498
|
+
console.log('Login Error Debug:', { status, data });
|
|
499
|
+
|
|
500
|
+
// --- SKEPTISCHER CHECK (KORRIGIERT) ---
|
|
501
|
+
// Wir suchen in der Liste 'flows' nach einem Eintrag mit id='mfa_authenticate'
|
|
502
|
+
// und prüfen, ob er 'is_pending' ist.
|
|
503
|
+
const mfaFlow = data?.flows?.find(f => f.id === 'mfa_authenticate');
|
|
504
|
+
|
|
505
|
+
if (status === 401 && mfaFlow && mfaFlow.is_pending) {
|
|
502
506
|
return {
|
|
503
507
|
needsMfa: true,
|
|
504
|
-
availableTypes:
|
|
508
|
+
availableTypes: mfaFlow.types || [], // ["recovery_codes", "webauthn"]
|
|
505
509
|
};
|
|
506
510
|
}
|
|
507
|
-
|
|
508
|
-
//
|
|
509
|
-
if (
|
|
510
|
-
//
|
|
511
|
+
|
|
512
|
+
// --- Already Logged In ---
|
|
513
|
+
if (status === 409) {
|
|
514
|
+
// user ist schon eingeloggt
|
|
511
515
|
} else {
|
|
512
|
-
|
|
516
|
+
throw new Error(extractErrorMessage(error));
|
|
513
517
|
}
|
|
514
518
|
}
|
|
515
519
|
|
|
516
|
-
//
|
|
520
|
+
// Erfolg ohne MFA
|
|
517
521
|
const user = await fetchCurrentUser();
|
|
518
522
|
return { user, needsMfa: false };
|
|
519
523
|
}
|
package/src/pages/LoginPage.jsx
CHANGED
|
@@ -77,7 +77,24 @@ export function LoginPage() {
|
|
|
77
77
|
|
|
78
78
|
// ... (Social & Sign Up Handler bleiben gleich) ...
|
|
79
79
|
const handleSocialLogin = (provider) => authApi.startSocialLogin(provider);
|
|
80
|
-
const handlePasskeyLoginInitial = async () => {
|
|
80
|
+
const handlePasskeyLoginInitial = async () => {
|
|
81
|
+
setError('');
|
|
82
|
+
setSubmitting(true);
|
|
83
|
+
try {
|
|
84
|
+
// Wir rufen die existierende Passkey-Login Funktion auf
|
|
85
|
+
const { user } = await authApi.loginWithPasskey();
|
|
86
|
+
login(user);
|
|
87
|
+
navigate('/');
|
|
88
|
+
} catch (err) {
|
|
89
|
+
setError(
|
|
90
|
+
err?.response?.data?.detail ||
|
|
91
|
+
err?.message ||
|
|
92
|
+
'Passkey login failed.',
|
|
93
|
+
);
|
|
94
|
+
} finally {
|
|
95
|
+
setSubmitting(false);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
81
98
|
const handleSignUp = () => navigate('/signup');
|
|
82
99
|
const handleForgotPassword = () => navigate('/reset-request-password');
|
|
83
100
|
|