@multiplatform.one/auth 7.16.0 → 7.18.0
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/cjs/index.cjs +22 -8
- package/dist/cjs/index.native.js +24 -8
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/esm/index.mjs +23 -9
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +25 -9
- package/dist/esm/index.native.js.map +1 -1
- package/dist/jsx/index.js +23 -9
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +23 -9
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +24 -8
- package/dist/jsx/index.native.js.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +30 -17
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/auth",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.18.0",
|
|
4
4
|
"description": "Better Auth helpers for multiplatform.one apps with Keycloak",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auth",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@better-auth/expo": "^1.6.9",
|
|
51
|
-
"@multiplatform.one/config": "7.
|
|
52
|
-
"@multiplatform.one/test-utils": "7.
|
|
51
|
+
"@multiplatform.one/config": "7.18.0",
|
|
52
|
+
"@multiplatform.one/test-utils": "7.18.0",
|
|
53
53
|
"@tamagui/build": "2.7.6",
|
|
54
54
|
"@vitest/coverage-v8": "^4.1.5",
|
|
55
55
|
"better-auth": "^1.6.9",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"@better-auth/expo": "^1.4.0",
|
|
61
|
-
"@multiplatform.one/wallet": "^7.
|
|
61
|
+
"@multiplatform.one/wallet": "^7.18.0",
|
|
62
62
|
"better-auth": "^1.4.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependenciesMeta": {
|
package/src/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
APIError,
|
|
22
22
|
createAuthEndpoint,
|
|
23
23
|
createAuthMiddleware,
|
|
24
|
+
getAccessToken,
|
|
24
25
|
getSessionFromCtx,
|
|
25
26
|
isAPIError,
|
|
26
27
|
} from "better-auth/api";
|
|
@@ -51,13 +52,14 @@ export type { AccessTokenFailureKind, RetryAttemptResult } from "./accessTokenRe
|
|
|
51
52
|
const requestOriginStorage = new AsyncLocalStorage<string>();
|
|
52
53
|
|
|
53
54
|
/**
|
|
54
|
-
* The visitor origin for
|
|
55
|
+
* The visitor origin for a request from a private-network dev host, else
|
|
56
|
+
* undefined so callers use the configured BASE_URL. The app may sit behind
|
|
55
57
|
* the bench's dev proxy (browser → :8000 → one server :3456), where
|
|
56
58
|
* `req.url` shows the proxy target — so prefer `X-Forwarded-Proto/Host`
|
|
57
59
|
* (the bench proxy sets them for exactly this purpose), then the browser's
|
|
58
|
-
* `Origin` header, then the request URL.
|
|
59
|
-
*
|
|
60
|
-
*
|
|
60
|
+
* `Origin` header, then the request URL. A public host never picks the
|
|
61
|
+
* origin: behind a TLS edge the request URL says http, and its Host is
|
|
62
|
+
* whatever the client sent.
|
|
61
63
|
*/
|
|
62
64
|
function deriveRequestOrigin(req: Request): string | undefined {
|
|
63
65
|
const isDevHost = (host: string) =>
|
|
@@ -69,21 +71,16 @@ function deriveRequestOrigin(req: Request): string | undefined {
|
|
|
69
71
|
return `${proto}://${forwardedHost}`;
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
+
for (const candidate of [req.headers.get("origin"), req.url]) {
|
|
75
|
+
if (!candidate) continue;
|
|
74
76
|
try {
|
|
75
|
-
const url = new URL(
|
|
77
|
+
const url = new URL(candidate);
|
|
76
78
|
if (isDevHost(url.host)) return url.origin;
|
|
77
79
|
} catch {
|
|
78
|
-
//
|
|
80
|
+
// not a URL; try the next candidate
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
return new URL(req.url).origin;
|
|
84
|
-
} catch {
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
83
|
+
return undefined;
|
|
87
84
|
}
|
|
88
85
|
|
|
89
86
|
// ─── Types ──────────────────────────────────────────────────────────
|
|
@@ -160,12 +157,21 @@ interface KeycloakSsoPluginOptions {
|
|
|
160
157
|
clientSecret: string;
|
|
161
158
|
/** Backchannel issuer (server-to-server), e.g. http://localhost:8080/auth/realms/myrealm */
|
|
162
159
|
issuer: string;
|
|
163
|
-
/**
|
|
160
|
+
/** Public app origin, used for every visitor that is not on a dev host. */
|
|
164
161
|
baseUrl: string;
|
|
165
162
|
/** Browser-facing Keycloak base for a visitor origin (proxy-aware). */
|
|
166
163
|
publicKeycloakBaseFor: (requestOrigin?: string) => string | undefined;
|
|
167
164
|
}
|
|
168
165
|
|
|
166
|
+
const accessTokenBodySchema = getAccessToken.options.body as
|
|
167
|
+
| { safeParse?: (value: unknown) => { success: boolean } }
|
|
168
|
+
| undefined;
|
|
169
|
+
|
|
170
|
+
/** Whether the installed Better Auth validates this `/get-access-token` body. */
|
|
171
|
+
function acceptsAccessTokenBody(body: unknown): boolean {
|
|
172
|
+
return accessTokenBodySchema?.safeParse?.(body).success !== false;
|
|
173
|
+
}
|
|
174
|
+
|
|
169
175
|
/** Minimal shape of a stored OAuth account used by the SSO plugin. */
|
|
170
176
|
interface KeycloakAccountLike {
|
|
171
177
|
providerId?: string;
|
|
@@ -317,10 +323,17 @@ function createKeycloakSsoPlugin(options: KeycloakSsoPluginOptions) {
|
|
|
317
323
|
// so it is a 200 with no token, as /get-session answers, instead
|
|
318
324
|
// of a 4xx the browser logs. Runs before body validation, so the
|
|
319
325
|
// client's body-shape negotiation never 400s for a visitor either.
|
|
326
|
+
// A signed-in >=1.7 body (`useAccountCookie`) on a server whose
|
|
327
|
+
// schema still demands `providerId` gets the Keycloak provider
|
|
328
|
+
// added, so the negotiation never 400s once signed in either.
|
|
320
329
|
matcher: (ctx) => ctx.path === "/get-access-token",
|
|
321
330
|
handler: createAuthMiddleware(async (ctx) => {
|
|
322
331
|
const session = await getSessionFromCtx(ctx).catch(() => null);
|
|
323
332
|
if (!session) return ctx.json(null);
|
|
333
|
+
const body = ctx.body as { useAccountCookie?: unknown } | undefined;
|
|
334
|
+
if (body?.useAccountCookie !== true || acceptsAccessTokenBody(body)) return;
|
|
335
|
+
const legacy = { ...body, providerId: "keycloak" };
|
|
336
|
+
if (acceptsAccessTokenBody(legacy)) return { context: { body: legacy } };
|
|
324
337
|
}),
|
|
325
338
|
},
|
|
326
339
|
],
|
|
@@ -649,8 +662,8 @@ export type AuthInstance = ReturnType<typeof createAuth>;
|
|
|
649
662
|
* ```
|
|
650
663
|
*/
|
|
651
664
|
export function createAuthRouteHandler(auth: AuthLike) {
|
|
652
|
-
//
|
|
653
|
-
// visitor origin (proxy-aware; see deriveRequestOrigin), so the dev
|
|
665
|
+
// An auth request from a dev host runs inside an AsyncLocalStorage scope
|
|
666
|
+
// carrying its visitor origin (proxy-aware; see deriveRequestOrigin), so the dev
|
|
654
667
|
// redirect-URI/authorization-URL getters (createAuth) can follow the host
|
|
655
668
|
// the visitor is actually on (survives the awaits inside better-auth).
|
|
656
669
|
const handler = (req: Request) => {
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,UAAU,EAAsB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,UAAU,EAAsB,MAAM,aAAa,CAAC;AAe7D,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AA+CvF,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qCAAqC;IACrC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACtD;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;CACzD;AAED,kEAAkE;AAClE,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAC5D,GAAG,EAAE;QACH,UAAU,EAAE,CAAC,IAAI,EAAE;YAAE,OAAO,EAAE,OAAO,CAAA;SAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAC9D,CAAC;CACH;AA4SD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB;;;;;;;;;;;;;;;;;;;GAmNzD;AAED,yCAAyC;AACzC,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAIzD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ;wBAK7B,OAAO;yBAAP,OAAO;EAK9B;AAID;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ;sBAOlB,OAAO;sBALP,OAAO;EAcvC"}
|