spotify: manual 302 for external redirects in /api/spotify/connect (kit refuses redirect() to external origins)
Some checks failed
Deploy production / deploy (push) Has been cancelled

This commit is contained in:
2026-10-24 16:12:10 +00:00
parent 4738f10ad1
commit 3903317a59

View File

@@ -1,5 +1,5 @@
import { SPOTIFY_CLIENT_ID } from '$app/env/private';
import { error, redirect } from '@sveltejs/kit';
import { error } from '@sveltejs/kit';
import { requireOwner } from '#lib/server/owner.js';
import {
authorizeUrl,
@@ -9,13 +9,18 @@ import {
} from '#lib/server/music/oauth.js';
import type { RequestHandler } from './$types';
// SvelteKit refuses redirect() to external origins; build the 302 by hand.
// Cookies set via event.cookies are still attached to this Response.
const externalRedirect = (location: string) =>
new Response(null, { status: 302, headers: { location, 'cache-control': 'no-store' } });
// Owner only: start the Spotify Authorization Code flow for the listening tracker.
export const GET: RequestHandler = (event) => {
requireOwner(event);
const { url, cookies } = event;
// The state cookie must be set on the host Spotify redirects back to.
if (url.hostname === 'www.stanrunge.dev')
redirect(302, 'https://stanrunge.dev/api/spotify/connect');
return externalRedirect('https://stanrunge.dev/api/spotify/connect');
if (!SPOTIFY_CLIENT_ID) error(503, 'Spotify is not configured on this server.');
const state = Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString('base64url');
cookies.set(STATE_COOKIE, state, {
@@ -25,5 +30,5 @@ export const GET: RequestHandler = (event) => {
sameSite: 'lax',
maxAge: 600
});
redirect(302, authorizeUrl(SPOTIFY_CLIENT_ID, `${publicOrigin(url)}${CALLBACK_PATH}`, state));
return externalRedirect(authorizeUrl(SPOTIFY_CLIENT_ID, `${publicOrigin(url)}${CALLBACK_PATH}`, state));
};