Trigger MFA during user session with nextjs-auth0

I have this feature I want to implement in my NextJS app, using the nextjs-auth0 sdk:

  • When a user logs in, I don’t want the MFA to be triggered immediately after the successful login.
  • When the user accesses certain pages/functions/components within a page (which can only be accessed during the user active session), I want to trigger MFA in my app only ONCE if the MFA has not been triggered before during the active session of the user.
    – When I say “user active session”, I mean the session/time starting when the user successfully logs in, and ending when the user logs out or when their token is no longer valid.

To explain further this feature, imagine this hypothetical case:

  1. user logins to mystreamingservice.com (only logs in with user/password, does not require MFA at that moment).
  2. user is navigating across pages inside mystreamingservice.com during the active session (still does not require MFA at that moment).
  3. when user wants to access billing page inside mystreamingservice.com, I want to trigger MFA so user can provide an OTP (let’s pretend user previously enrolled their cellphone with a custom app, which uses Guardian SDK and other SDKs to generate OTPs).
    3.1. if user provides an OTP correctly, I will give the user access to the information and functions within billing page.
    3.2. if user fails to provide an OTP, I will NOT give the user access to the information and functions within billing page.
  4. user continues navigating inside mystreamingservice.com.
  5. user navigates to billing page again…
    5.1. if user already provided OTP during triggered MFA, I will give access to info and functions within billing page, and user DOES NOT need to provide OTP again during that session.
    5.2. if user hasn’t provided OTP correctly, I will trigger MFA to give the user another chance to provide OTP.
  6. user logs out, and is no longer allowed to navigate to the billing page or any other page within mystreamingservice.com.

I found info about how to configure step-up authentication, and tried to follow the documentation. I created the rule successfully. But in the Configure App section, I haven’t found the correct documentation explaining the state query param in the API:

https://YOUR_DOMAIN/authorize?
        audience=https://YOUR_DOMAIN/userinfo&
        scope=openid&
        response_type=code&
        client_id=YOUR_CLIENT_ID&
        redirect_uri=https://YOUR_APP/callback&
        state=YOUR_OPAQUE_VALUE&
        acr_values=http://schemas.openid.net/pape/policies/2007/06/multi-factor

I get this error:

[BadRequestError]: checks.state argument is missing

, because I am not passing the state param correctly, because I don’t know what does YOUR_OPAQUE_VALUE mean; and I also don’t understand the documentation explaining the Opaque Access Token, and I also haven’t found how to obtain or generate an Opaque Access Token with nextjs-auth0. Can someone explain this concept?

I also tried to use the MFA api, /mfa/challenge, but I get this response:
{"error":"invalid_grant","error_description":"Malformed mfa_token"},
but I haven’t found in the SDK doc information about how to get a mfa_token using the nextjs-auth0 sdk (which I understand uses the Authorization Code Flow for login).

So my question is, can I Trigger MFA during user session using the nextjs-auth0 SDK?


Please include the following information in your post:

  • Which SDK this is regarding: nextjs-auth0
  • SDK Version: “@auth0/nextjs-auth0”: “^1.9.1
  • Platform Version: “next”: “latest”, “react”: “^18.1.0”,
  • Code Snippets/Error Messages/Supporting Details/Screenshots:

Is this a feature request or bug report? No, it is a question.

Hi @margarza

Welcome to Auth0 Community !!!

I don’t know what YOUR_OPAQUE_VALUE

This could be any random string, the state is used to protect against replay attacks. This state will be returning as part of the response from Auth0.

Hope it helps

Thank you
Jeff Ishar

2 Likes

Hi @margarza

In addition to the above you can get further information on how the state parameter can be used via this document https://auth0.com/docs/secure/attack-protection/state-parameters

Warm regards.

1 Like

Thank you, I have one question regarding the OPAQUE_VALUE: Do I have to generate this random string every time the user logs in?

Thank you, I want a bit more of clarification to see if I understood correctly:

  1. I will send the state (which is a random generated value that I generate in my web app, and has to be different from the access token and the id token) as a query string parameter in the /authorize API endpoint.
  2. Auth0 will redirect the user to the callback url.
  3. I need to retrieve that callback url in my code, and validate if it has the state query string parameter and if its value is the same as the state I previously sent in the /authorize endpoint.
    3.1. If both state values are equal, I can authorize the callback request in my web app.
    3.2. If they are NOT equal, I have to reject the callback request in my web app.

Did I understand correctly ?

Hi @margarza
That sounds right to me.

Warm regards.

1 Like

Hi again, I am still getting the checks.state argument is missing error, this is what I have done so far…

I have constructed the /authorize url endpoint with the state query string param correctly :tada::white_check_mark::

https://mytenant.auth0.com/authorize?audience=https://mytenant.auth0.com/userinfo&scope=openid&response_type=code&client_id=MY_CLIENT_ID&redirect_uri=http://mywebapp.com/api/auth/callback&state=randomlyGeneratedStateValue&acr_values=http://schemas.openid.net/pape/policies/2007/06/multi-factor

, so when the user wants to navigate to my hypothetical billing page, I redirect the user to the /authorize url above. Auth0 then displays the MFA Auth0 screen so the user introduces the OTP :white_check_mark:, and validates the OTP correctly :white_check_mark:.

But after the user introduces OTP correctly, Auth0 redirects the browser to this callback url:

http://mywebapp.com/api/auth/callback?code=MN2Z-and_more_characters&state=randomlyGeneratedStateValue 

, and I am still getting the checks.state argument is missing error. Also, in the JS Log Console, I see the url gives status code = 400, Bad Request, because the page in the url above does not exist in my NextJs Web App.

This is the screenshot:

In my Application settings, I have already configured the Allowed Callback Url when I integrated the Login function in my NextJs Web App: http://mywebapp.com/api/auth/callback

… so my next questions are:

  • why am I still getting the check.state argument missing error, even after I added state as a query string param in the /authorize url, and even if the /callback url is adding the code and state params, and the state param in both the authorize and callback urls are the same?
  • and also, what do I have to do to be redirected to the page in my web app where the user was before being redirected to the Auth0 MFA Screen? Do I have to add all the Redirect Urls from my NextJs Web App (i.e. mywebapp.com/billingpage) to the Allowed Callback URLs section in my Application Settings?
  • what else can I do to trigger MFA during the user active session?

I hope I have explained correctly the issue I am facing :raised_hands::pray:, but if anyone has a question, please let me know so I can explain further!

Thank you in advance

Hi @margarza
Are you deployed via Vercel by any chance, if so please can you check this post to see if it helps https://community.auth0.com/t/checks-state-argument-is-missing-in-next-js/70639

Warm regards.