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

handleCallback post-processing #1613

Open
5 tasks done
jamesarosen opened this issue Dec 20, 2023 · 4 comments
Open
5 tasks done

handleCallback post-processing #1613

jamesarosen opened this issue Dec 20, 2023 · 4 comments

Comments

@jamesarosen
Copy link

Checklist

  • I have looked into the Readme, Examples, and FAQ and have not found a suitable solution or answer.
  • I have looked into the API documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have searched the Auth0 Community forums and have not found a suitable solution or answer.
  • I agree to the terms within the Auth0 Code of Conduct.

Describe the problem you'd like to have solved

I'm trying to do some post-processing in the callback handler:

// pages/api/auth/[auth0].ts

export default handleAuth({
  callback: async (req: NextApiRequest, res: NextApiResponse) => {
    // default session initialization:
    await handleCallback(req, res);

    // store the token in the backend for authentication / authorization:
    const { accessToken } = await getAccessToken(req, res);
    const success = await db.addValidAccessToken(accessToken);
    if (!success) {
      // what to do here?
    }
  }
})

Option 1: Throw an Error

if (!success) {
  const error = new Error('Error signing in');
  error.status = error.statusCode = 500;
  throw error;
}

The problem with this is that @auth0/nextjs-auth0 overrides my status with 400 and its own error message. The UI is quite poor.

Option 2: Modify res

if (!success) {
  res.redirect('/login-error');
}

This doesn't do anything because the original handler succeeded, so the modifications to the response are discarded.

Describe the ideal solution

I'd like to be able to replace the Response with one of my own even if the callback succeeded. Ideally, I'd like to be able to render my application's error page.

Alternatives and current workarounds

No response

Additional context

The handleCallback docs have some information on customizing the callback, but not on modifying the response or much on error handling.

This issue suggests using res.redirect, but that doesn't work here because handleCallback already finalized res.

@nocodehummel
Copy link

@jamesarosen, maybe the below is of help.

async function authenticationCallback(
    req: NextApiRequest,
    res: NextApiResponse,
    session: Session
): Promise<Session | undefined> {
    const user = await User.upsertUser();

    if (user.isNew) {
        console.log('Redirect to update profile.');
        res.setHeader('location', '/profile');
    } else session.user = setSessionUser(session, user);
    return session;
}

export default handleAuth({
    async callback(req: NextApiRequest, res: NextApiResponse) {
        try {
            await handleCallback(req, res, { afterCallback: authenticationCallback });
        } catch (error) {
            console.error('Callback:', error);
            res.redirect('/');
        }
    },
});

@jamesarosen
Copy link
Author

afterCallback is definitely the thing I'm looking for!

I'm using the App Router and thus NextRequest and NextResponse. Thus, the signature for my afterCallback needs to be

type AfterCallbackAppRoute = (
  req: NextRequest,
  session: Session,
  state?: { [key: string]: any }
) => Promise<Session | Response | undefined> | Session | Response | undefined;

In that callback, I want to call auth0.getAccessToken so I can add it as a Bearer token on the upstream request I'm going to make. That requires a NextResponse. I can easily create one:

async function afterCallback(req: NextRequest, session: Session, state?: { [key: string]: any }) {
  const { accessToken } = await auth0.getAccessToken(req, res);
  await fetch('https://api.example.com', { headers: { authentication: `Bearer ${accessToken}` } });
}

But now I'm stuck with an extra res that might have set-cookie headers on it from Auth0. I can't figure out how to merge that with the result of auth0.handleCallback.

@paolorossig
Copy link

@jamesarosen did you find a way to successfully use the Response or NextResponse object in the afterCallback on App Router?

@jamesarosen
Copy link
Author

Not yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants