awinogrodzki / next-firebase-auth-edge

Next.js Firebase Authentication for Edge and Node.js runtimes. Compatible with latest Next.js features.
https://next-firebase-auth-edge-docs.vercel.app/
MIT License
452 stars 40 forks source link

How to handle custom middleware with package middleware #217

Open discoverlance-com opened 1 month ago

discoverlance-com commented 1 month ago

I have seen examples and on the docs (usage with other middleware). But I seem to be getting these warnings in my console after updating the middleware. Basically, I want to set CSP header on my request/response so I am updating the middleware functions to do this but I keep getting the error below:

warn next-firebase-auth-edge: NextResponse returned by handleValidToken was not decorated by modified request headers. This can cause token verification to happen multiple times in a single request. See: https://next-firebase-auth-edge-docs.vercel.app/docs/usage/middleware#middleware-token-verification-caching ○ Compiling /dashboard ... ✓ Compiled /dashboard in 12.2s (2081 modules)

I have made sure to pass the headers from the handleValidToken function but it still seems to give this error.

This is my updated handleValidToken function and also the other functions.

handleValidToken: async ({ token, decodedToken }, headers) => {
            // Authenticated user should not be able to access /login, /register and /reset-password routes
            if (PUBLIC_PATHS.includes(request.nextUrl.pathname)) {
                return redirectToHome(request)
            }

            let response = NextResponse.next({
                request: {
                                        // pass headers from handle valid token instead of request.headers
                    headers: headers,
                },
            })

            const { nonce, contentSecurityPolicyHeaderValue } = getCspInformation()
            const requestHeaders = new Headers(headers) // pass headers from handle valid token instead of request.headers
            requestHeaders.set('x-nonce', nonce)
            requestHeaders.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            response = NextResponse.next({
                request: {
                    headers: requestHeaders,
                },
            })

            response.headers.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            return response
        },
        handleInvalidToken: async (reason) => {
            console.info('Missing or malformed credentials', { reason })

            let response = NextResponse.next({
                request: {
                    headers: request.headers,
                },
            })

            const { nonce, contentSecurityPolicyHeaderValue } = getCspInformation()
            const requestHeaders = new Headers(request.headers)
            requestHeaders.set('x-nonce', nonce)
            requestHeaders.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            response = NextResponse.next({
                request: {
                    headers: requestHeaders,
                },
            })

            response.headers.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            return redirectToLogin(request, response, {
                path: '/',
                publicPaths: PUBLIC_PATHS,
            })
        },
        handleError: async (error) => {
            console.error('Unhandled authentication error', { error })

            let response = NextResponse.next({
                request: {
                    headers: request.headers,
                },
            })

            const { nonce, contentSecurityPolicyHeaderValue } = getCspInformation()
            const requestHeaders = new Headers(request.headers)
            requestHeaders.set('x-nonce', nonce)
            requestHeaders.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            response = NextResponse.next({
                request: {
                    headers: requestHeaders,
                },
            })

            response.headers.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            return redirectToLogin(request, response, {
                path: '/',
                publicPaths: PUBLIC_PATHS,
            })
        },

Am I doing it right here? What's the best thing to do in this case?

awinogrodzki commented 1 month ago

Hey @discoverlance-com! Thanks for reporting. I'll try to reproduce the behaviour on my side and will get back to you

awinogrodzki commented 1 month ago

I could not reproduce your issue in starter example: https://github.com/awinogrodzki/next-firebase-auth-edge/pull/218/files

Could you provide some more context on the issue?

In what environment is the server running? I am interested in hosting provider, Node.js version

Could you set debug: true option in middleware and share the logs here?

discoverlance-com commented 1 month ago

Hello,

I updated it to your example and it worked for me now with no warnings. I thought I needed to first create the response with the code below and then set the headers there before I later on update it with the headers from the new Headers() too. It seems like that was the issue. In the end, I replicated what you did by first creating the headers, before later creating the NextResponse and that should be what resolved the warning as I no longer saw the warning. Thanks


            let response = NextResponse.next({
                request: {
                                        // pass headers from handle valid token instead of request.headers
                    headers: headers,
                },
            })

