Enroll and Challenge SMS and Voice Authenticators

Auth0 provides a built-in MFA enrollment and authentication flow using Universal Login. However, if you want to create your own user interface, you can use the MFA API to accomplish it.

Prerequisites

Before you can use the MFA APIs, you'll need to enable the MFA grant type for your application. Go to Auth0 Dashboard > Applications > Advanced Settings > Grant Types and select MFA.

Enroll with SMS or voice

Get MFA token

Depending on when you are triggering enrollment, you can obtain an access token for using the MFA API in different ways:

Enroll authenticator

Make a POST request to the MFA Associate endpoint to enroll the user's authenticator. The bearer token required by this endpoint is the MFA token obtained in the previous step.

To enroll with SMS or voice, they enroll with a phone number that can be challenged either with SMS or voice. Specific the parameters below to call the endpoint. The oob_channels parameter indicates how you want to send the code to the user (SMS or voice).


curl --request POST \
  --url 'https://{yourDomain}/mfa/associate' \
  --header 'authorization: Bearer {mfaToken}' \
  --header 'content-type: application/json' \
  --data '{ "authenticator_types": ["oob"], "oob_channels": ["sms"], "phone_number": "+11...9" }'

feedbackSection.helpful

/
var client = new RestClient("https://{yourDomain}/mfa/associate");
var request = new RestRequest(Method.POST);
request.AddHeader("authorization", "Bearer {mfaToken}");
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"sms\"], \"phone_number\": \"+11...9\" }", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

feedbackSection.helpful

/
package main

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

func main() {

	url := "https://{yourDomain}/mfa/associate"

	payload := strings.NewReader("{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"sms\"], \"phone_number\": \"+11...9\" }")

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

	req.Header.Add("authorization", "Bearer {mfaToken}")
	req.Header.Add("content-type", "application/json")

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

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

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

}

feedbackSection.helpful

/
HttpResponse<String> response = Unirest.post("https://{yourDomain}/mfa/associate")
  .header("authorization", "Bearer {mfaToken}")
  .header("content-type", "application/json")
  .body("{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"sms\"], \"phone_number\": \"+11...9\" }")
  .asString();

feedbackSection.helpful

/
var axios = require("axios").default;

var options = {
  method: 'POST',
  url: 'https://{yourDomain}/mfa/associate',
  headers: {authorization: 'Bearer {mfaToken}', 'content-type': 'application/json'},
  data: {authenticator_types: ['oob'], oob_channels: ['sms'], phone_number: '+11...9'}
};

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

feedbackSection.helpful

/
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"authorization": @"Bearer {mfaToken}",
                           @"content-type": @"application/json" };
NSDictionary *parameters = @{ @"authenticator_types": @[ @"oob" ],
                              @"oob_channels": @[ @"sms" ],
                              @"phone_number": @"+11...9" };

NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/mfa/associate"]
                                                       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];

feedbackSection.helpful

/
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://{yourDomain}/mfa/associate",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"sms\"], \"phone_number\": \"+11...9\" }",
  CURLOPT_HTTPHEADER => [
    "authorization: Bearer {mfaToken}",
    "content-type: application/json"
  ],
]);

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

curl_close($curl);

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

feedbackSection.helpful

/
import http.client

conn = http.client.HTTPSConnection("")

payload = "{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"sms\"], \"phone_number\": \"+11...9\" }"

headers = {
    'authorization': "Bearer {mfaToken}",
    'content-type': "application/json"
    }

conn.request("POST", "/{yourDomain}/mfa/associate", payload, headers)

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

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

feedbackSection.helpful

/
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://{yourDomain}/mfa/associate")

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["authorization"] = 'Bearer {mfaToken}'
request["content-type"] = 'application/json'
request.body = "{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"sms\"], \"phone_number\": \"+11...9\" }"

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

feedbackSection.helpful

/
import Foundation

