SvelteKit: How to protect page with www-authenticate header

Viewed 221

I am trying to build a site with svelte-kit that has a small admin section that only users with a username and password can access. What I have right now is an admin page admin.svelte and a page endpoint admin.ts which should return a 401 status with a www-authenticate: basic header when the user is not logged in, like so:

import type { RequestHandler } from '@sveltejs/kit';

export const get: RequestHandler = async () => {
    return {
        status: 401,
        headers: {
            'www-authenticate': 'Basic'
        }
    };
};

But when I open /admin the browser login prompt is not shown like I would expect with the authenticate header. When I look at the network traffic, I can see that the page request has the correct 401 status, but the authenticate header is missing from the response headers.

Contrary to that, the browser login prompt is shown when I navigate via client-side routing from / to /admin.

How can I get the server-rendered page to include authenticate header and show me the browser login prompt, like it does after client side navigation?

1 Answers

I'd recommend looking at the handle hook to intercept requests and check for authentication.

// hooks.ts
import type { Handle } from "@sveltejs/kit";
import { ADMIN_LOGIN } from "$env/static/private";

export async function handle({
    event,
    resolve,
}: Parameters<Handle>[0]): Promise<ReturnType<Handle>> {
    const url = new URL(event.request.url);

    if (url.pathname.startsWith("/admin")) {
        const auth = event.request.headers.get("Authorization");

        if (auth !== `Basic ${btoa(ADMIN_LOGIN)}`) {
            return new Response("Not authorized", {
                status: 401,
                headers: {
                    "WWW-Authenticate":
                        'Basic realm="User Visible Realm", charset="UTF-8"',
                },
            });
        }
    }

    return resolve(event);
}

Then in your .env file:

ADMIN_LOGIN="admin:password"

Make sure to also set ADMIN_LOGIN in your hosting providers environment variable system.

Related