getsentry / sentry-javascript

Official Sentry SDKs for JavaScript
https://sentry.io
MIT License
8.02k stars 1.59k forks source link

Unable to setUser on Next.js middleware + next-auth #8508

Closed naofalleoagusta closed 1 year ago

naofalleoagusta commented 1 year ago

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nextjs

SDK Version

7.57.0

Framework Version

Next.js 13.2.4

Link to Sentry event

https://govtech-procurement.sentry.io/issues/4307368258/?query=is%3Aunresolved&referrer=issue-stream&stream_index=1

SDK Setup

Mostly just from the docs, with the addition of an environment options.

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  // Adjust this value in production, or use tracesSampler for greater control
  tracesSampleRate: 1.0,
  // ...
  // Note: if you want to override the automatic release value, do not set a
  // `release` value here - use the environment variable `SENTRY_RELEASE`, so
  // that it will also get attached to your source maps
  // in development and sample at a lower rate in production
  replaysSessionSampleRate: 0.1,

  // If the entire session is not sampled, use the below sample rate to sample
  // sessions when an error occurs.
  replaysOnErrorSampleRate: 1.0,

  integrations: [
    new Sentry.Replay({
      // Additional SDK configuration goes in here, for example:
      maskAllText: true,
      blockAllMedia: true,
    }),
  ],
})

Steps to Reproduce

Attempting to use setUser on Next.js middleware+withAuth HOC from next-auth.

The middleware setup looking like this :

export default withAuth(
  function middleware(request: NextRequest) {
    const tokenJWT = (request as any)?.nextauth.token as JWT
    const userId = tokenJWT?.profile?.userId
    console.log("console log here", userId)
    if (buyerId) {
      setUser({ id: userId })
    }
    // rest of code
    return NextResponse.next()
  },
  {
    callbacks: {
      authorized: ({ token }) =>!!token
    },
    cookies: customCookies,
    pages: {
      signIn: "/signinpage",
      signOut: "/signoutpage",
      error: "/errorpage",
    },
  }
)

/**
 * Note: Add here if pages requires authentication
 */
export const config = {
  matcher: [
    "/protectedpath"
  ],
}

And yes I have made sure, I have logged in because the middleware only get executed when you are logged in.

Also, I have tried calling the setUser on my client provider using useEffect :

 React.useEffect(() => {
    if (user?.id) {
      setUser({
        id: id,
      })
    }
  }, [buyer?.buyerId])

That didn't work too

Expected Result

The error log should've set the user.id

Actual Result

Sentry doesn't log the user.id

naofalleoagusta commented 1 year ago

I'm also getting this error on the terminal Screenshot 2023-07-12 at 08 40 10 I have tried several suggestions on issue https://github.com/getsentry/sentry-javascript/issues/6858, such as :

None of these suggestions worked for me.

jelling commented 1 year ago

Don't know if it's related for certain, but I'm seeing the same issue with Sentry.setUser() with a React app. My code is super-simple and I've verified the values are being passed in.

  const onSignIn = (res: any, redirectUrl: any) => {
    Sentry.setUser({
      id: res.user.uid,
      username: res.user.displayName,
      email: res.user.email,
    });
  };

Could be a separate issue or could be an ingestion issue if it's happening across SDKs.

AbhiPrasad commented 1 year ago

Could you pass in debug: true in your Sentry.init config as see what the debug logs say?

maybe you're trying to call Sentry.setUser when sentry hasn't initialized yet? I've seen that before.

Otherwise a reproduction of some kind would help us a lot!

jelling commented 1 year ago

My issue was that I was looking at the user tag:

image

And expecting to see the user name / email there. But it's down below in the page. It would be nice if the user name was visible higher up imho.

lforst commented 1 year ago

@naofalleoagusta The reason you don't have a user show up on your event is that middleware (and any other edge runtime features) basically runs in its own process. Any context you give to Sentry in middleware is only available for things happening inside the middleware.

The event you shared was inside a server component - which is in a different context than the middleware. If you want the user recorded for errors there, you also need to set the user in that context.

I wouldn't say this is by design but rather how Next.js works.

Closing this because it's not something we can (easily) change from the SDK's side and we're not planning on implementing user propagation across Next.js runtimes at the moment.