I'm trying to figure out an appropriate way of doing authentication, which I know is a touchy subject on the GitHub issue page .
My authentication is simple. I store a JWT token in the session. I send it to a different server for approval. If I get back true, we keep going, if I get back false, it clears the session and puts sends them to the main page.
In my server.js
file I have the following (note- I am using the example from nextjs learn and just adding isAuthenticated
):
function isAuthenticated(req, res, next) {
//checks go here
//if (req.user.authenticated)
// return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/');
}
server.get('/p/:id', isAuthenticated, (req, res) => {
const actualPage = '/post'
const queryParams = { id: req.params.id }
app.render(req, res, actualPage, queryParams)
})
This works as designed. If I refresh the page /p/123
, it will redirect to the /
. However, if I go there via a next/link
href, it doesn't. Which I believe is because it's not using express at this point but next's custom routing.
Is there a way I can bake in a check for every single next/link
that doesn't go through express so that I can make sure the user is logged in?
Tim from the next chat helped me solve this. Solution can be found here but I will quote him so you all can see:
_app.js
getInitialProps
and redirect like thisI've also created an example skeleton template you can take a look at.
--
EDIT July 2021 - WARNING: This is an outdated solution and has not been confirmed to work with the latest versions of next.js. Use skeleton template at your own risk.
没有middleware
在没有API的路线NextJS
,但也有肝卵圆细胞,它可以用来连接数据库-选择用户,等: https://hoangvvo.com/blog/nextjs-middleware
With the release of Next.js 12, there's now beta support for middleware using Vercel Edge Functions.
https://nextjs.org/blog/next-12#introducing-middleware
Middleware uses a strict runtime that supports standard Web APIs like fetch. > This works out of the box using next start, as well as on Edge platforms like Vercel, which use Edge Functions.
To use Middleware in Next.js, you can create a file pages/_middleware.js. In this example, we use the standard Web API Response (MDN):
// pages/_middleware.js
export function middleware(req, ev) {
return new Response('Hello, world!')
}
in next.config.js
:
const withTM = require('@vercel/edge-functions-ui/transpile')()
module.exports = withTM()
in pages/_middleware.js
:
import { NextRequest, NextResponse } from 'next/server'
import { setUserCookie } from '@lib/auth'
export function middleware(req: NextRequest) {
// Add the user token to the response
return setUserCookie(req, NextResponse.next())
}
in pages/api/_middleware.js
:
import type { NextRequest } from 'next/server'
import { nanoid } from 'nanoid'
import { verifyAuth } from '@lib/auth'
import { jsonResponse } from '@lib/utils'
export async function middleware(req: NextRequest) {
const url = req.nextUrl
if (url.searchParams.has('edge')) {
const resOrPayload = await verifyAuth(req)
return resOrPayload instanceof Response
? resOrPayload
: jsonResponse(200, { nanoid: nanoid(), jwtID: resOrPayload.jti })
}
}
in pages/api/index.js
:
import type { NextApiRequest, NextApiResponse } from 'next'
import { verify, JwtPayload } from 'jsonwebtoken'
import { nanoid } from 'nanoid'
import { USER_TOKEN, JWT_SECRET_KEY } from '@lib/constants'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'GET') {
return res.status(405).json({
error: { message: 'Method not allowed' },
})
}
try {
const token = req.cookies[USER_TOKEN]
const payload = verify(token, JWT_SECRET_KEY) as JwtPayload
res.status(200).json({ nanoid: nanoid(), jwtID: payload.jti })
} catch (err) {
res.status(401).json({ error: { message: 'Your token has expired.' } })
}
}
I created mine by creating a wrapper component leveraging NextAuth.js:
const AUTH_FLOW = '/api/auth'
/**
* Provider to wrap the components in to check the user is authenticated before displaying a page.
*/
const Auth: React.FC<React.PropsWithChildren> = ({ children }) => {
const { data: session, status } = useSession()
const router = useRouter();
React.useEffect(() => {
const current_url = router.asPath
const inAuthFlow = current_url.startsWith(AUTH_FLOW)
// Delegate access to auth pages to NextAuth.js
if (inAuthFlow) {
return;
}
if (status == 'unauthenticated') {
signIn();
}
}, [session])
if (status === "authenticated") {
return <>{children}</>
}
return <div>Loading...</div>
}
/**
* Application initializer.
*/
const App = ({
Component,
pageProps: { session, ...pageProps }
}: AppProps): JSX.Element => {
return (
<SessionProvider session={session}>
<Auth>
<Layout>
<Component {...pageProps} />
</Layout>
</Auth>
</SessionProvider>
)
}
If a user is not on the auth pages and is not logged in, they'll be sent to the login screen.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.