@micha.bigler/ui-core-micha 1.3.4 → 1.3.6
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 +41 -25
- package/package.json +1 -1
- package/src/auth/authApi.jsx +52 -25
package/dist/auth/authApi.js
CHANGED
|
@@ -373,32 +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, _b;
|
|
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
381
|
const status = (_a = error.response) === null || _a === void 0 ? void 0 : _a.status;
|
|
382
382
|
const data = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data;
|
|
383
|
-
|
|
384
|
-
//
|
|
385
|
-
//
|
|
386
|
-
|
|
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) {
|
|
387
389
|
return {
|
|
388
390
|
needsMfa: true,
|
|
389
|
-
availableTypes:
|
|
391
|
+
availableTypes: mfaFlow.types || [], // ["recovery_codes", "webauthn"]
|
|
390
392
|
};
|
|
391
393
|
}
|
|
392
|
-
// ---
|
|
394
|
+
// --- Already Logged In ---
|
|
393
395
|
if (status === 409) {
|
|
394
|
-
//
|
|
396
|
+
// user ist schon eingeloggt
|
|
395
397
|
}
|
|
396
398
|
else {
|
|
397
|
-
// Echter Fehler (z.B. falsches Passwort oder Serverfehler)
|
|
398
399
|
throw new Error(extractErrorMessage(error));
|
|
399
400
|
}
|
|
400
401
|
}
|
|
401
|
-
//
|
|
402
|
+
// Erfolg ohne MFA
|
|
402
403
|
const user = await fetchCurrentUser();
|
|
403
404
|
return { user, needsMfa: false };
|
|
404
405
|
}
|
|
@@ -411,25 +412,40 @@ export async function fetchAuthenticators() {
|
|
|
411
412
|
}
|
|
412
413
|
// 2. TOTP Einrichtung starten (liefert Secret & QR-URL)
|
|
413
414
|
export async function requestTotpKey() {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
withCredentials: true
|
|
417
|
-
|
|
418
|
-
|
|
415
|
+
var _a, _b, _c, _d;
|
|
416
|
+
try {
|
|
417
|
+
const res = await axios.get(`${HEADLESS_BASE}/account/authenticators/totp`, { withCredentials: true });
|
|
418
|
+
// 200 => TOTP ist bereits aktiv
|
|
419
|
+
return {
|
|
420
|
+
isActive: true,
|
|
421
|
+
secret: null,
|
|
422
|
+
totpUrl: null,
|
|
423
|
+
raw: res.data,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
catch (error) {
|
|
427
|
+
const status = (_a = error.response) === null || _a === void 0 ? void 0 : _a.status;
|
|
428
|
+
const payload = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data;
|
|
429
|
+
// 404 + meta.secret + meta.totp_url => Setup-Information
|
|
430
|
+
if (status === 404 &&
|
|
431
|
+
((_c = payload === null || payload === void 0 ? void 0 : payload.meta) === null || _c === void 0 ? void 0 : _c.secret) &&
|
|
432
|
+
((_d = payload === null || payload === void 0 ? void 0 : payload.meta) === null || _d === void 0 ? void 0 : _d.totp_url)) {
|
|
433
|
+
return {
|
|
434
|
+
isActive: false,
|
|
435
|
+
secret: payload.meta.secret,
|
|
436
|
+
totpUrl: payload.meta.totp_url,
|
|
437
|
+
raw: payload,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
throw new Error(extractErrorMessage(error));
|
|
441
|
+
}
|
|
419
442
|
}
|
|
420
|
-
// 3. TOTP Einrichtung abschließen (Code verifizieren)
|
|
421
443
|
export async function activateTotp(code) {
|
|
422
|
-
const res = await axios.post(`${HEADLESS_BASE}/
|
|
444
|
+
const res = await axios.post(`${HEADLESS_BASE}/account/authenticators/totp`, { code }, { withCredentials: true });
|
|
423
445
|
return res.data;
|
|
424
446
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
// Manche Implementierungen nutzen DELETE auf /mfa/totp, andere auf den Authenticator-ID endpoint.
|
|
428
|
-
// Wir nutzen hier den allgemeinen Authenticator-Delete Endpoint, wenn wir die ID haben.
|
|
429
|
-
// Alternativ: DELETE /mfa/totp
|
|
430
|
-
const res = await axios.delete(`${HEADLESS_BASE}/mfa/authenticators/${id}`, {
|
|
431
|
-
withCredentials: true,
|
|
432
|
-
});
|
|
447
|
+
export async function deactivateTotp() {
|
|
448
|
+
const res = await axios.delete(`${HEADLESS_BASE}/account/authenticators/totp`, { withCredentials: true });
|
|
433
449
|
return res.data;
|
|
434
450
|
}
|
|
435
451
|
// -----------------------------
|
package/package.json
CHANGED
package/src/auth/authApi.jsx
CHANGED
|
@@ -495,26 +495,29 @@ export async function loginWithPassword(email, password) {
|
|
|
495
495
|
const status = error.response?.status;
|
|
496
496
|
const data = error.response?.data;
|
|
497
497
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
//
|
|
501
|
-
|
|
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
511
|
|
|
508
|
-
// ---
|
|
512
|
+
// --- Already Logged In ---
|
|
509
513
|
if (status === 409) {
|
|
510
|
-
|
|
514
|
+
// user ist schon eingeloggt
|
|
511
515
|
} else {
|
|
512
|
-
// Echter Fehler (z.B. falsches Passwort oder Serverfehler)
|
|
513
516
|
throw new Error(extractErrorMessage(error));
|
|
514
517
|
}
|
|
515
518
|
}
|
|
516
519
|
|
|
517
|
-
//
|
|
520
|
+
// Erfolg ohne MFA
|
|
518
521
|
const user = await fetchCurrentUser();
|
|
519
522
|
return { user, needsMfa: false };
|
|
520
523
|
}
|
|
@@ -529,31 +532,55 @@ export async function fetchAuthenticators() {
|
|
|
529
532
|
|
|
530
533
|
// 2. TOTP Einrichtung starten (liefert Secret & QR-URL)
|
|
531
534
|
export async function requestTotpKey() {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
535
|
+
try {
|
|
536
|
+
const res = await axios.get(
|
|
537
|
+
`${HEADLESS_BASE}/account/authenticators/totp`,
|
|
538
|
+
{ withCredentials: true },
|
|
539
|
+
);
|
|
540
|
+
|
|
541
|
+
// 200 => TOTP ist bereits aktiv
|
|
542
|
+
return {
|
|
543
|
+
isActive: true,
|
|
544
|
+
secret: null,
|
|
545
|
+
totpUrl: null,
|
|
546
|
+
raw: res.data,
|
|
547
|
+
};
|
|
548
|
+
} catch (error) {
|
|
549
|
+
const status = error.response?.status;
|
|
550
|
+
const payload = error.response?.data;
|
|
551
|
+
|
|
552
|
+
// 404 + meta.secret + meta.totp_url => Setup-Information
|
|
553
|
+
if (
|
|
554
|
+
status === 404 &&
|
|
555
|
+
payload?.meta?.secret &&
|
|
556
|
+
payload?.meta?.totp_url
|
|
557
|
+
) {
|
|
558
|
+
return {
|
|
559
|
+
isActive: false,
|
|
560
|
+
secret: payload.meta.secret,
|
|
561
|
+
totpUrl: payload.meta.totp_url,
|
|
562
|
+
raw: payload,
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
throw new Error(extractErrorMessage(error));
|
|
567
|
+
}
|
|
537
568
|
}
|
|
538
569
|
|
|
539
|
-
// 3. TOTP Einrichtung abschließen (Code verifizieren)
|
|
540
570
|
export async function activateTotp(code) {
|
|
541
571
|
const res = await axios.post(
|
|
542
|
-
`${HEADLESS_BASE}/
|
|
572
|
+
`${HEADLESS_BASE}/account/authenticators/totp`,
|
|
543
573
|
{ code },
|
|
544
|
-
{ withCredentials: true }
|
|
574
|
+
{ withCredentials: true },
|
|
545
575
|
);
|
|
546
576
|
return res.data;
|
|
547
577
|
}
|
|
548
578
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
const res = await axios.delete(`${HEADLESS_BASE}/mfa/authenticators/${id}`, {
|
|
555
|
-
withCredentials: true,
|
|
556
|
-
});
|
|
579
|
+
export async function deactivateTotp() {
|
|
580
|
+
const res = await axios.delete(
|
|
581
|
+
`${HEADLESS_BASE}/account/authenticators/totp`,
|
|
582
|
+
{ withCredentials: true },
|
|
583
|
+
);
|
|
557
584
|
return res.data;
|
|
558
585
|
}
|
|
559
586
|
|