> ## Documentation Index
> Fetch the complete documentation index at: https://auth0.generaltranslation.app/llms.txt
> Use this file to discover all available pages before exploring further.

> Describes how to use the MFA API to challenge users who lose access to their device or account using recovery codes.

# Challenge with Recovery Codes

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              processedNode = processedNode.replace(new RegExp(key, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        let processedChildren = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          processedChildren = processedChildren.replace(new RegExp(key, "g"), value);
        }
        setProcessedChildren(processedChildren);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
      {processedChildren}
    </CodeBlock>;
};

When [recovery codes are enabled](/docs/secure/multi-factor-authentication/configure-recovery-codes-for-mfa) for your tenant, Auth0 automatically generates them when a user enrolls with <Tooltip tip="Multi-factor authentication (MFA): User authentication process that uses a factor in addition to username and password such as a code via SMS." cta="View Glossary" href="/docs/glossary?term=multi-factor+authentication">multi-factor authentication</Tooltip> (MFA). The user should save the recovery code. This code can later be used if the user loses access to the device or account used for MFA.

When recovery codes are disabled the MFA API will not return a recovery code when you associate a user's first MFA factor and users cannot authenticate with a recovery code.

You can enable users to authenticate with a recovery code using the MFA API.

1. Prompt the user for their recovery code. That value should be entered in the application for the user to authenticate.

   <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
     Auth0 does not generate recovery codes for DUO and for the legacy `google-authenticator` factor.
   </Callout>
