Challenge with Recovery Codes

When recovery codes are enabled for your tenant, Auth0 automatically generates them when a user enrolls with multi-factor authentication (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.

  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:

    Parameter Value
    grant_type http://auth0.com/oauth/grant-type/mfa-recovery-code
    recovery_code The recovery code provided by the user.
    
    
    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}'

    Was this helpful?

    /
    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);

    Was this helpful?

    /
    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))
    
    }

    Was this helpful?

    /
    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();

    Was this helpful?

    /
    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);
    });

    Was this helpful?

    /
    #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];

    Was this helpful?

    /
    $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;
    }

    Was this helpful?

    /
    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"))

    Was this helpful?

    /
    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

    Was this helpful?

    /
    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()

    Was this helpful?

    /

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

    {
        "access_token": "O3...H4",
        "id_token": "eyJh...w",
        "scope": "openid profile",
        "expires_in": 86400,
        "recovery_code": "K6LGLV3RSH3VERMKET8L7QKU",
        "token_type": "Bearer"
    }

    Was this helpful?

    /

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

Learn more