But quick question, if I have middleware logic like in this example for csp or any other custom middleware function I want to run, do I need to run it in all three functions from the package's middleware (handleValidToken, handleErrors, handleInvalidToken)? And also, what about the redirectToLogin and redirectToHome functions? Do I need to update them in this case? For instance, in my case, because I saw that the redirectToLogin function also uses NextResponse. I was just not sure if I might be caught of guard somewhere and a response will be returned without me setting the csp.

// In the package's code, `src/next/middleware.ts`, the redirectToLogin function uses next response as below

export function redirectToLogin(
  request: NextRequest,
  options: RedirectToLoginOptions = {
    path: '/login',
    publicPaths: ['/login']
  }
) {
  const redirectKey = options.redirectParamKeyName || 'redirect';

 // Next Response is used here
  if (options.publicPaths.includes(request.nextUrl.pathname)) {
    return NextResponse.next();
  }
...
}

// So I thought it could be a place where I miss to pass the csp so I created a custom redirectToLogin that accepted the response from the handleInvalidToken function that has been modified with the csp headers to make sure it uses the modified response
function redirectToLogin(
    request: NextRequest,
    response: NextResponse<unknown>,
    options: RedirectToLoginOptions = {
        path: '/',
        publicPaths: ['/'],
    },
) {
    const redirectKey = options.redirectParamKeyName || 'redirect'

        // here i use the modified response
    if (options.publicPaths.includes(request.nextUrl.pathname)) {
        return response
    }
        ...
}

Are there any guidelines or notes to ensure that if I want to pass information like custom headers or even cookies to my response, I don't miss passing it to any response the package's middleware returns?

discoverlance-com commented 1 month ago

Sorry, it looks like I am still getting the warning even after the changes, initially, I did not see it again after the changes.

My node version: v20.14.0

I set debug:true and these are the logs:

Ready in 2s
 ○ Compiling /src/middleware ...
 ✓ Compiled /src/middleware in 1342ms (181 modules)
ⓘ next-firebase-auth-edge: Handle request
         path: /
ⓘ next-firebase-auth-edge: Verifying user credentials...
ⓘ next-firebase-auth-edge: No public keys found in cache. Fetching public keys from Google...
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Public keys fetched
         responseHeaders: {
  age: '52',
  alt-svc: 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000',
  cache-control: 'public, max-age=19976, must-revalidate, no-transform',
  content-encoding: 'gzip',
  content-length: '2156',
  content-type: 'application/json; charset=UTF-8',
  date: 'Fri, 19 Jul 2024 07:27:02 GMT',
  expires: 'Fri, 19 Jul 2024 12:59:58 GMT',
  server: 'scaffolding on HTTPServer2',
  vary: 'Origin,X-Origin,Referer',
  x-content-type-options: 'nosniff',
  x-frame-options: 'SAMEORIGIN',
  x-xss-protection: '0'
}
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Public keys cached
         cacheKey: https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com
         expiresAt: 1721394050526
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Credentials verified successfully
ⓘ next-firebase-auth-edge: Successfully handled authenticated response
ⓘ next-firebase-auth-edge: Handle request
         path: /dashboard
ⓘ next-firebase-auth-edge: Verifying user credentials...
ⓘ next-firebase-auth-edge: Get public keys from cache
         expiresAt: 1721394050526
         now: 1721374074973
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Credentials verified successfully
ⓘ next-firebase-auth-edge: Successfully handled authenticated response
 ○ Compiling /dashboard ...
 ✓ Compiled /dashboard in 8.8s (1102 modules)
 GET /dashboard 200 in 10052ms
 ✓ Compiled in 1376ms (449 modules)
ⓘ next-firebase-auth-edge: Handle request
         path: /logo/logo-icon4x.png
ⓘ next-firebase-auth-edge: Verifying user credentials...
ⓘ next-firebase-auth-edge: Get public keys from cache
         expiresAt: 1721394050526
         now: 1721374085462
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Credentials verified successfully
ⓘ next-firebase-auth-edge: Successfully handled authenticated response
ⓘ next-firebase-auth-edge: Handle request
         path: /avatars/03.png
