T
TanStack3w ago
fascinating-indigo

Basic HTTP Authentication

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?
12 Replies
adverse-sapphire
adverse-sapphire3w ago
beforeLoad is too late for basic auth you would need a request middleware
fascinating-indigo
fascinating-indigoOP3w ago
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>;
}
// 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>;
}
adverse-sapphire
adverse-sapphire3w ago
you would need to add a server file route and install the middleware on that
fascinating-indigo
fascinating-indigoOP3w ago
Oh I see it 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>;
}
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:
if (!authToken) {
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>'.
if (!authToken) {
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>'.
adverse-sapphire
adverse-sapphire3w ago
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
fascinating-indigo
fascinating-indigoOP3w ago
thanks so much! This clarifies a lot of my understanding about tanstack start
adverse-sapphire
adverse-sapphire3w ago
this needs much more documentation for sure we'll add this
fascinating-indigo
fascinating-indigoOP3w ago
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
No description
fascinating-indigo
fascinating-indigoOP3w ago
anyway closing this thread!
adverse-sapphire
adverse-sapphire3w ago
that magic is also a doc issue btw
conscious-sapphire
conscious-sapphire3w ago
Would you be able to expand on this?
adverse-sapphire
adverse-sapphire3w ago
basic auth needs to happen before router gets the request so would either need to happen in the request handler or in a serverFileRoute middleware

Did you find this page helpful?