diff --git a/src/routes/oauth/authorize.tsx b/src/routes/oauth/authorize.tsx index bba904a5..18b08dc3 100644 --- a/src/routes/oauth/authorize.tsx +++ b/src/routes/oauth/authorize.tsx @@ -9,23 +9,23 @@ import { useIsDark } from '~/hooks/useIsDark' import { BrandContextMenu } from '~/components/BrandContextMenu' /** - * Validate redirect URI - must be localhost or HTTPS + * Validate redirect URI - block only HTTP to non-localhost + * Allows: HTTPS, localhost (any protocol), custom schemes (cursor://, vscode://, etc.) * Inlined here to avoid pulling in server-only dependencies */ function validateRedirectUri(uri: string): boolean { try { const url = new URL(uri) - if ( - url.hostname === 'localhost' || - url.hostname === '127.0.0.1' || - url.hostname === '[::1]' - ) { - return true + // Block only HTTP to non-localhost + if (url.protocol === 'http:') { + return ( + url.hostname === 'localhost' || + url.hostname === '127.0.0.1' || + url.hostname === '[::1]' + ) } - if (url.protocol === 'https:') { - return true - } - return false + // Allow everything else: HTTPS, custom schemes + return true } catch { return false } @@ -84,7 +84,7 @@ export const Route = createFileRoute('/oauth/authorize')({ if (!validateRedirectUri(deps.redirect_uri)) { return { error: 'invalid_request', - errorDescription: 'redirect_uri must be localhost or HTTPS', + errorDescription: 'HTTP redirect URIs are only allowed for localhost', } } diff --git a/src/routes/oauth/register.ts b/src/routes/oauth/register.ts index b67eeb7d..43313033 100644 --- a/src/routes/oauth/register.ts +++ b/src/routes/oauth/register.ts @@ -16,7 +16,7 @@ export const Route = createFileRoute('/oauth/register')({ // This is secure because: // 1. Registration only generates deterministic client IDs // 2. No secrets are issued (PKCE public clients) - // 3. Redirect URIs are validated for localhost or HTTPS + // 3. Redirect URIs block insecure HTTP to remote hosts const origin = request.headers.get('Origin') setResponseHeader('Content-Type', 'application/json') setResponseHeader('Access-Control-Allow-Origin', origin || '*') @@ -41,14 +41,14 @@ export const Route = createFileRoute('/oauth/register')({ url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]' - const isHttps = url.protocol === 'https:' - if (!isLocalhost && !isHttps) { + // Block only HTTP to non-localhost (allows custom schemes like cursor://) + if (url.protocol === 'http:' && !isLocalhost) { return new Response( JSON.stringify({ error: 'invalid_redirect_uri', error_description: - 'Redirect URIs must be localhost or HTTPS', + 'HTTP redirect URIs are only allowed for localhost', }), { status: 400 }, )