ⓘ next-firebase-auth-edge: Verifying user credentials...
ⓘ next-firebase-auth-edge: Get public keys from cache
         expiresAt: 1721394050526
         now: 1721374089117
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Credentials verified successfully
ⓘ next-firebase-auth-edge: Successfully handled authenticated response
ⓘ next-firebase-auth-edge: Handle request
         path: /avatars/02.png
ⓘ next-firebase-auth-edge: Handle request
         path: /avatars/01.png
ⓘ next-firebase-auth-edge: Verifying user credentials...
ⓘ next-firebase-auth-edge: Get public keys from cache
         expiresAt: 1721394050526
         now: 1721374089354
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Verifying user credentials...
ⓘ next-firebase-auth-edge: Get public keys from cache
         expiresAt: 1721394050526
         now: 1721374089355
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Credentials verified successfully
ⓘ next-firebase-auth-edge: Successfully handled authenticated response
ⓘ next-firebase-auth-edge: Credentials verified successfully
ⓘ next-firebase-auth-edge: Successfully handled authenticated response
 ○ Compiling /_not-found ...
 ✓ Compiled /_not-found in 4.7s (1073 modules)
 GET /avatars/03.png 404 in 5159ms
 GET /avatars/02.png 404 in 4925ms
 GET /avatars/01.png 404 in 4927ms
ⓘ next-firebase-auth-edge: Handle request
         path: /avatars/05.png
ⓘ next-firebase-auth-edge: Handle request
         path: /avatars/04.png
ⓘ next-firebase-auth-edge: Verifying user credentials...
ⓘ next-firebase-auth-edge: Get public keys from cache
         expiresAt: 1721394050526
         now: 1721374094516
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Verifying user credentials...
ⓘ next-firebase-auth-edge: Get public keys from cache
         expiresAt: 1721394050526
         now: 1721374094518
         cryptoRuntime: WebCryptoAPI
ⓘ next-firebase-auth-edge: Credentials verified successfully
ⓘ next-firebase-auth-edge: Successfully handled authenticated response
ⓘ next-firebase-auth-edge: Credentials verified successfully
ⓘ next-firebase-auth-edge: Successfully handled authenticated response
 GET /avatars/05.png 404 in 56ms
 GET /avatars/04.png 404 in 56ms

It's quite weird I think, I am not sure if it's a local configuration but I am not doing anything out of the norm, I am setting these headers below in my next config, that should be the only different thing I am doing I think and also that I am running on github codespaces. But what I am observing is that, when I leave my dev server for a while and then I start it afresh or start a new dev server, then I see the error. But after that, it does not matter how many times I restart the dev server, I no longer see the error so I am not able to provide more context or debug.


