#Basic HTTP Authentication

19 messages · Page 1 of 1 (latest)

tawny crag
#

I am trying to implement basic HTTP authentication on an /admin route. The middleware section of the docs is a bit confusing as I'm not totally sure how I can specify a middleware to run before on a specific route everytime?

I tried using the beforeLoad method, but it's a bit unclear if I have to create a middleware, wrap it in a server function, and then call it in my beforeLoad or if there's a simpler way to do this?

marble thicket
#

beforeLoad is too late for basic auth

#

you would need a request middleware

tawny crag
#

I see. I'm still confused how I call or execute this middleware on the route. This is what my file looks like:

// routes/admin.tsx
import { createFileRoute } from "@tanstack/react-router";
import { createMiddleware } from "@tanstack/react-start";

const authMiddleware = createMiddleware({ type: "function" }).server(
    async ({ next, request }) => {
        const authToken = request.headers.get("authorization");
        if (!authToken) {
            // Return 401
        }
        return next();
    },
);

export const Route = createFileRoute("/admin")({
    component: RouteComponent,
});

function RouteComponent() {
    return <div>Hello "/admin"!</div>;
}

marble thicket
#

you would need to add a server file route and install the middleware on that

tawny crag
#

Oh I see it

tawny crag
#

Okay here is my file so far:

import { createFileRoute } from "@tanstack/react-router";
import { createMiddleware } from "@tanstack/react-start";
import { createServerFileRoute } from "@tanstack/react-start/server";

const authMiddleware = createMiddleware({ type: "request" }).server(
    async ({ next, request }) => {
        console.log("next", next);
        const authToken = request.headers.get("authorization");
        if (!authToken) {
            return new Response("Authentication Required", {
                status: 401,
                headers: {
                    "WWW-Authenticate": 'Basic realm="Admin Page"',
                },
            });
        }
        return next();
    },
);

export const ServerRoute = createServerFileRoute("/admin").methods((api) => ({
    GET: api.middleware([authMiddleware]).handler(async ({ request }) => {
        return new Response("Hello, world!");
    }),
}));

export const Route = createFileRoute("/admin")({
    component: RouteComponent,
});

function RouteComponent() {
    return <div>Hello "/admin"!</div>;
}

I have a couple of questions:

  1. Do I need a middleware if I can just my auth logic in the GET request handler?
  2. The webpage now just shows "Hello, world!" instead of "Hello /admin!". Why is the RouteComponent getting overridden?
  3. What is the purpose of the server.ts file? I thought I would need it to enable ServerRoutes but it doesn't look like I need to.
  4. Am getting a typescript error on my authMiddleware:
Argument of type '({ next, request }: RequestServerOptions<undefined>) => Promise<Response | RequestServerResult<undefined, undefined>>' is not assignable to parameter of type 'RequestServerFn<undefined, undefined>'.
  Type 'Promise<Response | RequestServerResult<undefined, undefined>>' is not assignable to type 'RequestMiddlewareServerFnResult<undefined, undefined>'.```
marble thicket
#

What is the purpose of the server.ts file? I thought I would need it to enable ServerRoutes but it doesn't look like I need to.

you can use this to get the request before it is passed into start's handler. whatever you want to do with it, you can do there

#

The webpage now just shows "Hello, world!" instead of "Hello /admin!". Why is the RouteComponent getting overridden?

don't return a response, just return undefined. server file routes have priority over the router routes. that means, if they return a response, their response will be returned to the client

#

if they dont return a response, the router route will be invoked next

#

Do I need a middleware if I can just my auth logic in the GET request handler?

if you only need it in this particular route, then no, you wont need a middleware

tawny crag
#

thanks so much! This clarifies a lot of my understanding about tanstack start

marble thicket
#

this needs much more documentation for sure

#

we'll add this

tawny crag
#

I also was getting a typescript error on and couldn't understand why since I was copying code from the docs until I realized after I hit save that I need to specify a route on it and the framework autopopulated one for me.

Magic like this is super nice, but didn't realize the framework was doing a lot of this for me

#

anyway closing this thread!

marble thicket
#

that magic is also a doc issue btw

vapid stream
marble thicket
#

basic auth needs to happen before router gets the request