next-fortress icon indicating copy to clipboard operation
next-fortress copied to clipboard

Redirects even when logged in

Open revmischa opened this issue 3 years ago • 5 comments

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 avatar Feb 02 '22 09:02 revmischa

@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.

  1. login (/cognito)
  2. go to the logged in page (/cognito/authed)
  3. navigated without problems
  4. then open /cognito/authed in a new tab
  5. 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?

aiji42 avatar Feb 03 '22 16:02 aiji42

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?

revmischa avatar Feb 18 '22 12:02 revmischa

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

shainegordon avatar Aug 15 '22 12:08 shainegordon

https://github.com/aiji42/next-fortress/pull/209

shainegordon avatar Aug 15 '22 12:08 shainegordon

#209

PR merged, thanks @aiji42

shainegordon avatar Aug 16 '22 21:08 shainegordon