Cookies not available in other Route

r.get("/login/:userId", async (c): Promise<Response> => {
const redirectUri = `${c.env.WORKER_BASE_URL}/callback`;

setCookie(c, "userId", c.req.param("userId"), {
secure: true,
sameSite: "None",
httpOnly: true,
domain: c.env.WORKER_BASE_URL,
});

console.log(getCookie(c, "userId"));

const spotifyAuthUrl =
`https://accounts.spotify.com/authorize?` +
`response_type=code&client_id=${c.env.SPOTIFY_CLIENT_ID}` +
`&scope=playlist-modify-public` +
`&redirect_uri=${redirectUri}`;

return Response.redirect(spotifyAuthUrl, 302);
});

router.get("/callback", async (c): Promise<Response> => {
const { env } = c;
const request = c.req;
const url = new URL(request.url);
const code = url.searchParams.get("code");
if (!code) {
return new Response("No code found", { status: 400 });
}

const userId = getCookie(c, "userId");

if (!userId) {
return new Response("No userId found", { status: 400 });
}

// set auth code to userId
await env.TUNE_STORE.put(userId, code);

console.log(code);

return new Response("Authorized");
});
r.get("/login/:userId", async (c): Promise<Response> => {
const redirectUri = `${c.env.WORKER_BASE_URL}/callback`;

setCookie(c, "userId", c.req.param("userId"), {
secure: true,
sameSite: "None",
httpOnly: true,
domain: c.env.WORKER_BASE_URL,
});

console.log(getCookie(c, "userId"));

const spotifyAuthUrl =
`https://accounts.spotify.com/authorize?` +
`response_type=code&client_id=${c.env.SPOTIFY_CLIENT_ID}` +
`&scope=playlist-modify-public` +
`&redirect_uri=${redirectUri}`;

return Response.redirect(spotifyAuthUrl, 302);
});

router.get("/callback", async (c): Promise<Response> => {
const { env } = c;
const request = c.req;
const url = new URL(request.url);
const code = url.searchParams.get("code");
if (!code) {
return new Response("No code found", { status: 400 });
}

const userId = getCookie(c, "userId");

if (!userId) {
return new Response("No userId found", { status: 400 });
}

// set auth code to userId
await env.TUNE_STORE.put(userId, code);

console.log(code);

return new Response("Authorized");
});
The Cookies are available in /login but not in /callback
11 Replies
boots
boots5mo ago
just off the cuff — my impression is that since you're redirecting the response from /login/:userId, the set-cookie header won't actually be sent. which would explain why you don't have the cookie in /callback it would be better to pass the userId param as part of the redirectUI, that way you can parse it from the url in /callback also most authorization providers will document a way to pass state in your auth url, the spotify docs might tell you how to do something like that
InvalidJoker
InvalidJokerOP5mo ago
sadly spotify doesnt allow to pass state everytime it says invalid redirect uri
boots
boots5mo ago
hmmmm even if you add it as a queryparam in the redirectUri?
InvalidJoker
InvalidJokerOP5mo ago
oh whait I found something &redirect_uri=${redirectUri} + &state=${c.req.param("userId")}; I need to do this
boots
boots5mo ago
yes
InvalidJoker
InvalidJokerOP5mo ago
&state is the solution
InvalidJoker
InvalidJokerOP5mo ago
ty very much
boots
boots5mo ago
you see this pretty often in oauth flows of course!! good luck also depending on your oauth flow there are some interesting patterns you can do with that state param. (you can use it to reference a record in the database that understands the "state" of the user's authorization flow, i.e., pending or granted or rejected, and update it accordingly depending on the response from spotify)
goofysystem
goofysystem5mo ago
Hey running into this issue as well. Based on this you should be able to pass cookies around during OAuth flow: https://github.com/lukesthl/expo-lucia-auth-example/blob/b5d664af7f54d080a56d67be249d3be3c1f5e265/apps/api/src/controller/auth/auth.controller.ts#L95 I have implemented something similar as above on Hono to run into the same issue of cookies being dropped when redirecting to callback from the provider authorization page. What is interesting is I have the same oauth flow that uses cookies on sveltekit that still works.
GitHub
expo-lucia-auth-example/apps/api/src/controller/auth/auth.controlle...
lucia-auth example built with expo, hono, drizzle (cloudflare d1) and tamagui - lukesthl/expo-lucia-auth-example
goofysystem
goofysystem5mo ago
ok in my case it was mismatch in host. My client(mobile app) was making a request to 127.0.0.1:8787 when getting the authorization url and setting the cookies. However, c.redirect sets the host as localhost:8787 and loses the cookies set for 127.0.0.1:8787. So cookies should work. I recommend logging the raw headers per request to see if anything is odd. Also I set the sameSite property as "Lax"
Want results from more Discord servers?
Add your server