app.use("/api/auth/*", async (c, next) => { const ExpoOrigin = c.req.header("expo-origin"); if (ExpoOrigin) { const originalRequest = c.req.raw; // Create new headers const newHeaders = new Headers(originalRequest.headers); newHeaders.set("origin", ExpoOrigin); // Create a new Request with updated headers const newRequest = new Request(originalRequest, { headers: newHeaders, }); // Replace the request in context c.req.raw = newRequest; } await next(); }); app.use( "/*", cors({ origin: (origin) => { if (!origin || origin === "null") return "*"; const allowedOrigins = process.env.NODE_ENV === "production" ? DEFAULT_ALLOWED_ORIGINS : ["*"]; if (process.env.NODE_ENV !== "production") return origin; if (typeof origin === "string" && origin.startsWith("lately://")) return origin; return allowedOrigins.includes(origin) ? origin : ""; }, allowMethods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], allowHeaders: [ "Content-Type", "Authorization", "Cookie", "x-client-type", // Expo-specific headers — must be allowed so they are not stripped/blocked "expo-origin", "expo-go-origin", "User-Agent", // QStash webhook headers "upstash-signature", "upstash-message-id", "upstash-retry-count", "X-Qstash-Signature-Source" ], credentials: true, }), ); app.use("*", errorHandler); app.all("/api/auth/*", (c) => auth.handler(c.req.raw)); import { expoClient } from "@better-auth/expo/client"; import { createAuthClient } from "better-auth/react"; import { emailOTPClient, usernameClient, adminClient } from "better-auth/client/plugins"; import * as SecureStore from "expo-secure-store"; import { getBaseUrl } from "./getBaseUrl"; export const authClient = createAuthClient({ baseURL: getBaseUrl(), plugins: [ expoClient({ scheme: "lately", storagePrefix: "lately-app", storage: SecureStore, }), emailOTPClient(), usernameClient(), adminClient() ], fetchOptions: { headers: { "expo-origin": "lately://" } } }); scheme: 'lately', --> OPTIONS /api/auth/sign-in/social 204 1ms <-- POST /api/auth/sign-in/social ==> auth response Set-Cookie: __Secure-lately_auth.state=Yza_oEK-Tbagjufp3wqI5WiNUtWKAAbF.CzN%2FZDAxFinyauMUCOkU6zwKTIeqR48jYdWPY1Ou55Y%3D; Max-Age=300000; Path=/; HttpOnly; Secure; SameSite=None --> POST /api/auth/sign-in/social 200 145ms <-- GET /api/auth/callback/google?state=Yza_oEK-Tbagjufp3wqI5WiNUtWKAAbF&code=4%2F0ATX87lN5Vq4pr56nF-pNmhQZeslmCEXom6bq7aY2Iu-Z9ksB5pyf1uSQF40ItaW03b3fmg&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=1&prompt=consent ==> CALLBACK incoming Cookie: __Secure-lately_auth.state=Yza_oEK-Tbagjufp3wqI5WiNUtWKAAbF.CzN%2FZDAxFinyauMUCOkU6zwKTIeqR48jYdWPY1Ou55Y%3D ==> CALLBACK incoming state param: Yza_oEK-Tbagjufp3wqI5WiNUtWKAAbF ==> CALLBACK request url: http://lately-w2yl.onrender.com/api/auth/callback/google?state=Yza_oEK-Tbagjufp3wqI5WiNUtWKAAbF&code=4%2F0ATX87lN5Vq4pr56nF-pNmhQZeslmCEXom6bq7aY2Iu-Z9ksB5pyf1uSQF40ItaW03b3fmg&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=1&prompt=consent [GET] route/api/auth/callback/google?state=Yza_oEK-Tbagjufp3wqI5WiNUtWKAAbF&code=4%2F0ATX87lN5Vq4pr56nF-pNmhQZeslmCEXom6bq7aY2Iu-Z9ksB5pyf1uSQF40ItaW03b3fmg&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=1&prompt=consentclientIP="106.51.75.67" requestID="4bb5b934-baba-4125" responseTimeMS=1011 responseBytes=561 userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36" ==> auth response Set-Cookie: __Secure-lately_auth.state=; Max-Age=0; Secure, __Secure-lately_auth.session_token=SbwS5ZLbtT6STGryKVGlP1atjdPgM4k5.iOSAb6M%2BllonRKBLo4yyhN4Z3PkAHM5pCSzeCtsYb9Q%3D; Max-Age=604800; Path=/; HttpOnly; Secure; SameSite=None --> GET /api/auth/callback/google?state=Yza_oEK-Tbagjufp3wqI5WiNUtWKAAbF&code=4%2F0ATX87lN5Vq4pr56nF-pNmhQZeslmCEXom6bq7aY2Iu-Z9ksB5pyf1uSQF40ItaW03b3fmg&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=1&prompt=consent 302 1s