Auth0 Home Blog Docs

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(
    Authorization: "Bearer #{access_token}",
    'Content-Type' => 'application/json'

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

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.