async headers() {
        return [
            {
                source: '/:path*',
                headers: [
                    {
                        key: 'Strict-Transport-Security',
                        value: 'max-age=31536000; includeSubDomains; preload',
                    },
                    {
                        key: 'X-Frame-Options',
                        value: 'SAMEORIGIN',
                    },
                    {
                        key: 'X-Content-Type-Options',
                        value: 'nosniff',
                    },
                    {
                        key: 'Referrer-Policy',
                        value: 'strict-origin-when-cross-origin',
                    },
                    {
                        key: 'X-Xss-Protection',
                        value: '1; mode=block',
                    },
                ],
            },
        ]
awinogrodzki commented 3 weeks ago

Hey @discoverlance-com!

Thank you for your patience.

if I have middleware logic like in this example for csp or any other custom middleware function I want to run, do I need to run it in all three functions from the package's middleware (handleValidToken, handleErrors, handleInvalidToken)?

It depends on your needs really. Are you planning to expose CSP headers to unauthenticated users? If so, you would have to use the same logic in all three callbacks. You can encapsulate the logic in some function shared by all the callbacks.

In future I will introduce a way to add custom logic for three of those methods at once

And also, what about the redirectToLogin and redirectToHome functions? Do I need to update them in this case?

redirectToLogin and redirectToHome are very simple functions

export function redirectToHome(
  request: NextRequest,
  options: RedirectToHomeOptions = {
    path: '/'
  }
) {
  const url = request.nextUrl.clone();
  url.pathname = options.path;
  url.search = '';
  return NextResponse.redirect(url);
}

Initially user was required to write their own implementation. I included those functions just to enable basic auth flow for most users.

You can most-definitely write your own custom redirect logic. It's encouraged.

But what I am observing is that, when I leave my dev server for a while and then I start it afresh or start a new dev server, then I see the error. But after that, it does not matter how many times I restart the dev server, I no longer see the error so I am not able to provide more context or debug.

How often do you see this warning in github codespaces?

First of all, this warning is nothing critical, it just means that whenever you call getTokens after this warning, the token will be verified again, which introduces a bit of computational overhead.

It can happen if a response returned by handleValidToken was not decorated with headers:

        markCookiesAsVerified(request.cookies);

        const response = await handleValidToken(
          {
            token: customTokens.idToken,
            decodedToken,
            customToken: customTokens.customToken
          },
          request.headers
        );

        if (!response.headers.has('location')) {
          validateResponse(response); // <!-- this prints a warning
        }

        return response;

There might be some cases where Next.js does not pass down those headers – one scenario is redirect, thus validation is skipped if response.headers.has('location')

I will investigate further if there are some other paths this warning can occur. Anyways, if it does not happen on every user request, you should not worry about it

discoverlance-com commented 3 weeks ago

Hey @discoverlance-com!

Thank you for your patience.

if I have middleware logic like in this example for csp or any other custom middleware function I want to run, do I need to run it in all three functions from the package's middleware (handleValidToken, handleErrors, handleInvalidToken)?

It depends on your needs really. Are you planning to expose CSP headers to unauthenticated users? If so, you would have to use the same logic in all three callbacks. You can encapsulate the logic in some function shared by all the callbacks.

In future I will introduce a way to add custom logic for three of those methods at once

And also, what about the redirectToLogin and redirectToHome functions? Do I need to update them in this case?

redirectToLogin and redirectToHome are very simple functions

export function redirectToHome(
  request: NextRequest,
  options: RedirectToHomeOptions = {
    path: '/'
  }
) {
  const url = request.nextUrl.clone();
  url.pathname = options.path;
  url.search = '';
  return NextResponse.redirect(url);
}

Initially user was required to write their own implementation. I included those functions just to enable basic auth flow for most users.

You can most-definitely write your own custom redirect logic. It's encouraged.

But what I am observing is that, when I leave my dev server for a while and then I start it afresh or start a new dev server, then I see the error. But after that, it does not matter how many times I restart the dev server, I no longer see the error so I am not able to provide more context or debug.

How often do you see this warning in github codespaces?

First of all, this warning is nothing critical, it just means that whenever you call getTokens after this warning, the token will be verified again, which introduces a bit of computational overhead.

It can happen if a response returned by handleValidToken was not decorated with headers:

        markCookiesAsVerified(request.cookies);

        const response = await handleValidToken(
          {
            token: customTokens.idToken,
            decodedToken,
            customToken: customTokens.customToken
          },
          request.headers
        );

        if (!response.headers.has('location')) {
          validateResponse(response); // <!-- this prints a warning
        }

        return response;

There might be some cases where Next.js does not pass down those headers – one scenario is redirect, thus validation is skipped if response.headers.has('location')

I will investigate further if there are some other paths this warning can occur. Anyways, if it does not happen on every user request, you should not worry about it

Ok noted, yes it does not happen on every user request. Only the initial request or when I launch the dev server after stopping the github workspace. So it happens on fresh server loads. I guess it could be because it's fetching the data the first time? I am not sure.

Anyways, thanks for the bits you shared on this. I really appreciate it and understand at least how to add custom middlewares to my project.

If it's no issue that it does not happen on every request then I am good with that.

awinogrodzki commented 2 weeks ago

The warning should not happen on first request or server startup also, I will mark it as a bug and try to reproduce it on my end. I'll keep you updated on this one

awinogrodzki commented 2 weeks ago

@discoverlance-com, by the way, which Next.js version are you using? I cannot reproduce this in Next.js 14.2.3

discoverlance-com commented 2 weeks ago

@discoverlance-com, by the way, which Next.js version are you using? I cannot reproduce this in Next.js 14.2.3

My Nextjs version and the package versions are as below:

    "next": "14.2.4",
    "next-firebase-auth-edge": "^1.6.2",

My middleware as it stands has this content below, major difference being that my homepage is what handles the authentication so I don't actually have a /login page and also that I develop on github codespaces.


import { authMiddleware } from 'next-firebase-auth-edge'
import { NextRequest, NextResponse } from 'next/server'

import { authConfig } from '@/lib/firebase/config/server-config'

interface RedirectToLoginOptions {
    path: string
    publicPaths: string[]
    redirectParamKeyName?: string
}

const PUBLIC_PATHS = ['/', '/reset-password']

function redirectToHome(request: NextRequest) {
    const url = request.nextUrl.clone()
    url.pathname = '/dashboard'
    url.search = ''
    return NextResponse.redirect(url)
}

function redirectToLogin(
    request: NextRequest,
    response: NextResponse<unknown>,
    options: RedirectToLoginOptions = {
        path: '/',
        publicPaths: ['/'],
    },
) {
    const redirectKey = options.redirectParamKeyName || 'redirect'

    if (options.publicPaths.includes(request.nextUrl.pathname)) {
        return response
    }

    const url = request.nextUrl.clone()
    url.pathname = options.path
    url.search = `${redirectKey}=${request.nextUrl.pathname}${url.search}`
    return NextResponse.redirect(url)
}

function getCspInformation() {
    const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
    const cspHeader = `
        connect-src 'self' securetoken.googleapis.com firebasestorage.googleapis.com firestore.googleapis.com https://www.googleapis.com identitytoolkit.googleapis.com;
    default-src 'self';
    script-src 'self' 'nonce-${nonce}' 'strict-dynamic' https: ${
            process.env.NODE_ENV === 'production' ? '' : `'unsafe-eval'`
        };
    style-src 'self' 'unsafe-inline';
    img-src images.unsplash.com 'self' firebasestorage.googleapis.com ui-avatars.com blob: data: content: ;
    font-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    upgrade-insecure-requests;
`

    // Replace newline characters and spaces
    const contentSecurityPolicyHeaderValue = cspHeader
        .replace(/\s{2,}/g, ' ')
        .trim()

    return { nonce, contentSecurityPolicyHeaderValue }
}

export async function middleware(request: NextRequest) {
    return authMiddleware(request, {
        loginPath: '/api/login',
        logoutPath: '/api/logout',
        refreshTokenPath: '/api/refresh-token',
        apiKey: authConfig.apiKey,
        cookieName: authConfig.cookieName,
        cookieSerializeOptions: authConfig.cookieSerializeOptions,
        cookieSignatureKeys: authConfig.cookieSignatureKeys,
        serviceAccount: authConfig.serviceAccount,
        handleValidToken: async ({ token, decodedToken }, headers) => {
            // Authenticated user should not be able to access /login, /register and /reset-password routes
            if (PUBLIC_PATHS.includes(request.nextUrl.pathname)) {
                return redirectToHome(request)
            }

            const { nonce, contentSecurityPolicyHeaderValue } = getCspInformation()

            const requestHeaders = new Headers(headers)
            requestHeaders.set('x-nonce', nonce)
            requestHeaders.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            const response = NextResponse.next({
                request: {
                    headers: requestHeaders,
                },
            })

            response.headers.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            return response
        },
        handleInvalidToken: async (reason) => {
            console.info('Missing or malformed credentials', { reason })

            const { nonce, contentSecurityPolicyHeaderValue } = getCspInformation()
            const requestHeaders = new Headers(request.headers)
            requestHeaders.set('x-nonce', nonce)
            requestHeaders.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            const response = NextResponse.next({
                request: {
                    headers: requestHeaders,
                },
            })

            response.headers.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            return redirectToLogin(request, response, {
                path: '/',
                publicPaths: PUBLIC_PATHS,
            })
        },
        handleError: async (error) => {
            console.error('Unhandled authentication error', { error })

            const { nonce, contentSecurityPolicyHeaderValue } = getCspInformation()
            const requestHeaders = new Headers(request.headers)
            requestHeaders.set('x-nonce', nonce)
            requestHeaders.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            const response = NextResponse.next({
                request: {
                    headers: requestHeaders,
                },
            })

            response.headers.set(
                'Content-Security-Policy',
                contentSecurityPolicyHeaderValue,
            )

            return redirectToLogin(request, response, {
                path: '/',
                publicPaths: PUBLIC_PATHS,
            })
        },
    })
}

export const config = {
    matcher: [
        '/',
        '/api/refresh-token',
        '/dashboard/:path*',
        '/((?!_next/static|_next/image|favicon.ico|__/auth|__/firebase|api|.*\\.).*)',
        // {
        //  source: '/((?!api|_next|__/auth|__/firebase|favicon.ico).*)',
        //  missing: [
        //      { type: 'header', key: 'next-router-prefetch' },
        //      { type: 'header', key: 'purpose', value: 'prefetch' },
        //  ],
        // },
        '/api/login',
        '/api/logout',
    ],
}

And also, my authConfig:

import { env } from '@/env'

import { clientConfig } from './client-config'

export const serverConfig = {
    useSecureCookies: env.ADMIN_USE_SECURE_COOKIES === 'true',
    firebaseApiKey: env.NEXT_PUBLIC_ADMIN_FIREBASE_API_KEY,
    serviceAccount: env.ADMIN_FIREBASE_ADMIN_PRIVATE_KEY
        ? {
                projectId: env.NEXT_PUBLIC_ADMIN_FIREBASE_PROJECT_ID,
                clientEmail: env.ADMIN_FIREBASE_ADMIN_CLIENT_EMAIL!,
                privateKey: env.ADMIN_FIREBASE_ADMIN_PRIVATE_KEY.replace(/\\n/g, '\n')!,
            }
        : undefined,
}

export const authConfig = {
    apiKey: serverConfig.firebaseApiKey,
    cookieName: '__session',
    cookieSignatureKeys: [
        env.ADMIN_COOKIE_SIGNATURE_SECRET_1,
        env.ADMIN_COOKIE_SIGNATURE_SECRET_2,
    ],
    cookieSerializeOptions: {
        path: '/',
        httpOnly: true,
        secure: serverConfig.useSecureCookies, // Set this to true on HTTPS environments
        sameSite: 'lax' as const,
        maxAge: 12 * 60 * 60 * 24, // twelve days
    },
    serviceAccount: serverConfig.serviceAccount,
}

export const clientAuthConfig = {
    ...clientConfig,
    storageBucket: env.NEXT_PUBLIC_ADMIN_FIREBASE_STORAGE_BUCKET,
    cookieName: authConfig.cookieName,
    cookieSignatureKeys: authConfig.cookieSignatureKeys,
}
awinogrodzki commented 6 days ago

Hey @discoverlance-com!

In v1.7.0-canary.10 I've added additional debug logs for getTokens function. You can pass debug: true to getTokens and look for getTokens: Cookies are marked as verified. Skipping verification logs. You can share those here if you wish, so we can debug it together.

Cheers!

discoverlance-com commented 5 days ago

Hello @awinogrodzki,

I upgraded to the canary and used the debug: true option in my config and I did not see the warning in my logs. I tried again with no debug true in the getTokens function and I also don't see any warning in the logs.

I am not sure perhaps there was an upgrade fix but I no longer see that warning in my console. Even when I start a new codespace. So it should be ok now. I can't tell if it will pop up once more but at least from what you mentioned, it is not an error but a warning so it should not break my application. Thanks for working on this.