Manage Authentication Factors with Authentication API
Auth0 provides several API endpoints to help you manage the authenticators you're using with an application for multi-factor authentication (MFA). You can use these endpoints to build a complete user interface for letting users manage their authenticator factors.
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.
Get MFA API access tokens
To call the MFA API to manage enrollments, you first need to obtain an access token for the MFA API.
To use the MFA API as part of an authentication flow, you can follow the steps detailed in Authenticate With Resource Owner Password Grant and MFA. If you are building a user interface to manage authentication factors, you'll need to obtain a token you can use for the MFA API at any moment, not only during authentication.
Universal Login
If you are using Universal Login, redirect to the Authorize endpoint, specifying the https://{yourDomain}/mfa/
audience, before using calling the MFA API.
Resource owner password grant
If you are using the Resource Owner Password Grant (ROPG), you have 3 options:
Ask for the
https://{yourDomain}/mfa/
audience when logging-in, and use a refresh token to refresh it later.If you need to list and delete authenticators, ask the user to authenticate again with
/oauth/token
, specifying thehttps://{yourDomain}/mfa/
audience. Users will need to complete MFA before being able to list and/or delete authentication factors.If you only need to list authenticators, ask the user to authenticate again using
/oauth/token
with username/password. The endpoint will return anmfa_required
error, and anmfa_token
you can use to list authenticators. Users will need to provide their password to see their authenticators.
Scopes
When you request a token for the MFA audience, you can request the following scopes:
Scope | Description |
---|---|
enroll |
To enroll a new authenticator. |
read:authenticators |
To list existing authenticators. |
remove:authenticators |
To delete an authenticator. |
List authenticators
To get a list of the authenticators for a user, you can call the MFA Authenticators endpoint:
curl --request GET \
--url 'https://{yourDomain}/mfa/authenticators' \
--header 'authorization: Bearer MFA_TOKEN'
Was this helpful?
var client = new RestClient("https://{yourDomain}/mfa/authenticators");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Bearer MFA_TOKEN");
IRestResponse response = client.Execute(request);
Was this 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")
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.get("https://{yourDomain}/mfa/authenticators")
.header("authorization", "Bearer MFA_TOKEN")
.asString();
Was this helpful?
var axios = require("axios").default;
var options = {
method: 'GET',
url: 'https://{yourDomain}/mfa/authenticators',
headers: {authorization: 'Bearer MFA_TOKEN'}
};
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 = @{ @"authorization": @"Bearer MFA_TOKEN" };
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];
Was this 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"
],
]);
$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("")
headers = { 'authorization': "Bearer MFA_TOKEN" }
conn.request("GET", "/{yourDomain}/mfa/authenticators", headers=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}/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'
response = http.request(request)
puts response.read_body
Was this helpful?
import Foundation
let headers = ["authorization": "Bearer MFA_TOKEN"]
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()
Was this helpful?
You should receive information about the authenticator type(s) in the response:
[
{
"authenticator_type": "recovery-code",
"id": "recovery-code|dev_IsBj5j3H12VAdOIj",
"active": true
},
{
"authenticator_type": "otp",
"id": "totp|dev_nELLU4PFUiTW6iWs",
"active": true,
},
{
"authenticator_type": "oob",
"oob_channel": "sms",
"id": "sms|dev_sEe99pcpN0xp0yOO",
"name": "+1123XXXXX",
"active": true
}
]
Was this helpful?
For the purposes of building a user interface for end users to manage their factors, you should ignore authenticators that have active
as false
. Those authenticators are not confirmed by users, so they can't be used to challenge for MFA.
The MFA API will list the following enrollments depending on the authenticator type:
Authenticator | Actions |
---|---|
Push and OTP | If push is enabled, Auth0 also creates an OTP enrollment. You will see both when listing enrollments. |
SMS and Voice | If both SMS and voice are enabled, when a user enrolls with either SMS or voice, Auth0 automatically creates two authenticators for the phone number, one for SMS and another for voice. |
All verified emails will be listed as authenticators. |
Enroll authenticators
See the following links for details on how to enroll authenticators for different factors:
You can also use the Universal Login flow for enrolling users at any time.
Delete authenticators
To delete an associated authenticator, send a DELETE
request to the MFA Authenticators endpoint replacing the AUTHENTICATOR_ID
with the relevant authenticator ID. You can get the ID when you list authenticators.
If an mfa_token
was used to list authenticators, users will need to complete MFA to obtain an access token with an audience of https://{yourDomain}/mfa/
in order to delete an authenticator.
curl --request DELETE \
--url 'https://{yourDomain}/mfa/authenticators/AUTHENTICATOR_ID' \
--header 'authorization: Bearer ACCESS_TOKEN'
Was this helpful?
var client = new RestClient("https://{yourDomain}/mfa/authenticators/AUTHENTICATOR_ID");
var request = new RestRequest(Method.DELETE);
request.AddHeader("authorization", "Bearer ACCESS_TOKEN");
IRestResponse response = client.Execute(request);
Was this helpful?
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://{yourDomain}/mfa/authenticators/AUTHENTICATOR_ID"
req, _ := http.NewRequest("DELETE", url, nil)
req.Header.Add("authorization", "Bearer ACCESS_TOKEN")
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.delete("https://{yourDomain}/mfa/authenticators/AUTHENTICATOR_ID")
.header("authorization", "Bearer ACCESS_TOKEN")
.asString();
Was this helpful?
var axios = require("axios").default;
var options = {
method: 'DELETE',
url: 'https://{yourDomain}/mfa/authenticators/AUTHENTICATOR_ID',
headers: {authorization: 'Bearer ACCESS_TOKEN'}
};
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 = @{ @"authorization": @"Bearer ACCESS_TOKEN" };
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/mfa/authenticators/AUTHENTICATOR_ID"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:@"DELETE"];
[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];
Was this helpful?
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{yourDomain}/mfa/authenticators/AUTHENTICATOR_ID",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => [
"authorization: Bearer ACCESS_TOKEN"
],
]);
$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("")
headers = { 'authorization': "Bearer ACCESS_TOKEN" }
conn.request("DELETE", "/{yourDomain}/mfa/authenticators/AUTHENTICATOR_ID", headers=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}/mfa/authenticators/AUTHENTICATOR_ID")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Delete.new(url)
request["authorization"] = 'Bearer ACCESS_TOKEN'
response = http.request(request)
puts response.read_body
Was this helpful?
import Foundation
let headers = ["authorization": "Bearer ACCESS_TOKEN"]
let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/mfa/authenticators/AUTHENTICATOR_ID")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "DELETE"
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()
Was this helpful?
If the authenticator was deleted, a 204 response is returned.
When you delete an authenticator, the following actions take place depending on the authenticator type:
Authenticator | Action |
---|---|
Push and OTP | When a user enrolls a push authenticator, Auth0 also enrolls OTP. If you delete either of them, the other one will also be deleted. |
SMS and Voice | When a user enrolls in either SMS or Voice,. Auth0 creates two authenticators, SMS and voice. If you delete either of them, the other will will also be deleted. |
All verified emails listed as authenticators, but you can't delete them. You can only delete email authenticators that are enrolled explicitly. |
Regenerate recovery codes
To delete a recovery code and generate a new one, get an Auth0 Management API access token and use the Management API Recovery Code Regeneration endpoint.
curl --request POST \
--url 'https://{yourDomain}/api/v2/users/USER_ID/recovery-code-regeneration' \
--header 'authorization: Bearer MANAGEMENT_API_TOKEN'
Was this helpful?
var client = new RestClient("https://{yourDomain}/api/v2/users/USER_ID/recovery-code-regeneration");
var request = new RestRequest(Method.POST);
request.AddHeader("authorization", "Bearer MANAGEMENT_API_TOKEN");
IRestResponse response = client.Execute(request);
Was this helpful?
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://{yourDomain}/api/v2/users/USER_ID/recovery-code-regeneration"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("authorization", "Bearer MANAGEMENT_API_TOKEN")
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}/api/v2/users/USER_ID/recovery-code-regeneration")
.header("authorization", "Bearer MANAGEMENT_API_TOKEN")
.asString();
Was this helpful?
var axios = require("axios").default;
var options = {
method: 'POST',
url: 'https://{yourDomain}/api/v2/users/USER_ID/recovery-code-regeneration',
headers: {authorization: 'Bearer MANAGEMENT_API_TOKEN'}
};
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 = @{ @"authorization": @"Bearer MANAGEMENT_API_TOKEN" };
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/api/v2/users/USER_ID/recovery-code-regeneration"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
[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];
Was this helpful?
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{yourDomain}/api/v2/users/USER_ID/recovery-code-regeneration",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"authorization: Bearer MANAGEMENT_API_TOKEN"
],
]);
$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("")
headers = { 'authorization': "Bearer MANAGEMENT_API_TOKEN" }
conn.request("POST", "/{yourDomain}/api/v2/users/USER_ID/recovery-code-regeneration", headers=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}/api/v2/users/USER_ID/recovery-code-regeneration")
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 MANAGEMENT_API_TOKEN'
response = http.request(request)
puts response.read_body
Was this helpful?
import Foundation
let headers = ["authorization": "Bearer MANAGEMENT_API_TOKEN"]
let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/api/v2/users/USER_ID/recovery-code-regeneration")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "POST"
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()
Was this helpful?
You will get a new recovery code that the end user will need to capture, for example:
{
"recovery_code": "FA45S1Z87MYARX9RG6EVMAPE"
}
Was this helpful?