2. Authenticate with recovery code. Call the OAuth Token endpoint with the recovery code to authenticate and generate a new recovery code. You need to specify the following parameters:

   <table class="table">
     <thead>
       <tr>
         <th>Parameter</th>
         <th>Value</th>
       </tr>
     </thead>

     <tbody>
       <tr>
         <td><code>grant\_type</code></td>
         <td><code>[http://auth0.com/oauth/grant-type/mfa-recovery-code](http://auth0.com/oauth/grant-type/mfa-recovery-code)</code></td>
       </tr>

       <tr>
         <td><code>recovery\_code</code></td>
         <td>The recovery code provided by the user.</td>
       </tr>
     </tbody>
   </table>

<AuthCodeGroup>
  ```bash cURL theme={null}
     curl --request POST \
  --url 'https://{yourDomain}/oauth/token' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=http://auth0.com/oauth/grant-type/mfa-recovery-code \
  --data 'client_id={yourClientId}' \
  --data 'client_secret={yourClientSecret}' \
  --data 'mfa_token={mfaToken}' \
  --data 'recovery_code={recoveryCode}'

  ```

  ```csharp C# theme={null}
     var client = new RestClient("https://{yourDomain}/oauth/token");
  var request = new RestRequest(Method.POST);
  request.AddHeader("content-type", "application/x-www-form-urlencoded");
  request.AddParameter("application/x-www-form-urlencoded", "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-recovery-code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&recovery_code=%7BrecoveryCode%7D", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);

  ```

  ```go Go theme={null}
     package main

  import (
     "fmt"
     "strings"
     "net/http"
     "io/ioutil"
  )

  func main() {

     url := "https://{yourDomain}/oauth/token"

     payload := strings.NewReader("grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-recovery-code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&recovery_code=%7BrecoveryCode%7D")

     req, _ := http.NewRequest("POST", url, payload)

     req.Header.Add("content-type", "application/x-www-form-urlencoded")

     res, _ := http.DefaultClient.Do(req)

     defer res.Body.Close()
     body, _ := ioutil.ReadAll(res.Body)

     fmt.Println(res)
     fmt.Println(string(body))

  }

  ```

  ```java Java theme={null}
     HttpResponse<String> response = Unirest.post("https://{yourDomain}/oauth/token")
  .header("content-type", "application/x-www-form-urlencoded")
  .body("grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-recovery-code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&recovery_code=%7BrecoveryCode%7D")
  .asString();

  ```

  ```javascript Node.JS theme={null}
     var axios = require("axios").default;

  var options = {
  method: 'POST',
  url: 'https://{yourDomain}/oauth/token',
  headers: {'content-type': 'application/x-www-form-urlencoded'},
  data: new URLSearchParams({
     grant_type: 'http://auth0.com/oauth/grant-type/mfa-recovery-code',
     client_id: '{yourClientId}',
     client_secret: '{yourClientSecret}',
     mfa_token: '{mfaToken}',
     recovery_code: '{recoveryCode}'
  })
  };

  axios.request(options).then(function (response) {
  console.log(response.data);
  }).catch(function (error) {
  console.error(error);
  });

  ```

  ```objc Obj-C theme={null}
     #import <Foundation/Foundation.h>

  NSDictionary *headers = @{ @"content-type": @"application/x-www-form-urlencoded" };

  NSMutableData *postData = [[NSMutableData alloc] initWithData:[@"grant_type=http://auth0.com/oauth/grant-type/mfa-recovery-code" dataUsingEncoding:NSUTF8StringEncoding]];
  [postData appendData:[@"&client_id={yourClientId}" dataUsingEncoding:NSUTF8StringEncoding]];
  [postData appendData:[@"&client_secret={yourClientSecret}" dataUsingEncoding:NSUTF8StringEncoding]];
  [postData appendData:[@"&mfa_token={mfaToken}" dataUsingEncoding:NSUTF8StringEncoding]];
  [postData appendData:[@"&recovery_code={recoveryCode}" dataUsingEncoding:NSUTF8StringEncoding]];

  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/oauth/token"]
                                                        cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                     timeoutInterval:10.0];
  [request setHTTPMethod:@"POST"];
  [request setAllHTTPHeaderFields:headers];
  [request setHTTPBody:postData];

  NSURLSession *session = [NSURLSession sharedSession];
  NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                  if (error) {
                                                     NSLog(@"%@", error);
                                                  } else {
                                                     NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                     NSLog(@"%@", httpResponse);
                                                  }
                                            }];
  [dataTask resume];

  ```

  ```php PHP theme={null}
     $curl = curl_init();

  curl_setopt_array($curl, [
  CURLOPT_URL => "https://{yourDomain}/oauth/token",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-recovery-code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&recovery_code=%7BrecoveryCode%7D",
  CURLOPT_HTTPHEADER => [
     "content-type: application/x-www-form-urlencoded"
  ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
  echo "cURL Error #:" . $err;
  } else {
  echo $response;
  }

  ```

  ```python Python theme={null}
     import http.client

  conn = http.client.HTTPSConnection("")

  payload = "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-recovery-code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&recovery_code=%7BrecoveryCode%7D"

  headers = { 'content-type': "application/x-www-form-urlencoded" }

  conn.request("POST", "/{yourDomain}/oauth/token", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))

  ```

  ```ruby Ruby theme={null}
     require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/oauth/token")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Post.new(url)
  request["content-type"] = 'application/x-www-form-urlencoded'
  request.body = "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-recovery-code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&recovery_code=%7BrecoveryCode%7D"

  response = http.request(request)
  puts response.read_body

  ```

  ```swift Swift theme={null}
     import Foundation

  let headers = ["content-type": "application/x-www-form-urlencoded"]

  let postData = NSMutableData(data: "grant_type=http://auth0.com/oauth/grant-type/mfa-recovery-code".data(using: String.Encoding.utf8)!)
  postData.append("&client_id={yourClientId}".data(using: String.Encoding.utf8)!)
  postData.append("&client_secret={yourClientSecret}".data(using: String.Encoding.utf8)!)
  postData.append("&mfa_token={mfaToken}".data(using: String.Encoding.utf8)!)
  postData.append("&recovery_code={recoveryCode}".data(using: String.Encoding.utf8)!)

  let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/oauth/token")! as URL,
                                         cachePolicy: .useProtocolCachePolicy,
                                      timeoutInterval: 10.0)
  request.httpMethod = "POST"
  request.allHTTPHeaderFields = headers
  request.httpBody = postData as Data

  let session = URLSession.shared
  let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
     print(error)
  } else {
     let httpResponse = response as? HTTPURLResponse
     print(httpResponse)
  }
  })

  dataTask.resume()

  ```
</AuthCodeGroup>

3. Prompt user to capture recovery code. If the call is successful, you'll get the authentication tokens and a new recovery code:

   ```json lines theme={null}
   {
       "access_token": "O3...H4",
       "id_token": "eyJh...w",
       "scope": "openid profile",
       "expires_in": 86400,
       "recovery_code": "K6LGLV3RSH3VERMKET8L7QKU",
       "token_type": "Bearer"
   }
   ```

4. Notify the user that a new recovery code was generated and ask them to capture it.

## Learn more

* [Enroll and Challenge SMS and Voice Authenticators](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-challenge-sms-voice-authenticators)
* [Enroll and Challenge Push Authenticators](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-push-authenticators)
* [Enroll and Challenge OTP Authenticators](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-otp-authenticators)
* [Enroll and Challenge Email Authenticators](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-email-authenticators)
* [Auth0 MFA API](/docs/secure/multi-factor-authentication/multi-factor-authentication-developer-resources/mfa-api)
* [Manage Authentication Factors with Authentication API](/docs/secure/multi-factor-authentication/manage-mfa-auth0-apis/manage-authenticator-factors-mfa-api)
