Proxying request is even more strict

This commit is contained in:
WardPearce
2026-02-14 00:52:31 +13:00
parent b521006ea3
commit db820b3021
5 changed files with 47 additions and 19 deletions
+3 -1
View File
@@ -3,6 +3,7 @@ export type IsOwnBackend = {
internalAuth: boolean;
requireAuth: boolean;
registrationAllowed: boolean;
allowAnyProxy: boolean;
};
export function isOwnBackend(): IsOwnBackend | null {
@@ -12,6 +13,7 @@ export function isOwnBackend(): IsOwnBackend | null {
builtWithBackend: true,
internalAuth: import.meta.env.VITE_INTERNAL_AUTH !== 'false',
requireAuth: import.meta.env.VITE_REQUIRE_AUTH !== 'false',
registrationAllowed: import.meta.env.VITE_REGISTRATION_ALLOWED === 'true'
registrationAllowed: import.meta.env.VITE_REGISTRATION_ALLOWED === 'true',
allowAnyProxy: import.meta.env.VITE_ALLOW_ANY_PROXY === 'true'
};
}
@@ -25,6 +25,7 @@
isAndroidTvStore,
playerState,
playertheatreModeIsActive,
rawSubscriptionKeyStore,
syncPartyPeerStore,
themeColorStore
} from '$lib/store';
@@ -186,6 +187,11 @@
}
function logout() {
if (isOwnBackend()?.internalAuth) {
rawSubscriptionKeyStore.set(undefined);
fetch('/api/user/logout');
}
authStore.set(null);
clearCaches();
goto(resolve('/', {}));
@@ -3,6 +3,7 @@ import type { IGetChallengeResponse } from 'youtubei.js';
import BG, { buildURL, GOOG_API_KEY, USER_AGENT, type WebPoSignalOutput } from 'bgutils-js';
import { error } from '@sveltejs/kit';
import z from 'zod';
import { isOwnBackend } from '$lib/shared/index.js';
const zPoTokenGenSchema = z.object({
requestKey: z.string(),
@@ -10,7 +11,11 @@ const zPoTokenGenSchema = z.object({
challenge: z.record(z.any(), z.any())
});
export async function POST({ request }) {
export async function POST({ request, locals }) {
if (isOwnBackend()?.requireAuth && !locals.userId) {
throw error(401);
}
const data = zPoTokenGenSchema.safeParse(await request.json());
if (!data.success) {
@@ -1,6 +1,7 @@
import { isOwnBackend } from '$lib/shared';
import psl from 'psl';
import { env } from '$env/dynamic/private';
import { error } from '@sveltejs/kit';
const allowedDomains: string[] = [
'youtube.com',
@@ -27,26 +28,40 @@ dynamicAllowDomains.forEach((domain) => {
}
});
async function proxyRequest(request: Request, urlToProxy: string): Promise<Response> {
async function proxyRequest(
request: Request,
urlToProxy: string,
userId: string | undefined = undefined
): Promise<Response> {
const backendRestrictions = isOwnBackend();
if (!backendRestrictions) {
// Shouldn't be possible.
return new Response('How did you get here?', { status: 400 });
throw error(400, 'How did you get here?');
}
if (backendRestrictions.requireAuth) {
return new Response('Auth required', { status: 401 });
if (backendRestrictions.requireAuth && !userId) {
throw error(401, 'Auth required');
}
let urlToProxyObj: URL;
try {
urlToProxyObj = new URL(decodeURIComponent(urlToProxy));
} catch {
return new Response('Invalid URL', { status: 400 });
throw error(400, 'Invalid URL');
}
if (!allowedDomains.includes(psl.parse(urlToProxyObj.host).domain)) {
return new Response('Invalid URL', { status: 400 });
// allowAnyProxy allows a instance owner to bypass the whitelist.
// BUT is extremely strict.
// AND I still don't recommend this.
if (
!backendRestrictions.allowAnyProxy ||
!backendRestrictions.requireAuth ||
backendRestrictions.registrationAllowed ||
!userId
) {
throw error(400, 'Invalid URL');
}
}
if (urlToProxyObj.pathname.includes('v1/player')) {
@@ -84,21 +99,21 @@ async function proxyRequest(request: Request, urlToProxy: string): Promise<Respo
});
}
export async function GET({ request, params }) {
return await proxyRequest(request, params.urlToProxy);
export async function GET({ request, params, locals }) {
return await proxyRequest(request, params.urlToProxy, locals.userId);
}
export async function PATCH({ request, params }) {
return await proxyRequest(request, params.urlToProxy);
export async function PATCH({ request, params, locals }) {
return await proxyRequest(request, params.urlToProxy, locals.userId);
}
export async function DELETE({ request, params }) {
return await proxyRequest(request, params.urlToProxy);
export async function DELETE({ request, params, locals }) {
return await proxyRequest(request, params.urlToProxy, locals.userId);
}
export async function PUT({ request, params }) {
return await proxyRequest(request, params.urlToProxy);
export async function PUT({ request, params, locals }) {
return await proxyRequest(request, params.urlToProxy, locals.userId);
}
export async function POST({ request, params }) {
return await proxyRequest(request, params.urlToProxy);
export async function POST({ request, params, locals }) {
return await proxyRequest(request, params.urlToProxy, locals.userId);
}
@@ -23,7 +23,7 @@ export async function POST({ request, cookies }) {
cookies.set('userid', sign(userModel.id, env.COOKIE_SECRET), {
httpOnly: true,
path: '/',
path: '/api/user',
maxAge: 60 * 60 * 24 * 60 // 60 days
});