aws-samples / amazon-cognito-passwordless-auth

Passwordless authentication with Amazon Cognito: FIDO2 (WebAuthn, support for Passkeys), Magic Link, SMS OTP Step Up
Apache License 2.0
362 stars 62 forks source link

RespondToAuthChallenge - Got error when clicking on Magic link #189

Open ningo-agilityio opened 2 weeks ago

ningo-agilityio commented 2 weeks ago

Hi owner,

Currently, I followed your sample to implement Passwordless auth on Cognito. But in client side, I'm using another technical stack with Next.js and aws-amplify. After receiving Magic link from email, I got this error when calling confirmSignIn from aws-amplify/auth: error UserUnAuthenticatedException: User needs to be authenticated to call this API. I'm handling Sign In and Verify on different page, so how can I keep session cross tab? Many people is facing the same issue as me https://github.com/aws-amplify/amplify-js/issues/13071. Could you help to look into and support me?

Thanks!

ottokruse commented 2 weeks ago

Hi! I can try but I'd need much more info:

ningo-agilityio commented 2 weeks ago

Hi @ottokruse,

You can see my 2 separated functions for signIn and confirmSignIn as below:

import {
  signIn,
  confirmSignIn,
  getCurrentUser
} from "aws-amplify/auth";
...
export async function handleSignIn(
  prevState: string | undefined,
  formData: FormData
) {
  let redirectLink = "/auth/verify";
  try {
    const tmpSession = await signIn({
      username: String(formData.get("email")),
      options: {
        authFlowType: "CUSTOM_WITHOUT_SRP",
      }
    });
    localStorage.setItem('session', JSON.stringify(tmpSession))

    const currentAuth = await getAuthToken();
    const currentUser = await getCurrentUser();
    console.log('current user after sign in', currentAuth, currentUser)

    setTimeout(async () => {
      if (tmpSession.nextStep.signInStep === "CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE") {
        redirectLink = "/auth/verify";
      }
    }, 1000)
  } catch (error) {
    console.log('error', error)
    return getErrorMessage(error);
  } finally {
    redirect(redirectLink);
  }
}

export async function handleConfirmSignIn(
  prevState: string | undefined,
  formData: FormData
) {
  let redirectLink = "/auth/verify";
  const tmpSession = JSON.parse(localStorage.get('session'))

  try {
    const currentAuth = await getAuthToken();
    const currentUser = await getCurrentUser();
    console.log('current user after sign in', currentAuth, currentUser)

    setTimeout(async () => {
      const session = await confirmSignIn({
        challengeResponse: String(formData.get("token")),
      });
      if (session.isSignedIn) {
        const user = await getCurrentUser();
        console.log('isSignedIn', user);
        redirectLink = "dashboard";
      }
    }, 1000)
  } catch (error) {
    console.log('error', error)
    return getErrorMessage(error);
  } finally {
    redirect(redirectLink);
  }
}
ottokruse commented 2 weeks ago

Don't see the problem or solution quickly from this code and struggle to see the link with the Passwordless lib as well. But is it an option for you to auto confirm users ?

ningo-agilityio commented 1 week ago

@ottokruse The issue is when I call confirmSignIn from another page, this function will throw error error UserUnAuthenticatedException: User needs to be authenticated to call this API.