Part 3: Protecting Routes and Security

Mukesh JaiswalMukesh Jaiswal
3 min read

If you haven't already, I would recommend having a quick look at the Introduction & Sequence Diagram

Welcome to the 3-part series that helps you create a scalable production-ready authentication system using pure JWT & a middleware for your SvelteKit project


You are reading Part 3

Goal: Secure the app with middleware and discuss best practices for a production-ready system.

Topics we'll cover

  • Server Hooks (Middleware): Use SvelteKit hooks to verify JWT and secure routes.

  • Security Considerations: Token storage (HTTP-only cookies), CSRF protection, token expiration, HTTPS, etc.

  • Conclusion & Next Steps: Recap and suggestions like refresh tokens or role-based access.

SvelteKit Server Hooks (Middleware)

Now we'll implement the authentication middleware in SvelteKit's server hooks:

// src/hooks.server.ts
import { authenticateRequest } from "$lib/auth/jwt";
import { clearAuthCookies } from "$lib/auth/cookies";
import type { Handle } from "@sveltejs/kit";
import type { JwtPayload } from "$lib/auth/jwt";

// Extend the Locals interface to include our user property
declare global {
  namespace App {
    interface Locals {
      user?: Omit<JwtPayload, "iat" | "exp">;
    }
  }
}

export const handle: Handle = async ({ event, resolve }) => {
  const { cookies, url } = event;

  // Public routes that don't require authentication
  const publicRoutes = [
    "/auth/sign-in",
    "/auth/sign-up",
    "/auth/forgot-password",
    "/auth/reset-password",
    "/auth/logout",
  ];

  // Check if the current route is public
  const isPublicRoute = publicRoutes.some(
    (route) =>
      url.pathname === route ||
      url.pathname.startsWith("/api/public/")
  );

  // First, verify the authentication status for all routes
  const authResult = authenticateRequest(cookies);

  if (authResult.success && authResult.user) {
    // User is authenticated
    event.locals.user = authResult.user;

    // Maintain backward compatibility with existing code
    if (!cookies.get("user")) {
      cookies.set("user", JSON.stringify(authResult.user), {
        path: "/",
        httpOnly: true,
      });
    }

    // If user is authenticated and trying to access public routes like sign-in
    // redirect them to the dashboard instead
    if (isPublicRoute && url.pathname !== "/auth/logout") {
      return Response.redirect(new URL("/dashboard", url));
    }
  } else {
    // User is not authenticated
    if (!isPublicRoute) {
      // Non-public route requires authentication, redirect to login
      clearAuthCookies(cookies);
      return Response.redirect(new URL("/auth/sign-in", url));
    }
  }

  return resolve(event);
};

Security Considerations

When implementing JWT authentication, consider the following security aspects:

  1. Token Storage: Store tokens in HTTP-only cookies to prevent XSS attacks

  2. CSRF Protection: Implement CSRF tokens for form submissions

  3. Token Expiration: Use short-lived tokens to minimize damage from token theft

  4. Secure Connection: Always use HTTPS in production

  5. Environment Variables: Store your JWT secret in environment variables, not in code

Conclusion

We've built a complete authentication system using SvelteKit, TypeScript, and "pure JWT" authentication. This approach gives us the benefits of stateless authentication while still maintaining proper user management and security audit capabilities.

The key advantage of this implementation is that we don't need to query the database for each authenticated request, making our application more scalable. Instead, we rely on the cryptographic integrity of the JWT itself to validate the user's identity.

Next Steps

To further enhance this system, you might consider:

  1. Implementing refresh tokens for longer sessions

  2. Adding email verification for signup

  3. Supporting password reset functionality

  4. Implementing role-based access control

  5. Adding two-factor authentication

I hope this tutorial helps you build secure and scalable authentication systems with SvelteKit!


Previous → Part 2: Authentication Flows

1
Subscribe to my newsletter

Read articles from Mukesh Jaiswal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mukesh Jaiswal
Mukesh Jaiswal

Driving business growth with AI Automation (as Business Automation Partner) | Helping startups build (as Software Developer)