Redirect based on current URL
Unanswered
Western paper wasp posted this in #help-forum
Western paper waspOP
I know the current router path is not generally available to server components. However, I want to learn the current path for the specific case of including it in a redirect:
I want to be able to conditionally redirect users to a login page with a URL like
How can I accomplish this in a Next 13 server component?
I want to be able to conditionally redirect users to a login page with a URL like
/login?redirect_path=..., so that the login page can “returnâ€Â users wherever they were after they complete a login.How can I accomplish this in a Next 13 server component?
13 Replies
have you considered doing this in the middleware? it would be way faster than in a server component
and the short answer is that you can't do this in a server component because they don't rerender on navigation. so even if you manage to get the current URL, when the user navigates to a different page it won't read the new value and redirect as you would expect
you can still do this logic in a component if it is a client component, as you have access to
usePathname. but I recommend doing it in the middlewareWestern paper waspOP
I'm trying to write a generic function like
I can verify the token in middleware, but I don’t think I have a secure mechanism to make that verified identity available to server components (which might, for example, need to fetch some data based on the authenticated UID)
getAuthOrLogin() that I can use in server components to securely get the user’s identity from an access token JWT in cookies, falling back to a redirect to login.I can verify the token in middleware, but I don’t think I have a secure mechanism to make that verified identity available to server components (which might, for example, need to fetch some data based on the authenticated UID)
@Rafael Almeida have you considered doing this in the middleware? it would be way faster than in a server component
Western paper waspOP
Like, I don’t think I can get away with only doing verification in middleware because I need to
1. Verify/parse token to get user’s ID (
2. Use that user ID to make a database call
and Step 2 (data fetching) needs to happen in the server component
1. Verify/parse token to get user’s ID (
sub) 2. Use that user ID to make a database call
and Step 2 (data fetching) needs to happen in the server component
so if I were to move step 1 to middleware, I would need a secure channel to send the verified user ID from middleware -> RSC
Western paper waspOP
From the middleware I could set like a
x-verified-access-token-sub header on the response? but I’m not sure whether or not that’s spoofable@Western paper wasp Like, I don’t think I can get away with *only* doing verification in middleware because I need to
1. Verify/parse token to get user’s ID (`sub`)
2. Use that user ID to make a database call
and Step 2 (data fetching) *needs* to happen in the server component
if this database call needs to use a driver that isn't available in a serverless environment then you could move it to a route handler and fetch the route handler from the middleware. it is a bit of a hack but works perfectly, you can even protect it from external calls by passing a secret with a header
I don't have the full context of how your auth system works so it is hard to give you the best solution but if you want to keep all this logic inside server components, you could build something similar to this:
// page file
const Page = async () => {
const authState = await getAuthState();
return <>
<AuthStateHandler state={authState} />
// ... your page code
</>
}
// AuthStateHandler file
'use client'
export const AuthStateHandler = ({ authState }) => {
const pathname = usePathname()
// do something with the pathname, authState and redirect()
return null
}you can still use a server component to fetch the auth stuff and defer the decision of what to do with it to a client component since it has access to the pathname
@Rafael Almeida if this database call needs to use a driver that isn't available in a serverless environment then you could move it to a route handler and fetch the route handler from the middleware. it is a bit of a hack but works perfectly, you can even protect it from external calls by passing a secret with a header
Western paper waspOP
The issue is not that the database call couldn’t be made in middleware, but rather that the database calls are specific to each page, and their results are used in JSX for rendering the page content
so these calls are fetching the page content and while they usually return the content, they also could return an error saying the user isn't authenticated? so this is when you want to trigger a redirect but with the current URL in the query params
Western paper waspOP
Yep, basically