next-fortress
next-fortress copied to clipboard
Redirects even when logged in
My middleware:
import { region, userPoolId, userPoolWebClientId, Group } from "@frontend/config/next"
import { makeCognitoInspector } from "next-fortress"
import { NextMiddleware, NextResponse } from "next/server"
const redirecter: NextMiddleware = (req) => NextResponse.redirect("/login?next=" + req.nextUrl.pathname + "&redir=true")
// admins-only
export const middleware = makeCognitoInspector(redirecter, { region, userPoolId, userPoolWebClientId }, (payload) => {
if (!payload) return false
const groups = payload["cognito:groups"] as string[]
return groups?.includes(Group.Admins)
})
When I open a new tab and directly go to a route protected by this middleware, it redirects me to log in. However if I navigate to the route afterwards it lets me view it.
I think maybe fortress isn't waiting for the cognito auth state to be fully resolved, possibly because it needs to refresh my access token. Just a theory.
@revmischa Hi, thanks for opening the issue.
When using Cognito, next-fortress uses a token set in the cookie to check the status in the middleware. (The key of the cookie is CognitoIdentityServiceProvider.xxxx.idToken.) This cookie is automatically set by the Amplify client after login, and the expires is set as Session.
My guess is that either the cookie was cleared when you opened a new tab, or you opened a new tab before the Amplify client set the cookie. Is the cookie still in your browser when you open a new tab?
I have a sample site: https://next-fortress.vercel.app/cognito I have tried the following steps on this site and am not experiencing the problem you report.
- login (/cognito)
- go to the logged in page (/cognito/authed)
- navigated without problems
- then open /cognito/authed in a new tab
- accessed the page without problems
Please elaborate on the steps to reproduce your problem. Also, does the above sample site reproduce this problem when you try it?
I don't have a problem accessing my route when I authenticate and then open the route in a new tab. I have the cookie set. All works fine there.
The problem is if I wait some time (I suspect until the access token expires) then when I open the route it kicks me to the redirect. Perhaps this is because fortress does not wait for the token refresh before determining that I am not logged in?
The problem here is that the code doesnt work as expected
https://github.com/aiji42/next-fortress/blob/main/src/cognito.ts
const token = Object.entries(req.cookies).find(([key]) =>
new RegExp(
`CognitoIdentityServiceProvider\\.${clientId}\\..+\\.idToken`
).test(key)
)?.[1]
if you add some console.logs, you will see why
const token = Object.entries(req.cookies).find(([key]) => {
console.log('key:', key)
return new RegExp(`CognitoIdentityServiceProvider\\.${clientId}\\..+\\.idToken`).test(key)
})?.[1]
outputs
key: get
key: getWithOptions
key: set
key: delete
key: clear
key: response
the "correct" way to do this is like so
const tokenKey = [...req.cookies.keys()].find(key =>
new RegExp(`CognitoIdentityServiceProvider\\.${clientId}\\..+\\.idToken`).test(key),
)
if (!tokenKey) return false
const token = req.cookies.get(tokenKey)
I am going to open a PR for this
For now I am going to eject from next-fortress, and use my modified middleware, as I am only using it for Cognito
https://github.com/aiji42/next-fortress/pull/209
#209
PR merged, thanks @aiji42