let headers = [
  "authorization": "Bearer {mfaToken}",
  "content-type": "application/json"
]
let parameters = [
  "authenticator_types": ["oob"],
  "oob_channels": ["sms"],
  "phone_number": "+11...9"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/mfa/associate")! 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()

feedbackSection.helpful

/

Parameter Value
authentication_types [oob]
oob_channels [sms] or [voice]
phone_number +11...9, the phone number E.164 format

If successful, you receive a response like this:

{
  "authenticator_type": "oob",
  "binding_method": "prompt",
  "recovery_codes": [ "N3BGPZZWJ85JLCNPZBDW6QXC" ],
  "oob_channel": "sms",
  "oob_code": "ata6daXAiOi..."
}
`

feedbackSection.helpful

/

If you get a User is already enrolled error, the user already has an MFA factor enrolled. Before associating another factor with the user, you must challenge the user with the existing factor.

If this is the first time the user is associating an authenticator, you'll notice the response includes recovery_codes. Recovery codes are used to access the user's account in the event that they lose access to the account or device used for their second-factor authentication. These are one-time usable codes, and new ones are generated as necessary.

Confirm SMS or voice enrollment

Users should receive a message with a 6-digit code that they need to provide to the application.

To complete enrollment, make a POST request to the OAuth Token endpoint. You need to include the oob_code returned in the previous response, and the binding_code with the value received in the message.


curl --request POST \
  --url 'https://{yourDomain}/oauth/token' \
  --header 'authorization: Bearer {mfaToken}' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=http://auth0.com/oauth/grant-type/mfa-oob \
  --data 'client_id={yourClientId}' \
  --data 'client_secret={yourClientSecret}' \
  --data 'mfa_token={mfaToken}' \
  --data 'oob_code={oobCode}' \
  --data 'binding_code={userOtpCode}'

feedbackSection.helpful

/
var client = new RestClient("https://{yourDomain}/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("authorization", "Bearer {mfaToken}");
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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserOtpCode%7D", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

feedbackSection.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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserOtpCode%7D")

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

	req.Header.Add("authorization", "Bearer {mfaToken}")
	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))

}

feedbackSection.helpful

/
HttpResponse<String> response = Unirest.post("https://{yourDomain}/oauth/token")
  .header("authorization", "Bearer {mfaToken}")
  .header("content-type", "application/x-www-form-urlencoded")
  .body("grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserOtpCode%7D")
  .asString();

feedbackSection.helpful

/
var axios = require("axios").default;

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

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

feedbackSection.helpful

/
#import <Foundation/Foundation.h>

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

NSMutableData *postData = [[NSMutableData alloc] initWithData:[@"grant_type=http://auth0.com/oauth/grant-type/mfa-oob" 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:[@"&oob_code={oobCode}" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&binding_code={userOtpCode}" 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];

feedbackSection.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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserOtpCode%7D",
  CURLOPT_HTTPHEADER => [
    "authorization: Bearer {mfaToken}",
    "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;
}

feedbackSection.helpful

/
import http.client

conn = http.client.HTTPSConnection("")

payload = "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserOtpCode%7D"

headers = {
    'authorization': "Bearer {mfaToken}",
    '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"))

feedbackSection.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["authorization"] = 'Bearer {mfaToken}'
request["content-type"] = 'application/x-www-form-urlencoded'
request.body = "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserOtpCode%7D"

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

feedbackSection.helpful

/
import Foundation

let headers = [
  "authorization": "Bearer {mfaToken}",
  "content-type": "application/x-www-form-urlencoded"
]

let postData = NSMutableData(data: "grant_type=http://auth0.com/oauth/grant-type/mfa-oob".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("&oob_code={oobCode}".data(using: String.Encoding.utf8)!)
postData.append("&binding_code={userOtpCode}".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()

feedbackSection.helpful

/

If the call was successful, you'll receive a response in the following format, containing the access token:

{
  "id_token": "eyJ...i",
  "access_token": "eyJ...i",
  "expires_in": 600,
  "scope": "openid profile",
  "token_type": "Bearer"
}

feedbackSection.helpful

/

Challenge with SMS or voice

Get MFA token

Get an MFA token following the steps described in Authenticate With Resource Owner Password Grant and MFA.

Retrieve enrolled authenticators

To challenge the user, you need the authenticator_id for the factor you want to challenge. You can list all enrolled authenticators using the MFA Authenticators endpoint:


curl --request GET \
  --url 'https://{yourDomain}/mfa/authenticators' \
  --header 'authorization: Bearer MFA_TOKEN' \
  --header 'content-type: application/json'

feedbackSection.helpful

/
var client = new RestClient("https://{yourDomain}/mfa/authenticators");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Bearer MFA_TOKEN");
request.AddHeader("content-type", "application/json");
IRestResponse response = client.Execute(request);

feedbackSection.helpful

/
package main

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

func main() {

	url := "https://{yourDomain}/mfa/authenticators"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("authorization", "Bearer MFA_TOKEN")
	req.Header.Add("content-type", "application/json")

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

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

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

}

feedbackSection.helpful

/
HttpResponse<String> response = Unirest.get("https://{yourDomain}/mfa/authenticators")
  .header("authorization", "Bearer MFA_TOKEN")
  .header("content-type", "application/json")
  .asString();

feedbackSection.helpful

/
var axios = require("axios").default;

var options = {
  method: 'GET',
  url: 'https://{yourDomain}/mfa/authenticators',
  headers: {authorization: 'Bearer MFA_TOKEN', 'content-type': 'application/json'}
};

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

feedbackSection.helpful

/
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"authorization": @"Bearer MFA_TOKEN",
                           @"content-type": @"application/json" };

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/mfa/authenticators"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"GET"];
[request setAllHTTPHeaderFields:headers];

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

feedbackSection.helpful

/
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://{yourDomain}/mfa/authenticators",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => [
    "authorization: Bearer MFA_TOKEN",
    "content-type: application/json"
  ],
]);

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

curl_close($curl);

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

feedbackSection.helpful

/
import http.client

conn = http.client.HTTPSConnection("")

headers = {
    'authorization': "Bearer MFA_TOKEN",
    'content-type': "application/json"
    }

conn.request("GET", "/{yourDomain}/mfa/authenticators", headers=headers)

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

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

feedbackSection.helpful

/
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://{yourDomain}/mfa/authenticators")

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

request = Net::HTTP::Get.new(url)
request["authorization"] = 'Bearer MFA_TOKEN'
request["content-type"] = 'application/json'

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

feedbackSection.helpful

/
import Foundation

let headers = [
  "authorization": "Bearer MFA_TOKEN",
  "content-type": "application/json"
]

let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/mfa/authenticators")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

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

feedbackSection.helpful

/

You will get a list of authenticators with the following format:

[
    {
        "id": "recovery-code|dev_O4KYL4FtcLAVRsCl",
        "authenticator_type": "recovery-code",
        "active": true
    },
    {
        "id": "sms|dev_NU1Ofuw3Cw0XCt5x",
        "authenticator_type": "oob",
        "active": true,
        "oob_channel": "sms",
        "name": "XXXXXXXX8730"
    },
        {
        "id": "voice|dev_NU1Ofuw3Cw0XCt5x",
        "authenticator_type": "oob",
        "active": true,
        "oob_channel": "voice",
        "name": "XXXXXXXX8730"
    }
]

feedbackSection.helpful

/

Challenge user with OTP

To trigger a challenge, POST to the MFA Challenge endpoint using the corresponding authenticator_id and the mfa_token.


codeblockOld.header.login.configureSnippet
curl --request POST \
  --url 'https://{yourDomain}/mfa/challenge' \
  --header 'content-type: application/json' \
  --data '{ "client_id": "{yourClientId}",  "client_secret": "{yourClientSecret}", "challenge_type": "oob", "authenticator_id": "sms|dev_NU1Ofuw3Cw0XCt5x", "mfa_token": "{mfaToken}" }'

feedbackSection.helpful

/
codeblockOld.header.login.configureSnippet
var client = new RestClient("https://{yourDomain}/mfa/challenge");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret}\", \"challenge_type\": \"oob\", \"authenticator_id\": \"sms|dev_NU1Ofuw3Cw0XCt5x\", \"mfa_token\": \"{mfaToken}\" }", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

feedbackSection.helpful

/
codeblockOld.header.login.configureSnippet
package main

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

func main() {

	url := "https://{yourDomain}/mfa/challenge"

	payload := strings.NewReader("{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret}\", \"challenge_type\": \"oob\", \"authenticator_id\": \"sms|dev_NU1Ofuw3Cw0XCt5x\", \"mfa_token\": \"{mfaToken}\" }")

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

	req.Header.Add("content-type", "application/json")

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

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

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

}

feedbackSection.helpful

/
codeblockOld.header.login.configureSnippet
HttpResponse<String> response = Unirest.post("https://{yourDomain}/mfa/challenge")
  .header("content-type", "application/json")
  .body("{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret}\", \"challenge_type\": \"oob\", \"authenticator_id\": \"sms|dev_NU1Ofuw3Cw0XCt5x\", \"mfa_token\": \"{mfaToken}\" }")
  .asString();

feedbackSection.helpful

/
codeblockOld.header.login.configureSnippet
var axios = require("axios").default;

var options = {
  method: 'POST',
  url: 'https://{yourDomain}/mfa/challenge',
  headers: {'content-type': 'application/json'},
  data: {
    client_id: '{yourClientId}',
    client_secret: '{yourClientSecret}',
    challenge_type: 'oob',
    authenticator_id: 'sms|dev_NU1Ofuw3Cw0XCt5x',
    mfa_token: '{mfaToken}'
  }
};

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

feedbackSection.helpful

/
codeblockOld.header.login.configureSnippet
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"content-type": @"application/json" };
NSDictionary *parameters = @{ @"client_id": @"{yourClientId}",
                              @"client_secret": @"{yourClientSecret}",
                              @"challenge_type": @"oob",
                              @"authenticator_id": @"sms|dev_NU1Ofuw3Cw0XCt5x",
                              @"mfa_token": @"{mfaToken}" };

NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/mfa/challenge"]
                                                       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];

feedbackSection.helpful

/
codeblockOld.header.login.configureSnippet
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://{yourDomain}/mfa/challenge",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret}\", \"challenge_type\": \"oob\", \"authenticator_id\": \"sms|dev_NU1Ofuw3Cw0XCt5x\", \"mfa_token\": \"{mfaToken}\" }",
  CURLOPT_HTTPHEADER => [
    "content-type: application/json"
  ],
]);

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

curl_close($curl);

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

feedbackSection.helpful

/
codeblockOld.header.login.configureSnippet
import http.client

conn = http.client.HTTPSConnection("")

payload = "{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret}\", \"challenge_type\": \"oob\", \"authenticator_id\": \"sms|dev_NU1Ofuw3Cw0XCt5x\", \"mfa_token\": \"{mfaToken}\" }"

headers = { 'content-type': "application/json" }

conn.request("POST", "/{yourDomain}/mfa/challenge", payload, headers)

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

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

feedbackSection.helpful

/
codeblockOld.header.login.configureSnippet
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://{yourDomain}/mfa/challenge")

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/json'
request.body = "{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret}\", \"challenge_type\": \"oob\", \"authenticator_id\": \"sms|dev_NU1Ofuw3Cw0XCt5x\", \"mfa_token\": \"{mfaToken}\" }"

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

feedbackSection.helpful

/
codeblockOld.header.login.configureSnippet
import Foundation

let headers = ["content-type": "application/json"]
let parameters = [
  "client_id": "{yourClientId}",
  "client_secret": "{yourClientSecret}",
  "challenge_type": "oob",
  "authenticator_id": "sms|dev_NU1Ofuw3Cw0XCt5x",
  "mfa_token": "{mfaToken}"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/mfa/challenge")! 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()

feedbackSection.helpful

/

Complete authentication using received code

If success, you receive the following response:

{
  "challenge_type": "oob",
  "oob_code": "asdae35fdt5...",
  "binding_method": "prompt"
}

feedbackSection.helpful

/

Your application needs to prompt the user for the 6-digit code sent in the message and should be set in the binding_code parameter. You can verify the code and get authentication tokens using the OAuth0 Token endpoint, specifying the binding_code and oob_code returned by the previous call:


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-oob \
  --data 'client_id={yourClientId}' \
  --data 'client_secret={yourClientSecret}' \
  --data 'mfa_token={mfaToken}' \
  --data 'oob_code={oobCode}' \
  --data binding_code=USER_OTP_CODE

feedbackSection.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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=USER_OTP_CODE", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

feedbackSection.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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=USER_OTP_CODE")

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

}

feedbackSection.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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=USER_OTP_CODE")
  .asString();

feedbackSection.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-oob',
    client_id: '{yourClientId}',
    client_secret: '{yourClientSecret}',
    mfa_token: '{mfaToken}',
    oob_code: '{oobCode}',
    binding_code: 'USER_OTP_CODE'
  })
};

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

feedbackSection.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-oob" 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:[@"&oob_code={oobCode}" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&binding_code=USER_OTP_CODE" 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];

feedbackSection.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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=USER_OTP_CODE",
  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;
}

feedbackSection.helpful

/
import http.client

conn = http.client.HTTPSConnection("")

payload = "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=USER_OTP_CODE"

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

feedbackSection.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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=USER_OTP_CODE"

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

feedbackSection.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-oob".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("&oob_code={oobCode}".data(using: String.Encoding.utf8)!)
postData.append("&binding_code=USER_OTP_CODE".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()

feedbackSection.helpful

/

If the call was successful, you'll receive a response in the format below, containing the access token:

{
  "id_token": "eyJ...i",
  "access_token": "eyJ...i",
  "expires_in": 600,
  "scope": "openid profile",
  "token_type": "Bearer"
}

feedbackSection.helpful

/

Note: SMS and invalid code returns are subject to rate limiting. SMS codes can be sent 10 times and refill once per hour, while invalid codes can be returned 10 times and refill once every six minutes.

Learn more