@multiplatform.one/auth 7.7.2

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.
@@ -0,0 +1,336 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { betterAuth, matchesHostPattern } from "better-auth";
3
+ import { APIError, createAuthEndpoint, createAuthMiddleware, getSessionFromCtx, isAPIError } from "better-auth/api";
4
+ import { deleteSessionCookie, getAccountCookie } from "better-auth/cookies";
5
+ import { genericOAuth, keycloak } from "better-auth/plugins";
6
+ import { expo } from "@better-auth/expo";
7
+ import { FAILED_TO_GET_ACCESS_TOKEN, TOKEN_REFRESH_UNAVAILABLE } from "./accessTokenRefresh.mjs";
8
+ import { ACCESS_TOKEN_RETRY_DELAYS_MS, FAILED_TO_GET_ACCESS_TOKEN as FAILED_TO_GET_ACCESS_TOKEN2, TOKEN_REFRESH_UNAVAILABLE as TOKEN_REFRESH_UNAVAILABLE2, classifyAccessTokenResponse, retryWhileTransient, watchDocumentVisible } from "./accessTokenRefresh.mjs";
9
+ const requestOriginStorage = new AsyncLocalStorage();
10
+ function deriveRequestOrigin(req) {
11
+ const isDevHost = host => DEV_LAN_HOST_PATTERNS.some(pattern => matchesHostPattern(host, pattern));
12
+ const forwardedHost = req.headers.get("x-forwarded-host");
13
+ if (forwardedHost && isDevHost(forwardedHost)) {
14
+ const proto = req.headers.get("x-forwarded-proto") === "https" ? "https" : "http";
15
+ return `${proto}://${forwardedHost}`;
16
+ }
17
+ const originHeader = req.headers.get("origin");
18
+ if (originHeader) {
19
+ try {
20
+ const url = new URL(originHeader);
21
+ if (isDevHost(url.host)) return url.origin;
22
+ } catch {}
23
+ }
24
+ try {
25
+ return new URL(req.url).origin;
26
+ } catch {
27
+ return void 0;
28
+ }
29
+ }
30
+ const DEV_LAN_HOST_PATTERNS = ["localhost", "localhost:*", "127.0.0.1", "127.0.0.1:*", "10.*", "192.168.*", "172.*", "*.local", "*.local:*"];
31
+ function createKeycloakSsoPlugin(options) {
32
+ const {
33
+ realm,
34
+ clientId,
35
+ clientSecret,
36
+ issuer,
37
+ baseUrl,
38
+ publicKeycloakBaseFor
39
+ } = options;
40
+ const tokenEndpoint = `${issuer}/protocol/openid-connect/token`;
41
+ const resolveVisitorOrigin = request => requestOriginStorage.getStore() ?? (request ? deriveRequestOrigin(request) : void 0);
42
+ const isRefreshDefinitivelyDead = async refreshToken => {
43
+ try {
44
+ const res = await fetch(tokenEndpoint, {
45
+ method: "POST",
46
+ headers: {
47
+ "content-type": "application/x-www-form-urlencoded"
48
+ },
49
+ body: new URLSearchParams({
50
+ grant_type: "refresh_token",
51
+ refresh_token: refreshToken,
52
+ client_id: clientId,
53
+ client_secret: clientSecret
54
+ }),
55
+ signal: AbortSignal.timeout(5e3)
56
+ });
57
+ if (res.ok) return false;
58
+ if (res.status !== 400 && res.status !== 401) return false;
59
+ const body = await res.json().catch(() => null);
60
+ return body?.error === "invalid_grant" || body?.error === "invalid_token";
61
+ } catch {
62
+ return false;
63
+ }
64
+ };
65
+ const signOutSso = createAuthEndpoint("/sign-out/sso", {
66
+ method: "GET"
67
+ }, async ctx => {
68
+ const visitorOrigin = resolveVisitorOrigin(ctx.request) ?? baseUrl;
69
+ const searchParams = ctx.request ? new URL(ctx.request.url).searchParams : void 0;
70
+ const rawCallback = searchParams?.get("callbackURL") ?? null;
71
+ const jsonMode = searchParams?.get("mode") === "json";
72
+ const answer = (url, redirect) => {
73
+ if (jsonMode) return ctx.json({
74
+ redirect,
75
+ url
76
+ });
77
+ throw ctx.redirect(url);
78
+ };
79
+ const callbackURL = rawCallback || "/";
80
+ const postLogoutRedirect = callbackURL.startsWith("/") ? `${visitorOrigin}${callbackURL}` : callbackURL;
81
+ let idTokenHint;
82
+ const sessionToken = await ctx.getSignedCookie(ctx.context.authCookies.sessionToken.name, ctx.context.secret);
83
+ const session = await getSessionFromCtx(ctx).catch(() => null);
84
+ if (session) {
85
+ const accounts = await ctx.context.internalAdapter.findAccounts(session.user.id).catch(() => []);
86
+ idTokenHint = accounts.find(account => account.providerId === "keycloak")?.idToken ?? void 0;
87
+ }
88
+ if (!idTokenHint) {
89
+ const accountCookie = await getAccountCookie(ctx).catch(() => null);
90
+ if (accountCookie?.providerId === "keycloak" && accountCookie.idToken) {
91
+ idTokenHint = accountCookie.idToken;
92
+ }
93
+ }
94
+ if (sessionToken) {
95
+ await ctx.context.internalAdapter.deleteSession(sessionToken).catch(error => {
96
+ ctx.context.logger.error("Failed to delete session during SSO sign-out", error);
97
+ });
98
+ }
99
+ deleteSessionCookie(ctx);
100
+ const keycloakBase = publicKeycloakBaseFor(visitorOrigin);
101
+ if (!keycloakBase || !session && !idTokenHint && !sessionToken) {
102
+ return answer(postLogoutRedirect, false);
103
+ }
104
+ const endSession = new URL(`${keycloakBase}/realms/${realm}/protocol/openid-connect/logout`);
105
+ endSession.searchParams.set("post_logout_redirect_uri", postLogoutRedirect);
106
+ endSession.searchParams.set("client_id", clientId);
107
+ if (idTokenHint) endSession.searchParams.set("id_token_hint", idTokenHint);
108
+ return answer(endSession.toString(), true);
109
+ });
110
+ return {
111
+ id: "keycloak-sso",
112
+ endpoints: {
113
+ signOutSso
114
+ },
115
+ hooks: {
116
+ after: [{
117
+ matcher: ctx => ctx.path === "/get-access-token",
118
+ handler: createAuthMiddleware(async ctx => {
119
+ const returned = ctx.context.returned;
120
+ if (!isAPIError(returned)) return;
121
+ const body = returned.body;
122
+ if (body?.code !== FAILED_TO_GET_ACCESS_TOKEN) return;
123
+ const providerId = ctx.body?.providerId;
124
+ if (providerId && providerId !== "keycloak") return;
125
+ const session = await getSessionFromCtx(ctx).catch(() => null);
126
+ if (!session) return;
127
+ const accounts = await ctx.context.internalAdapter.findAccounts(session.user.id).catch(() => []);
128
+ let refreshToken = accounts.find(account => account.providerId === "keycloak")?.refreshToken;
129
+ if (!refreshToken) {
130
+ const accountCookie = await getAccountCookie(ctx).catch(() => null);
131
+ if (accountCookie?.providerId === "keycloak") {
132
+ refreshToken = accountCookie.refreshToken;
133
+ }
134
+ }
135
+ const definitive = refreshToken ? await isRefreshDefinitivelyDead(refreshToken) : true;
136
+ if (!definitive) {
137
+ return new APIError("INTERNAL_SERVER_ERROR", {
138
+ message: "Keycloak token refresh temporarily unavailable",
139
+ code: TOKEN_REFRESH_UNAVAILABLE
140
+ });
141
+ }
142
+ ctx.context.logger.warn("Keycloak refresh token is dead (invalid_grant); revoking the stale Better Auth session");
143
+ const sessionToken = await ctx.getSignedCookie(ctx.context.authCookies.sessionToken.name, ctx.context.secret);
144
+ if (sessionToken) {
145
+ await ctx.context.internalAdapter.deleteSession(sessionToken).catch(error => {
146
+ ctx.context.logger.error("Failed to delete stale session", error);
147
+ });
148
+ }
149
+ deleteSessionCookie(ctx);
150
+ const headers = new Headers();
151
+ const accumulated = ctx.responseHeaders;
152
+ accumulated?.getSetCookie().forEach(cookie => {
153
+ headers.append("set-cookie", cookie);
154
+ });
155
+ return new APIError("BAD_REQUEST", {
156
+ message: body?.message || "Failed to get a valid access token",
157
+ code: FAILED_TO_GET_ACCESS_TOKEN
158
+ }, headers);
159
+ })
160
+ }]
161
+ }
162
+ };
163
+ }
164
+ function createAuth(options = {}) {
165
+ const baseUrl = options.baseUrl || process.env.BASE_URL || `http://localhost:${process.env.ONE_PORT || "3000"}`;
166
+ const isProduction = process.env.NODE_ENV === "production";
167
+ const keycloakBaseUrl = options.keycloak?.baseUrl || process.env.KEYCLOAK_BACKCHANNEL_URL || `${baseUrl}/auth`;
168
+ const keycloakRealm = options.keycloak?.realm || process.env.KEYCLOAK_REALM || "master";
169
+ const issuer = `${keycloakBaseUrl}/realms/${keycloakRealm}`;
170
+ const keycloakClientId = options.keycloak?.clientId || process.env.KEYCLOAK_CLIENT_ID || "";
171
+ const keycloakClientSecret = options.keycloak?.clientSecret || process.env.KEYCLOAK_CLIENT_SECRET || "";
172
+ const expoPlugin = options.enableExpo !== false ? expo() : void 0;
173
+ const basePath = options.basePath || "/api/auth";
174
+ const keycloakProviderConfig = {
175
+ ...keycloak({
176
+ clientId: keycloakClientId,
177
+ clientSecret: keycloakClientSecret,
178
+ issuer
179
+ }),
180
+ // Backchannel token/userinfo: `/get-access-token` refresh keeps these
181
+ // when discovery fails (Keycloak restart), so we don't depend on the
182
+ // well-known document coming up in the same instant as the token
183
+ // endpoint. Browser-facing authorize/issuer stay on the public /auth
184
+ // proxy (getters below).
185
+ tokenUrl: `${issuer}/protocol/openid-connect/token`,
186
+ userInfoUrl: `${issuer}/protocol/openid-connect/userinfo`,
187
+ // Wallet (SIWE-style) users authenticate by signature and have NO email —
188
+ // Keycloak issues them a username = wallet address and no email claim.
189
+ // better-auth's genericOAuth callback hard-rejects a user with no email
190
+ // ("email_is_missing"), so synthesize a stable, unique placeholder from the
191
+ // wallet address / subject. `.wallet` is a non-routable placeholder domain;
192
+ // the address stays the stable identity.
193
+ mapProfileToUser: profile => {
194
+ const handle = profile.preferred_username || profile.sub || profile.id || profile.name;
195
+ const email = profile.email || (handle ? `${handle}@wallet` : void 0);
196
+ return {
197
+ ...profile,
198
+ email,
199
+ emailVerified: profile.email_verified ?? true,
200
+ name: profile.name || handle
201
+ };
202
+ }
203
+ };
204
+ const keycloakPublicPath = (() => {
205
+ try {
206
+ const path = new URL(keycloakBaseUrl).pathname.replace(/\/+$/, "");
207
+ return path && path !== "/" ? path : void 0;
208
+ } catch {
209
+ return void 0;
210
+ }
211
+ })();
212
+ const publicKeycloakBaseFor = requestOrigin => {
213
+ if (!keycloakPublicPath) return keycloakBaseUrl;
214
+ try {
215
+ const url = new URL(baseUrl);
216
+ if (!isProduction && requestOrigin) {
217
+ url.hostname = new URL(requestOrigin).hostname;
218
+ }
219
+ return `${url.origin}${keycloakPublicPath}`;
220
+ } catch {
221
+ return void 0;
222
+ }
223
+ };
224
+ if (!isProduction) {
225
+ Object.defineProperty(keycloakProviderConfig, "redirectURI", {
226
+ enumerable: true,
227
+ get() {
228
+ const origin = requestOriginStorage.getStore();
229
+ return origin ? `${origin}${basePath}/oauth2/callback/keycloak` : void 0;
230
+ }
231
+ });
232
+ const keycloakPublicBase = () => {
233
+ const origin = requestOriginStorage.getStore();
234
+ if (!origin || !keycloakPublicPath) return void 0;
235
+ return publicKeycloakBaseFor(origin);
236
+ };
237
+ if (keycloakPublicPath) {
238
+ Object.defineProperty(keycloakProviderConfig, "authorizationUrl", {
239
+ enumerable: true,
240
+ get() {
241
+ const base = keycloakPublicBase();
242
+ return base ? `${base}/realms/${keycloakRealm}/protocol/openid-connect/auth` : void 0;
243
+ }
244
+ });
245
+ Object.defineProperty(keycloakProviderConfig, "issuer", {
246
+ enumerable: true,
247
+ get() {
248
+ const base = keycloakPublicBase();
249
+ return base ? `${base}/realms/${keycloakRealm}` : void 0;
250
+ }
251
+ });
252
+ }
253
+ }
254
+ const oauthPlugin = genericOAuth({
255
+ config: [keycloakProviderConfig]
256
+ });
257
+ const keycloakSsoPlugin = createKeycloakSsoPlugin({
258
+ realm: keycloakRealm,
259
+ clientId: keycloakClientId,
260
+ clientSecret: keycloakClientSecret,
261
+ issuer,
262
+ baseUrl,
263
+ publicKeycloakBaseFor
264
+ });
265
+ const plugins = [...(expoPlugin ? [expoPlugin] : []), oauthPlugin, keycloakSsoPlugin, ...(options.plugins ?? [])];
266
+ const database = options.database ?? (process.env.DATABASE_URL || void 0);
267
+ return betterAuth({
268
+ basePath,
269
+ // Static on purpose: better-auth's dynamic `baseURL` config (allowedHosts)
270
+ // is not honored by the genericOAuth plugin — it pins redirect URIs at
271
+ // init time, which turned them relative and bounced callbacks to the
272
+ // Keycloak host. Dev multi-host support comes from the per-request
273
+ // redirectURI getter above + the LAN trustedOrigins below instead.
274
+ baseURL: baseUrl,
275
+ ...(database ? {
276
+ database
277
+ } : {}),
278
+ secret: options.secret || process.env.SECRET || "",
279
+ trustedOrigins: options.trustedOrigins || [baseUrl, keycloakBaseUrl,
280
+ // In dev, ONE_PORT may differ from BASE_URL; ensure the dev server origin is trusted.
281
+ ...(process.env.ONE_PORT && !baseUrl.includes(`:${process.env.ONE_PORT}`) ? [`http://localhost:${process.env.ONE_PORT}`] : []), "multiplatform-one://",
282
+ // Expo Go (dev) receives OAuth returns on the exp:// scheme — the app
283
+ // derives its callbackURL via Linking.createURL, which yields
284
+ // exp://<host>:<port>/--/ there. Never trusted in production builds.
285
+ // Dev also trusts private-network origins (see DEV_LAN_HOST_PATTERNS)
286
+ // so sign-in from a phone / the machine's LAN IP is not rejected.
287
+ ...(isProduction ? [] : ["exp://", ...DEV_LAN_HOST_PATTERNS.map(host => `http://${host}`)])],
288
+ session: {
289
+ cookieCache: {
290
+ enabled: true,
291
+ maxAge: options.sessionMaxAge ?? 7 * 24 * 60 * 60,
292
+ strategy: "jwe",
293
+ refreshCache: true
294
+ }
295
+ },
296
+ account: {
297
+ storeStateStrategy: "cookie",
298
+ storeAccountCookie: true
299
+ },
300
+ plugins
301
+ });
302
+ }
303
+ function createAuthRouteHandler(auth) {
304
+ const handler = req => {
305
+ const origin = deriveRequestOrigin(req);
306
+ return origin ? requestOriginStorage.run(origin, () => auth.handler(req)) : auth.handler(req);
307
+ };
308
+ return {
309
+ GET: handler,
310
+ POST: handler
311
+ };
312
+ }
313
+ function createSessionHelpers(auth) {
314
+ async function getSession(req) {
315
+ return auth.api.getSession({
316
+ headers: req.headers
317
+ });
318
+ }
319
+ async function verifyAuth(req) {
320
+ const session = await auth.api.getSession({
321
+ headers: req.headers
322
+ });
323
+ if (!session) {
324
+ throw new Response("Unauthorized", {
325
+ status: 401
326
+ });
327
+ }
328
+ return session;
329
+ }
330
+ return {
331
+ verifyAuth,
332
+ getSession
333
+ };
334
+ }
335
+ export { ACCESS_TOKEN_RETRY_DELAYS_MS, FAILED_TO_GET_ACCESS_TOKEN2 as FAILED_TO_GET_ACCESS_TOKEN, TOKEN_REFRESH_UNAVAILABLE2 as TOKEN_REFRESH_UNAVAILABLE, classifyAccessTokenResponse, createAuth, createAuthRouteHandler, createSessionHelpers, retryWhileTransient, watchDocumentVisible };
336
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["AsyncLocalStorage","betterAuth","matchesHostPattern","APIError","createAuthEndpoint","createAuthMiddleware","getSessionFromCtx","isAPIError","deleteSessionCookie","getAccountCookie","genericOAuth","keycloak","expo","FAILED_TO_GET_ACCESS_TOKEN","TOKEN_REFRESH_UNAVAILABLE","ACCESS_TOKEN_RETRY_DELAYS_MS","FAILED_TO_GET_ACCESS_TOKEN2","TOKEN_REFRESH_UNAVAILABLE2","classifyAccessTokenResponse","retryWhileTransient","watchDocumentVisible","requestOriginStorage","deriveRequestOrigin","req","isDevHost","host","DEV_LAN_HOST_PATTERNS","some","pattern","forwardedHost","headers","get","proto","originHeader","url","URL","origin","createKeycloakSsoPlugin","options","realm","clientId","clientSecret","issuer","baseUrl","publicKeycloakBaseFor","tokenEndpoint","resolveVisitorOrigin","request","getStore","isRefreshDefinitivelyDead","refreshToken","res","fetch","method","body","URLSearchParams","grant_type","refresh_token","client_id","client_secret","signal","AbortSignal","timeout","ok","status","json","catch","error","signOutSso","ctx","visitorOrigin","searchParams","rawCallback","jsonMode","answer","redirect","callbackURL","postLogoutRedirect","startsWith","idTokenHint","sessionToken","getSignedCookie","context","authCookies","name","secret","session","accounts","internalAdapter","findAccounts","user","id","find","account","providerId","idToken","accountCookie","deleteSession","logger","keycloakBase","endSession","set","toString","endpoints","hooks","after","matcher","path","handler","returned","code","definitive","message","warn","Headers","accumulated","responseHeaders","getSetCookie","forEach","cookie","append","createAuth","process","env","BASE_URL","ONE_PORT","isProduction","NODE_ENV","keycloakBaseUrl","KEYCLOAK_BACKCHANNEL_URL","keycloakRealm","KEYCLOAK_REALM","keycloakClientId","KEYCLOAK_CLIENT_ID","keycloakClientSecret","KEYCLOAK_CLIENT_SECRET","expoPlugin","enableExpo","basePath","keycloakProviderConfig","tokenUrl","userInfoUrl","mapProfileToUser","profile","handle","preferred_username","sub","email","emailVerified","email_verified","keycloakPublicPath","pathname","replace","requestOrigin","hostname","Object","defineProperty","enumerable","keycloakPublicBase","base","oauthPlugin","config","keycloakSsoPlugin","plugins","database","DATABASE_URL","baseURL","SECRET","trustedOrigins","includes","map","cookieCache","enabled","maxAge","sessionMaxAge","strategy","refreshCache","storeStateStrategy","storeAccountCookie","createAuthRouteHandler","auth","run","GET","POST","createSessionHelpers","getSession","api","verifyAuth","Response"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}