Reputation: 339
I have a have a project on Next.js and React, which doesn't use any libraries for routing. How should I implement route guards (protected routes) for non-authenticated users? Or should I just redirect them if there is no token in cookie?
Upvotes: 10
Views: 23232
Reputation: 1
You can use the https://www.npmjs.com/package/next-router-guards library. There, you can customize the access settings for your pages using the existing protection options, or create your own protection with custom logic. If you want to check if a user is authorized with a token, you can use AuthorizedGuard (example https://github.com/makskiyko/next-router-guards/blob/master/exmaples/AuthorizedGuard.md)
Upvotes: 0
Reputation: 217
I've had a lot of issues with this, but eventually succeeded to figure things out.
Im using apollo, and my problem was, that I had to redirect on the server if the user is not logged in, or doesn't have a particular role. This is how its done, maybe it helps you too:
import { gql } from 'apollo-boost'
import initApollo from '~/config/init-apollo'
import { Role } from '~/generated/apollo-components'
import { NextPage } from '~/node_modules/next'
import redirect from '~/utils/redirect'
import { parseCookies } from '~/utils/with-apollo'
const GET_USER_ROLE = gql`
query {
me {
role
}
}
`
export default (Page: NextPage<any>, allow: Role[]) => {
const originalGetInitialProps = Page.getInitialProps
let pageProps = {}
Page.getInitialProps = async (ctx) => {
if (originalGetInitialProps) {
pageProps = await originalGetInitialProps(ctx)
}
const apolloClient = initApollo(
{},
{ getToken: () => parseCookies(ctx.req).token },
)
try {
const { data } = await apolloClient.query({ query: GET_USER_ROLE })
if (!allow.includes(data.me.role as Role)) {
redirect(ctx, '/401')
}
return {
...pageProps,
}
} catch (e) {
console.log('error: ', e.graphQLErrors[0])
redirect(ctx, '/login')
}
}
return Page
}
Upvotes: 2
Reputation: 5926
You can check in getInitialProps
with some approp. logic evaluating the cookies to decide whether to redirect or not.
import Router from 'next/router'
const redirectToLogin = res => {
if (res) {
res.writeHead(302, {Location: '/login'})
res.end()
res.finished = true
} else {
Router.push('/login')
}
}
class ProtectedPage extends React.Component {
static async getInitialProps ({req, res}) {
// get cookie from req.headers or from document.cookie in browser
// this cookie must not contain sensitive information!
const profile = getProfileFromCookie(req)
if (!profile) {
redirectToLogin(res)
}
}
}
Have a look at this sample code https://github.com/lipp/login-with/blob/master/example/nextjs/with-profile.js#L8 (I am the author).
Upvotes: 11