DEV Community 👩‍💻👨‍💻

Dana Woodman
Dana Woodman

Posted on

How to secure pages with HTTP Basic Auth using SvelteKit

Originally posted on my blog.


Want to add simple authentication to a page, say an admin section or a demo app, in SvelteKit? Well, HTTP Basic Auth might be what you're looking for.

But before we start, you should be aware that HTTP Basic Auth is not considered very secure since you're sending the username/password as base64 encoded, amongst other concerns. If you use HTTPS (which you should be doing!), then this particular attack vector is less of a concern, but you should still consider these factors and you should absolutely not use it with customer/user facing logins. I see HTTP Basic as a useful and quick way to (somewhat) secure a page or section on your site. If you choose HTTP Basic, just be aware that the pages you're securing may not be as secure as you might think.

Ok, moving on!

In order to accomplish this, we will need to intercept all server-side requests using the handle hook which gets called on every request.

We will then check the URL pathname to see if it starts with /admin so that any page under and including /admin will get secured behind HTTP Basic Auth (e.g. /admin, /admin/reports).

Then we check for an Authorization header to see if the user has attempted logged in (or if they cancel the login dialog) and we check it against a username:password combo (base64 encoded). If it doesn't match, then they are not logged in so we indicate they're not authorized with a 401 error.

If they succeed with login by typing in the correct username:password combo, then they will be directed to the admin page they wanted.

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

export const handle: Handle = async ({ event }) => {
    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);
};
Enter fullscreen mode Exit fullscreen mode

Then, in your .env file (as well as set in your hosting provider's environment variable management system), set your username/password combo:

ADMIN_LOGIN="admin:sekret"
Enter fullscreen mode Exit fullscreen mode

And now make sure to create a page at /admin or somewhere else and attempt to load it. You should see the login prompt and on inputting admin for the username and sekret for the password, you should see the admin Svelte page.


Follow me on Dev.to, Twitter and Github for more web dev and startup related content

Top comments (1)

Collapse
fyodorio profile image
Fyodor

Client certificate check can help to make this way safer for using on internal portals or backoffice apps

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.