@flowselections/core 1.0.18 → 1.0.20
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/handover.functions.d.ts +16 -0
- package/dist/auth/handover.functions.d.ts.map +1 -0
- package/dist/auth/handover.functions.js +23 -0
- package/dist/components/layout/HandoverPage.d.ts +8 -0
- package/dist/components/layout/HandoverPage.d.ts.map +1 -0
- package/dist/components/layout/HandoverPage.js +73 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/provider-token.d.ts +17 -0
- package/dist/server/provider-token.d.ts.map +1 -1
- package/dist/server/provider-token.js +53 -6
- package/package.json +1 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface HandoverExchangeResult {
|
|
2
|
+
accessToken: string;
|
|
3
|
+
refreshToken: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Wisselt een eenmalige handover-code in voor een Supabase-sessie.
|
|
7
|
+
*
|
|
8
|
+
* Fail-closed: bij elke fout gooit deze functie en krijgt de client alleen een
|
|
9
|
+
* generieke foutmelding. De code wordt nooit gelogd.
|
|
10
|
+
*/
|
|
11
|
+
export declare const exchangeHandover: import("@tanstack/start-client-core").RequiredFetcher<undefined, (data: {
|
|
12
|
+
code: string;
|
|
13
|
+
}) => {
|
|
14
|
+
code: string;
|
|
15
|
+
}, Promise<HandoverExchangeResult>>;
|
|
16
|
+
//# sourceMappingURL=handover.functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handover.functions.d.ts","sourceRoot":"","sources":["../../src/core/auth/handover.functions.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,0EACJ;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;;mCASrC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
2
|
+
// Top-level import van het server-only bestand: de Start-compiler haalt de
|
|
3
|
+
// handler-body (en dus deze aanroep) uit de clientbundel. Met een testbuild
|
|
4
|
+
// gecontroleerd: het central-auth-secret en het exchange-pad komen niet in de
|
|
5
|
+
// clientchunks voor.
|
|
6
|
+
import { exchangeHandoverCode } from "../server/provider-token.js";
|
|
7
|
+
/**
|
|
8
|
+
* Wisselt een eenmalige handover-code in voor een Supabase-sessie.
|
|
9
|
+
*
|
|
10
|
+
* Fail-closed: bij elke fout gooit deze functie en krijgt de client alleen een
|
|
11
|
+
* generieke foutmelding. De code wordt nooit gelogd.
|
|
12
|
+
*/
|
|
13
|
+
export const exchangeHandover = createServerFn({ method: "POST" })
|
|
14
|
+
.inputValidator((data) => {
|
|
15
|
+
if (!data || typeof data.code !== "string" || data.code.trim() === "") {
|
|
16
|
+
throw new Error("invalid_request");
|
|
17
|
+
}
|
|
18
|
+
return { code: data.code };
|
|
19
|
+
})
|
|
20
|
+
.handler(async ({ data }) => {
|
|
21
|
+
const session = await exchangeHandoverCode(data.code);
|
|
22
|
+
return { accessToken: session.accessToken, refreshToken: session.refreshToken };
|
|
23
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface HandoverPageProps {
|
|
2
|
+
/** Waar de gebruiker na een geslaagde handover naartoe gaat. */
|
|
3
|
+
redirectTo?: string;
|
|
4
|
+
/** Pad van de (centrale) inlogpagina voor de foutknop. */
|
|
5
|
+
loginPath?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function HandoverPage({ redirectTo, loginPath }: HandoverPageProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=HandoverPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HandoverPage.d.ts","sourceRoot":"","sources":["../../../src/core/components/layout/HandoverPage.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,YAAY,CAAC,EAAE,UAAgB,EAAE,SAAoB,EAAE,EAAE,iBAAiB,2CAgGzF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { useRouter } from "@tanstack/react-router";
|
|
4
|
+
import { Button } from "../ui/button";
|
|
5
|
+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../ui/card";
|
|
6
|
+
import { supabase } from "../../supabase/client";
|
|
7
|
+
import { exchangeHandover } from "../../auth/handover.functions.js";
|
|
8
|
+
const FOUTMELDING = "Inloggen is niet gelukt. Probeer het opnieuw vanaf de inlogpagina.";
|
|
9
|
+
export function HandoverPage({ redirectTo = "/", loginPath = "/login" }) {
|
|
10
|
+
const router = useRouter();
|
|
11
|
+
const [failed, setFailed] = useState(false);
|
|
12
|
+
const started = useRef(false);
|
|
13
|
+
/** Wacht tot de auth-context de nieuwe sessie kent, zodat de route-gate niet terugstuurt. */
|
|
14
|
+
const waitForAuthContext = async () => {
|
|
15
|
+
for (let i = 0; i < 60; i++) {
|
|
16
|
+
const auth = router.options.context?.auth;
|
|
17
|
+
if (auth?.isAuthenticated)
|
|
18
|
+
return true;
|
|
19
|
+
await new Promise((r) => setTimeout(r, 25));
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
};
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
// React 19 mount kan in dev dubbel vuren; een code is eenmalig bruikbaar.
|
|
25
|
+
if (started.current)
|
|
26
|
+
return;
|
|
27
|
+
started.current = true;
|
|
28
|
+
(async () => {
|
|
29
|
+
const code = new URLSearchParams(window.location.search).get("code");
|
|
30
|
+
if (!code) {
|
|
31
|
+
setFailed(true);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// Code direct uit de adresbalk halen: hij mag niet in de geschiedenis
|
|
35
|
+
// of in een referer blijven staan.
|
|
36
|
+
const cleanUrl = window.location.pathname + window.location.hash;
|
|
37
|
+
window.history.replaceState(null, "", cleanUrl);
|
|
38
|
+
try {
|
|
39
|
+
// Eerst een eventuele bestaande sessie beëindigen, anders belandt
|
|
40
|
+
// iemand in de omgeving van de vorige gebruiker. Scope 'local':
|
|
41
|
+
// alleen de lokale opslag wissen, geen server-side sessies intrekken.
|
|
42
|
+
// De standaardscope ('global') zou óók de net aangemaakte
|
|
43
|
+
// handover-sessie server-side ongeldig maken (session_not_found).
|
|
44
|
+
const { data } = await supabase.auth.getSession();
|
|
45
|
+
if (data.session)
|
|
46
|
+
await supabase.auth.signOut({ scope: "local" });
|
|
47
|
+
const result = await exchangeHandover({ data: { code } });
|
|
48
|
+
const { error } = await supabase.auth.setSession({
|
|
49
|
+
access_token: result.accessToken,
|
|
50
|
+
refresh_token: result.refreshToken,
|
|
51
|
+
});
|
|
52
|
+
if (error) {
|
|
53
|
+
setFailed(true);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
await waitForAuthContext();
|
|
57
|
+
// Nooit window.location.href: een volledige pagina-load laat de
|
|
58
|
+
// server (zonder sessie) eerst naar /login redirecten.
|
|
59
|
+
await router.navigate({ to: redirectTo, replace: true });
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
setFailed(true);
|
|
63
|
+
}
|
|
64
|
+
})();
|
|
65
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
66
|
+
}, []);
|
|
67
|
+
if (failed) {
|
|
68
|
+
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background p-4", children: _jsxs(Card, { className: "w-full max-w-md", children: [_jsxs(CardHeader, { className: "text-center", children: [_jsx(CardTitle, { className: "text-2xl", children: "Inloggen mislukt" }), _jsx(CardDescription, { children: FOUTMELDING })] }), _jsx(CardFooter, { children: _jsx(Button, { className: "w-full", onClick: () => {
|
|
69
|
+
window.location.href = loginPath;
|
|
70
|
+
}, children: "Naar de inlogpagina" }) })] }) }));
|
|
71
|
+
}
|
|
72
|
+
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background p-4", children: _jsx(Card, { className: "w-full max-w-md", children: _jsxs(CardContent, { className: "flex flex-col items-center gap-4 py-10", children: [_jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-primary" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Je wordt aangemeld\u2026" })] }) }) }));
|
|
73
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export type { AuthContext, AuthState, AuthActions, AppRole } from "./auth/useAut
|
|
|
3
3
|
export { supabase } from "./supabase/client";
|
|
4
4
|
export type { Database } from "./supabase/types";
|
|
5
5
|
export { LoginPage } from "./components/layout/LoginPage";
|
|
6
|
+
export { HandoverPage } from "./components/layout/HandoverPage";
|
|
7
|
+
export type { HandoverPageProps } from "./components/layout/HandoverPage";
|
|
6
8
|
export { ResetWachtwoordPage } from "./components/layout/ResetWachtwoordPage";
|
|
7
9
|
export { Header } from "./components/layout/Header";
|
|
8
10
|
export { InstellingenPage } from "./components/layout/InstellingenPage";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/core/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/core/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { useAuth, useAuthState } from "./auth/useAuth";
|
|
|
4
4
|
export { supabase } from "./supabase/client";
|
|
5
5
|
// Layout
|
|
6
6
|
export { LoginPage } from "./components/layout/LoginPage";
|
|
7
|
+
export { HandoverPage } from "./components/layout/HandoverPage";
|
|
7
8
|
export { ResetWachtwoordPage } from "./components/layout/ResetWachtwoordPage";
|
|
8
9
|
export { Header } from "./components/layout/Header";
|
|
9
10
|
export { InstellingenPage } from "./components/layout/InstellingenPage";
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { getProviderToken, listProviderAccounts, revokeProviderAccount } from "./provider-token.js";
|
|
2
2
|
export type { ProviderAccount } from "./provider-token.js";
|
|
3
|
+
export { exchangeHandoverCode, HandoverExchangeError } from "./provider-token.js";
|
|
4
|
+
export type { HandoverSession } from "./provider-token.js";
|
|
3
5
|
export { CentralAuthConfigError, ProviderNotConnectedError, ProviderUpstreamError, CentralAuthUnavailableError, AmbiguousAccountError, } from "./provider-token.js";
|
|
4
6
|
export { requireModulePermission } from "./permissions.server.js";
|
|
5
7
|
export type { PermissionLevel } from "./permissions.server.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACpG,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACpG,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAClF,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { getProviderToken, listProviderAccounts, revokeProviderAccount } from "./provider-token.js";
|
|
2
|
+
export { exchangeHandoverCode, HandoverExchangeError } from "./provider-token.js";
|
|
2
3
|
export { CentralAuthConfigError, ProviderNotConnectedError, ProviderUpstreamError, CentralAuthUnavailableError, AmbiguousAccountError, } from "./provider-token.js";
|
|
3
4
|
// Server-only rechtencheck. Uitsluitend via het "./server" subpath, nooit via
|
|
4
5
|
// de hoofdbarrel.
|
|
@@ -33,4 +33,21 @@ export declare function listProviderAccounts(provider: string, opts?: {
|
|
|
33
33
|
export declare function revokeProviderAccount(provider: string, accountKey: string, opts?: {
|
|
34
34
|
environment?: "staging" | "live";
|
|
35
35
|
}): Promise<void>;
|
|
36
|
+
export declare class HandoverExchangeError extends Error {
|
|
37
|
+
constructor(message: string);
|
|
38
|
+
}
|
|
39
|
+
export interface HandoverSession {
|
|
40
|
+
accessToken: string;
|
|
41
|
+
refreshToken: string;
|
|
42
|
+
/** Kan ongeldig zijn als central geen expires_at meestuurt; alleen informatief. */
|
|
43
|
+
expiresAt: Date;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* POST {CENTRAL_AUTH_URL}/api/session/exchange met body { code }.
|
|
47
|
+
*
|
|
48
|
+
* Fail-closed: elke fout gooit. De code komt NOOIT in een logregel of
|
|
49
|
+
* foutmelding terecht, en het secret verlaat deze module niet.
|
|
50
|
+
* Uitsluitend beschikbaar via het "./server"-subpath.
|
|
51
|
+
*/
|
|
52
|
+
export declare function exchangeHandoverCode(code: string): Promise<HandoverSession>;
|
|
36
53
|
//# sourceMappingURL=provider-token.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-token.d.ts","sourceRoot":"","sources":["../../src/core/server/provider-token.ts"],"names":[],"mappings":"AAAA,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,2BAA4B,SAAQ,KAAK;gBACxC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAOD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"provider-token.d.ts","sourceRoot":"","sources":["../../src/core/server/provider-token.ts"],"names":[],"mappings":"AAAA,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,2BAA4B,SAAQ,KAAK;gBACxC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAOD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAqMD,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAE,CAAC,CA6BnD;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,eAAe,EAAE,CAAC,CA4C5B;AAED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAMD,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAmCjF"}
|
|
@@ -49,10 +49,12 @@ function getCentralAuthConfig() {
|
|
|
49
49
|
}
|
|
50
50
|
return { baseUrl, secret };
|
|
51
51
|
}
|
|
52
|
-
// segment is always one of the
|
|
52
|
+
// segment is always one of the literals above, never caller input —
|
|
53
53
|
// the URL path must never be built from anything a caller supplies.
|
|
54
|
+
// provider === undefined betekent: provider-less endpoint, geen extra segment.
|
|
54
55
|
function buildCentralUrl(baseUrl, segment, provider, query) {
|
|
55
|
-
const
|
|
56
|
+
const path = provider === undefined ? segment : `${segment}/${encodeURIComponent(provider)}`;
|
|
57
|
+
const base = `${baseUrl.replace(/\/+$/, "")}/api/${path}`;
|
|
56
58
|
if (!query)
|
|
57
59
|
return base;
|
|
58
60
|
const qs = new URLSearchParams(query).toString();
|
|
@@ -97,9 +99,13 @@ async function mapCentralError(response, provider, environment, allowAmbiguousAc
|
|
|
97
99
|
}
|
|
98
100
|
throw new CentralAuthUnavailableError(`Central auth unavailable (provider=${provider}, environment=${environment}, status=${response.status}).`);
|
|
99
101
|
}
|
|
100
|
-
async function requestCentral(segment,
|
|
102
|
+
async function requestCentral(segment,
|
|
103
|
+
// undefined bij provider-less endpoints; alleen voor de URL relevant.
|
|
104
|
+
provider, environment, init, allowAmbiguousAccount) {
|
|
101
105
|
const { baseUrl, secret } = getCentralAuthConfig();
|
|
102
106
|
const url = buildCentralUrl(baseUrl, segment, provider, init.query);
|
|
107
|
+
// Label uitsluitend voor logging en foutmeldingen — nooit voor de URL.
|
|
108
|
+
const providerLabel = provider ?? segment;
|
|
103
109
|
const controller = new AbortController();
|
|
104
110
|
let timedOut = false;
|
|
105
111
|
const timeout = setTimeout(() => {
|
|
@@ -119,14 +125,14 @@ async function requestCentral(segment, provider, environment, init, allowAmbiguo
|
|
|
119
125
|
});
|
|
120
126
|
}
|
|
121
127
|
catch {
|
|
122
|
-
logAuthFailure(
|
|
123
|
-
throw new CentralAuthUnavailableError(`Central auth request failed (provider=${
|
|
128
|
+
logAuthFailure(providerLabel, environment, timedOut ? "timeout" : "network");
|
|
129
|
+
throw new CentralAuthUnavailableError(`Central auth request failed (provider=${providerLabel}, environment=${environment}, reason=${timedOut ? "timeout" : "network"}).`);
|
|
124
130
|
}
|
|
125
131
|
finally {
|
|
126
132
|
clearTimeout(timeout);
|
|
127
133
|
}
|
|
128
134
|
if (!response.ok) {
|
|
129
|
-
await mapCentralError(response,
|
|
135
|
+
await mapCentralError(response, providerLabel, environment, allowAmbiguousAccount);
|
|
130
136
|
}
|
|
131
137
|
return response;
|
|
132
138
|
}
|
|
@@ -231,3 +237,44 @@ export async function revokeProviderAccount(provider, accountKey, opts) {
|
|
|
231
237
|
cache.delete(key);
|
|
232
238
|
}
|
|
233
239
|
}
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
// Handover: eenmalige code van central-auth inwisselen voor een Supabase-sessie.
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
export class HandoverExchangeError extends Error {
|
|
244
|
+
constructor(message) {
|
|
245
|
+
super(message);
|
|
246
|
+
this.name = "HandoverExchangeError";
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* POST {CENTRAL_AUTH_URL}/api/session/exchange met body { code }.
|
|
251
|
+
*
|
|
252
|
+
* Fail-closed: elke fout gooit. De code komt NOOIT in een logregel of
|
|
253
|
+
* foutmelding terecht, en het secret verlaat deze module niet.
|
|
254
|
+
* Uitsluitend beschikbaar via het "./server"-subpath.
|
|
255
|
+
*/
|
|
256
|
+
export async function exchangeHandoverCode(code) {
|
|
257
|
+
if (typeof code !== "string" || code.trim() === "") {
|
|
258
|
+
throw new HandoverExchangeError("Handover code is missing.");
|
|
259
|
+
}
|
|
260
|
+
const response = await requestCentral("session/exchange",
|
|
261
|
+
/* provider */ undefined, "live", { method: "POST", body: { code } },
|
|
262
|
+
/* allowAmbiguousAccount */ false);
|
|
263
|
+
let body;
|
|
264
|
+
try {
|
|
265
|
+
body = (await response.json());
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
logAuthFailure("session/exchange", "live", response.status);
|
|
269
|
+
throw new CentralAuthUnavailableError(`Central auth returned an unparseable response (endpoint=session/exchange, status=${response.status}).`);
|
|
270
|
+
}
|
|
271
|
+
if (typeof body.access_token !== "string" || typeof body.refresh_token !== "string") {
|
|
272
|
+
logAuthFailure("session/exchange", "live", response.status);
|
|
273
|
+
throw new HandoverExchangeError(`Central auth returned an incomplete session (endpoint=session/exchange, status=${response.status}).`);
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
accessToken: body.access_token,
|
|
277
|
+
refreshToken: body.refresh_token,
|
|
278
|
+
expiresAt: new Date(typeof body.expires_at === "string" ? body.expires_at : Date.now()),
|
|
279
|
+
};
|
|
280
|
+
}
|