Resetting MFA when Disabling

I am trying to setup MFA. Enabling the MFA is pretty straight forward but disabling is quite challenging. The use case is:

  1. Users looses MFA device.
  2. User logs in using recovery code
  3. User disables MFA to remove the old enrollment
  4. User re-enables MFA to setup new enrollment with new device

This issue has been covered a bit on this post but the answer is unsatisfactory:

The answer basically indicates the app administrator has to manually reset the user’s MFA. :frowning:

It does mention possibly using the API. After a bit of digging I found:

While WAY more work than it should be it appears the steps might be:

  1. Have user authorize a new authorization token (they would use the recovery code to do so)
  2. Exchange that authorization token for an access token.
  3. Use the access token to make an API call to get a list of the authenticators
  4. Use the access token to make individual API calls to delete each authenticators

Ughhh… So I get working on this. I make a link for step one. Rough code is:

...
params = {
  scope: 'openid profile email read:authenticators remove:authenticators',
  response_type: 'code',
  client_id: client_id,
  state: '....',
  redirect_uri: redirect,
  audience: "https://#{ENV['AUTH0_DOMAIN']}/mfa/",
}

link_to "Disable Two-factor Security", "https://#{ENV['AUTH0_DOMAIN']}/authorize?#{params.to_query}"

This successfully links me off to authenticate (password and 2-factor which I would be using the backup codes in this case). When redirected back to my app I can successfully exchange the authorization code for an access token (I’m actually piggybacking on the omniauth functionality already in my app for this).

Now with my access token I have the following function:

def reset_mfa access_token
  authenticators = JSON.parse RestClient.get(
    "https://#{ENV["AUTH0_DOMAIN"]}/mfa/authenticators",
    Authorization: "Bearer #{access_token}",
    'Content-Type' => 'application/json'
  ).body

  for authenticator in authenticators
    RestClient.delete "https://#{ENV['AUTH0_DOMAIN']}/mfa/authenticators/#{authenticator['id']}", Authorization: "Bearer #{access_token}"
  end
end

When the HTTP GET request is made I get back the following response:

"{\"error\":\"invalid_grant\",\"error_description\":\"The mfa_token provided is invalid. Try getting a new token.\"}"

This feels like it’s looking for a MFA code rather than an access token. The only thing I could find was:

But this is for someone making an association so passing Auth0 an MFA token makes sense. But to get a list of current authenticators the error doesn’t make sense.

Hello, please excuse me if your problem is no longer relevant but I hope my post can help someone else. First of all, I can’t tell why retrieving a list of authenticators doesn’t work for you but I made a demo app where a user can manage his own authenticator (add new ones or remove the old ones) but only if he still has access to one of existing MFA devices. There are 2 problems with this approach: it’s not really a “reset” (admin still has to do it manually) and you can’t delete your “recovery-code” device this way because Auth0 will return “You cannot delete a recovery-code authenticator” error.

The good news is that you can delete all MFA devices for a user (basically your initial goal) by first listing them using GET /api/v2/users/{id}/enrollments method and then deleting them one-by-one using DELETE /api/v2/guardian/enrollments/{id} method. Please note that the first method (get enrollments) doesn’t use the same format as “get authenticators”. For example, it won’t show a “recovery-code” device, but it will delete it along with the factor that was created first (and caused recovery code to be created). But if user deletes every factor except recovery code then this method won’t work either and you will have to use manual reset on Auth0 website. I find this whole system very confusing.

Wow, exactly the problem that I have.
Hi @konrad.sopala Refering to this last comemnt and this othet topic Remove Recovery Code thru Mobile App
It looks like it is a problem.

Steps to reproduce:

  1. Enroll a user MFA using Guardian app and not Google Authenticator.
  2. Now once the user has MFA setup and there are 2 MFA (which is ok)
  3. Delete user account from guardian app.
  4. It leaves only recovery code

Problem: GET /api/v2/users/{id}/enrollments does not return anything to delete it. and on re-login it wont prompt me to set a new mfa. Someone has to login to Auth0 dashboard and reset it manually.

1 Like

I’m having the same problem, but I noticed the recovery-code entry isn’t deleted only when the user has others entries under “guardian_authenticators” attribute, even if those entries are “confirmed”: false.
This happens when the user start to set up the MFA then give up. There will be a non-confirmed entry there forever. It doesnt matter if it’s guardian or google-authenticator in my tests.

The result is the same, Auth0 only ask for verification code and do not prompt to set a new mfa.

I think we resolved it by updating to the latest api version.

Hey Naptel! I’m having the problem even in the Auth0 API web interface. The recovery key is never deleted if the user has other MFA entries “confirmed”: false.

To have multiple entries the user has to skip the MFA Setup… and then tries to log in again. Every time a new entry is created.