Switch Organizations using Next.js

Hello there!

There are a few other topics on these forums relating to this topic, but none of them specifically use next.js, and I wasn’t able to easily replicate what those others are asking.

When users login to our application, they are presented with the ability to create an organization.
Under the hood, we do the following on our backend:

  1. create the org
  2. Add the currently authenticated user to that organization
  3. Enable various connections in that organization so when the user re-auths under the org, they can continue to actually log in.

Now, the problematic part is how we can re-authenticate the user under the organization such that the org_id appears in their JWT token.

I tried creating a serverless function that checks the user’s organizations and redirects them to the login page with the organization parameter set. However, after inspecting the JWT token, they still don’t have the org information in the token.

Example of the redirect function:

import { withApiAuthRequired } from '@auth0/nextjs-auth0';

export default withApiAuthRequired(async function (req, res) {
  const orgId = "<redacted>";

  return res.redirect(`/api/auth/login?organization=${orgId}`);
});

If I can get this to work, ideally this would suffice for the initial org creation, as well as subsequent visits to our page, as we would hit this call and automatically redirect them through the org login flow, properly setting their access token.

In an ideal world, the user never actually has to see the organization specific login page. That is more of an implementation detail and the user should only ever have to login a single time (through our general login page.)

Any help is appreciated, and happy to clarify anything that is unclear.

I ended up getting this to [mostly] work how I wanted it to.

I augmented the serverless function to look like so:

import { withApiAuthRequired, handleLogin } from '@auth0/nextjs-auth0';

export default withApiAuthRequired(async function (req, res) {
  const orgId = req.query.orgId;
 // logic to make sure the org id provided actually exists, and that the user is a member of it.

    return handleLogin(req, res, {
      authorizationParams: {
        organization: orgId,
      },
    });
});

The handshake worked better when using the underlying auth0 handleLogin function instead of redirecting to the already existing login function provided by the library.

Then, in a react component, I simply told the next router to go to that “page” like so:

import { NextRouter } from 'next/router';

export async function forceOrgLogin(
  router: NextRouter,
  orgId?: string
): Promise<boolean> {
  return router.push({
    pathname: '/api/auth/org/redirect',
    query: { orgId },
  });
}

The only thing that would make this better is to be able to make this request using fetch so that the page doesn’t have to go through a full reload. My attempts failed every time due to a CORS error. Not sure why as everything is properly included in the inclusion lists (as auth generally works.)