Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CallbackHandlerError after Organization Invite #1337

Closed
6 tasks done
kevinmitch14 opened this issue Aug 1, 2023 · 5 comments · Fixed by #1341
Closed
6 tasks done

CallbackHandlerError after Organization Invite #1337

kevinmitch14 opened this issue Aug 1, 2023 · 5 comments · Fixed by #1341
Labels
needs investigation This needs to be investigated further before proceeding

Comments

@kevinmitch14
Copy link

Checklist

Description

Context: I am developing a Next.js multi-tenant application. Subdomains map to organizations.

When inviting a user to an organization through Auth0 and following the invite URL, I am hitting the CallbackHandlerError: Missing state cookie from login request (check login URL, callback URL and cookie config). It looks like the cookie is being set on the wrong domain but I'm not quite sure on this or why. The invite goes through and is accepted on Auth0's end, but on the frontend, the error is shown.

In my callback handler, I am using the subdomain as the redirectUrl, so something along the lines of https://sub.domain.com/api/auth/callback. There are no issues completing a login request, but when accepting an org invite, I run into the issues. My callback+login handler are using the same redirectUri and I'm using the subdomain URL as the returnTo (https://sub.domain.com)

When sending the invitation to an org, the invitation URL is something like https://domain.com/api/auth/login?invitation=...orginization=.... I noticed if I prepend the relevant subdomain to this invitation URL, everything works as expected. I understand the cookie is not getting set in the correct place and as a result the callback is not working but I don't understand where the cookie is actually being set and the reason for this.

I have played around with the cookie config a lot. Setting the cookie domain to domain.com/.domain.com/sub.domain.com does allow the invite to be accepted and redirect to occur properly but then I can't log out. Logging out seems to clear the cookies, but then they appear again straight away. I have also tried SameSite=none and Secure=true but to no avail.

Unfortunately it is not possible to append the organization to the Application Login URI on Auth0 the same way it is possible to do so on the Allowed Callback URLs. Not too sure on how to proceed here.

Thanks!

Login Handler

login: handleLogin((request: NextRequest) => {
    const hostname = headers().get("host");
    const url = request.nextUrl;
    const searchParams = Object.fromEntries(url.searchParams.entries());
    const { invitation, organization, ...rest } = searchParams;
    let subdomain = getSubdomain(hostname) || rest.organization_name;
 
    return {
      authorizationParams: {
        invitation,
        redirect_uri: "https://sub.domain.com/api/auth/callback",
        organization: organization || organisationsMap.get(subdomain!),
        ...rest,
      },
      returnTo: "https://sub.domain.com",
    };
  }),

Callback Handler

callback: handleCallback((request: NextRequest) => {
    const hostname = headers().get("host");
    const subdomain = getSubdomain(hostname);
    const url = request.nextUrl;
    const searchParams = Object.fromEntries(url.searchParams.entries());
    const { organization, ...rest } = searchParams;
    const redirectURL = "https://subdomain.domain/api/auth/callback";
    return {
      organization: organization || organisationsMap.get(subdomain!),
      redirectUri: redirectURL,
      authorizationParams: {
        ...rest,
        redirect_uri: redirectURL,
      },
    };
  }),

Reproduction

  1. Send invite via Auth0 dashboard
  2. Follow invitation link in email or through dashboard
  3. Enter new password
  4. Hit error

Additional context

No response

nextjs-auth0 version

3.0.0

Next.js version

13.4.12

Node.js version

18.x

@adamjmcgrath
Copy link
Contributor

Setting the cookie domain to domain.com/.domain.com/sub.domain.com does allow the invite to be accepted and redirect to occur properly but then I can't log out. Logging out seems to clear the cookies, but then they appear again straight away.

Setting the cookie domain to the naked domain should allow you to logout, could you share a HAR file (with any secrets redacted) of logging out and then being logged back in again and I'd be happy to investigate.

@adamjmcgrath adamjmcgrath added the needs investigation This needs to be investigated further before proceeding label Aug 2, 2023
@kevinmitch14
Copy link
Author

kevinmitch14 commented Aug 2, 2023

Hey Adam,

Ultimately, I would like to keep the cookies scoped to the correct subdomain. Completing a regular login on a subdomain results in the appSession cookie domain value being subdomain.domain.com so I think it makes sense to have same behaviour for invite+login

@kevinmitch14
Copy link
Author

kevinmitch14 commented Aug 2, 2023

In addition, here is a happy path version where I don't set any cookie domain settings. Instead of following the invite URL, I prepend the subdomain to it and everything works perfectly. ie. subdomain.domain.com/api/auth/login?invitation...

Can complete invite, and log out, no issues. Redirect URIs are same in both.

@adamjmcgrath
Copy link
Contributor

Thanks for sharing the HAR file. I can see that the domain is not being included in the Set-Cookie header when /api/auth/logout is deleting the appSession cookie.

This looks like a bug in NextResponse.cookies.delete - have raised a PR to fix vercel/edge-runtime#507 (But I will also ship a workaround in the interim)

Ultimately, I would like to keep the cookies scoped to the correct subdomain.

You want the state cookie scoped to the naked domain (so you don't get the "CallbackHandlerError: Missing state cookie from login request") and the session cookies scoped to the subdomain. Currently both cookies share the same config so this is not possible, but I plan to make the state cookie name configurable, so I will make the other options (inc path and domain) configurable to - as part of #1297

@kevinmitch14
Copy link
Author

Thanks a lot @adamjmcgrath!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs investigation This needs to be investigated further before proceeding
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants