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

# Enroll and Challenge Push Authenticators

Auth0 provides a built-in <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=MFA">MFA</Tooltip> enrollment and authentication flow using [Universal Login](/docs/authenticate/login/auth0-universal-login). However, if you want to create your own user interface, you can use the [MFA API](/docs/secure/multi-factor-authentication/multi-factor-authentication-developer-resources/mfa-api) to accomplish it.

You can enroll and challenge users using push notifications with the Guardian application or SDK using the MFA API.

## 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](https://manage.auth0.com/#/applications) and select **MFA**.

* [Configure Push](/docs/secure/multi-factor-authentication/multi-factor-authentication-factors/configure-push-notifications-for-mfa) as a factor in the Dashboard or using the [Management API](https://auth0.com/docs/api/management/v2#!/Guardian/put_factors_by_name).

## Enroll with push

### Get MFA token

Depending on when you are triggering enrollment, you can obtain an <Tooltip tip="Access Token: Authorization credential, in the form of an opaque string or JWT, used to access an API." cta="View Glossary" href="/docs/glossary?term=access+token">access token</Tooltip> for using the MFA API in different ways:

* If you are enrolling during authentication, see [Authenticate With Resource Owner Password Grant and MFA](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa).
* If you want to let the user enroll a factor at any moment, see [Manage MFA Factor Enrollments](/docs/secure/multi-factor-authentication/manage-mfa-auth0-apis/manage-authenticator-factors-mfa-api).

### 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 push, set the `authenticator_types` parameter to `[oob]` and the `oob_channels` parameter to `[auth0]`.

<CodeGroup>
  ```bash cURL lines theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/mfa/associate' \
    --header 'authorization: Bearer MFA_TOKEN' \
    --header 'content-type: application/json' \
    --data '{ "authenticator_types": ["oob"], "oob_channels": ["auth0"] }'
  ```

  ```csharp C# lines theme={null}
  var client = new RestClient("https://{yourDomain}/mfa/associate");
  var request = new RestRequest(Method.POST);
  request.AddHeader("authorization", "Bearer MFA_TOKEN");
  request.AddHeader("content-type", "application/json");
  request.AddParameter("application/json", "{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"auth0\"] }", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go lines expandable theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/mfa/associate"

  	payload := strings.NewReader("{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"auth0\"] }")

  	req, _ := http.NewRequest("POST", url, payload)

  	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))

  }
  ```

  ```java Java lines theme={null}
  HttpResponse<String> response = Unirest.post("https://{yourDomain}/mfa/associate")
    .header("authorization", "Bearer MFA_TOKEN")
    .header("content-type", "application/json")
    .body("{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"auth0\"] }")
    .asString();
  ```

  ```javascript Node.JS lines theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/mfa/associate',
    headers: {authorization: 'Bearer MFA_TOKEN', 'content-type': 'application/json'},
    data: {authenticator_types: ['oob'], oob_channels: ['auth0']}
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```obj-c Obj-C lines expandable theme={null}
  #import <Foundation/Foundation.h>

  NSDictionary *headers = @{ @"authorization": @"Bearer MFA_TOKEN",
                             @"content-type": @"application/json" };
  NSDictionary *parameters = @{ @"authenticator_types": @[ @"oob" ],
                                @"oob_channels": @[ @"auth0" ] };

  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];
  ```

  ```php PHP lines expandable theme={null}
  $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\": [\"auth0\"] }",
    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;
  }
  ```

  ```python Python lines theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"auth0\"] }"

  headers = {
      'authorization': "Bearer MFA_TOKEN",
      'content-type': "application/json"
      }

  conn.request("POST", "/{yourDomain}/mfa/associate", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby lines theme={null}
  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 MFA_TOKEN'
  request["content-type"] = 'application/json'
  request.body = "{ \"authenticator_types\": [\"oob\"], \"oob_channels\": [\"auth0\"] }"

  response = http.request(request)
  puts response.read_body
  ```

  ```swift Swift lines expandable theme={null}
  import Foundation

  let headers = [
    "authorization": "Bearer MFA_TOKEN",
    "content-type": "application/json"
  ]
  let parameters = [
    "authenticator_types": ["oob"],
    "oob_channels": ["auth0"]
  ] 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()
  ```
</CodeGroup>

If successful, you receive a response like this:

```json lines theme={null}
{
    "authenticator_type": "oob",
    "barcode_uri": "otpauth://totp/tenant:user?enrollment_tx_id=qfjn2eiNYSjU3xID7dBYeCBSrdREWJPY&base_url=tenan",
    "recovery_codes": [
        "ALKE6EJZ4853BJYLM2DM2WU7"
    ],
    "oob_channel": "auth0",
    "oob_code": "Fe26.2...SYAg"
}
```

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 push enrollment

To confirm the enrollment, the end user will need to scan a QR code with the `barcode_uri` in the Guardian application, within the next 5 minutes.

Once that is done, the Guardian application will notify Auth0 that the user enrolled successfully. To know if that happened, poll the Auth0 <Tooltip tip="Token Endpoint: Endpoint on the Authorization Server that is used to programmatically request tokens." cta="View Glossary" href="/docs/glossary?term=Token+endpoint">Token endpoint</Tooltip> with the `oob_code` returned by the MFA Associate endpoint call.

<CodeGroup>
  ```bash cURL lines theme={null}
  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}'
  ```

  ```csharp C# lines theme={null}
  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", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go lines expandable 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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%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))

  }
  ```

  ```java Java lines theme={null}
  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")
    .asString();
  ```

  ```javascript Node.JS lines theme={null}
  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}'
    })
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```obj-c Obj-C lines expandable theme={null}
  #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]];

  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 lines expandable 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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%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;
  }
  ```

  ```python Python lines theme={null}
  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"

  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"))
  ```

  ```ruby Ruby lines 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["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"

  response = http.request(request)
  puts response.read_body
  ```

  ```swift Swift lines expandable theme={null}
  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)!)

  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()
  ```
</CodeGroup>

If the user has not scanned the code, it will return an `authorization_pending` response, indicating that you need to call `oauth_token` again in a few seconds:

```json lines theme={null}
{
    "error": "authorization_pending",
    "error_description": "Authorization pending: please repeat the request in a few seconds."
}
```

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

```json lines theme={null}
{
  "id_token": "eyJ...i",
  "access_token": "eyJ...i",
  "expires_in": 600,
  "scope": "openid profile",
  "token_type": "Bearer"
}
```

At this point, the authenticator is fully associated and ready to be used, and you have the authentication tokens for the user.

You can check at any point to verify whether an authenticator has been confirmed by calling the MFA Authenticators endpoint. If the authenticator is confirmed, the value returned for `active` is `true`.

## Challenge with push

### Get MFA token

Get an MFA token following the steps described in [Authenticate With Resource Owner Password Grant and MFA](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-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:

<CodeGroup>
  ```bash cURL lines theme={null}
  curl --request GET \
    --url 'https://{yourDomain}/mfa/authenticators' \
    --header 'authorization: Bearer MFA_TOKEN' \
    --header 'content-type: application/json'
  ```

  ```csharp C# lines theme={null}
  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);
  ```

  ```go Go lines expandable theme={null}
  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))

  }
  ```

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

  ```javascript Node.JS lines theme={null}
  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);
  });
  ```

  ```obj-c Obj-C lines theme={null}
  #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];
  ```

  ```php PHP lines expandable theme={null}
  $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;
  }
  ```

  ```python Python lines theme={null}
  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"))
  ```

  ```ruby Ruby lines theme={null}
  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
  ```

  ```swift Swift lines theme={null}
  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()
  ```
</CodeGroup>

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

```json lines theme={null}
[
    {
        "id": "recovery-code|dev_Ahb2Tb0ujX3w7ilC",
        "authenticator_type": "recovery-code",
        "active": true
    },
    {
        "id": "push|dev_ZUla9SQ6tAIHSz6y",
        "authenticator_type": "oob",
        "active": true,
        "oob_channel": "auth0",
        "name": "user's device name"
    },
    {
        "id": "totp|dev_gJ6Y6vpSrjnKeT67",
        "authenticator_type": "otp",
        "active": true
    }
]
```

When users enroll with push, they also get enrolled in OTP, as Guardian supports [challenging with OTP](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-otp-authenticators) for scenarios where the user does not have connectivity.

### Challenge user with push

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

<CodeGroup>
  ```bash cURL lines theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/mfa/challenge' \
    --data '{ "client_id": "{yourClientId}",  "client_secret": "{yourClientSecret", "challenge_type": "oob", "authenticator_id": "push|dev_ZUla9SQ6tAIHSz6y", "mfa_token": "{mfaToken}" }'
  ```

  ```csharp C# lines theme={null}
  var client = new RestClient("https://{yourDomain}/mfa/challenge");
  var request = new RestRequest(Method.POST);
  request.AddParameter("undefined", "{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret\", \"challenge_type\": \"oob\", \"authenticator_id\": \"push|dev_ZUla9SQ6tAIHSz6y\", \"mfa_token\": \"{mfaToken}\" }", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go lines expandable theme={null}
  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\": \"push|dev_ZUla9SQ6tAIHSz6y\", \"mfa_token\": \"{mfaToken}\" }")

  	req, _ := http.NewRequest("POST", url, payload)

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java lines theme={null}
  HttpResponse<String> response = Unirest.post("https://{yourDomain}/mfa/challenge")
    .body("{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret\", \"challenge_type\": \"oob\", \"authenticator_id\": \"push|dev_ZUla9SQ6tAIHSz6y\", \"mfa_token\": \"{mfaToken}\" }")
    .asString();
  ```

  ```javascript Node.JS lines theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/mfa/challenge',
    data: {
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret',
      challenge_type: 'oob',
      authenticator_id: 'push|dev_ZUla9SQ6tAIHSz6y',
      mfa_token: '{mfaToken}'
    }
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```obj-c Obj-C lines expandable theme={null}
  #import <Foundation/Foundation.h>
  NSDictionary *parameters = @{ @"client_id": @"{yourClientId}",
                                @"client_secret": @"{yourClientSecret",
                                @"challenge_type": @"oob",
                                @"authenticator_id": @"push|dev_ZUla9SQ6tAIHSz6y",
                                @"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 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 lines theme={null}
  $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\": \"push|dev_ZUla9SQ6tAIHSz6y\", \"mfa_token\": \"{mfaToken}\" }",
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python lines theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret\", \"challenge_type\": \"oob\", \"authenticator_id\": \"push|dev_ZUla9SQ6tAIHSz6y\", \"mfa_token\": \"{mfaToken}\" }"

  conn.request("POST", "/{yourDomain}/mfa/challenge", payload)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby lines theme={null}
  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.body = "{ \"client_id\": \"{yourClientId}\",  \"client_secret\": \"{yourClientSecret\", \"challenge_type\": \"oob\", \"authenticator_id\": \"push|dev_ZUla9SQ6tAIHSz6y\", \"mfa_token\": \"{mfaToken}\" }"

  response = http.request(request)
  puts response.read_body
  ```

  ```swift Swift lines expandable theme={null}
  import Foundation
  let parameters = [
    "client_id": "{yourClientId}",
    "client_secret": "{yourClientSecret",
    "challenge_type": "oob",
    "authenticator_id": "push|dev_ZUla9SQ6tAIHSz6y",
    "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.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()
  ```
</CodeGroup>

### Complete authentication using received code

If success, you receive the following response:

```json lines theme={null}
{
    "challenge_type": "oob",
    "oob_code": "Fe26...jGco"
}
```

Your application must start polling the OAuth0 Token endpoint until the user accepts the push notification.

<CodeGroup>
  ```bash cURL lines 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-oob \
    --data 'client_id={yourClientId}' \
    --data 'client_secret={yourClientSecret}' \
    --data 'mfa_token={mfaToken}' \
    --data 'oob_code={oobCode}'
  ```

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

  ```go Go lines expandable 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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%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 lines 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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D")
    .asString();
  ```

  ```javascript Node.JS lines 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-oob',
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret}',
      mfa_token: '{mfaToken}',
      oob_code: '{oobCode}'
    })
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```obj-c Obj-C lines expandable 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-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]];

  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 lines expandable 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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%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 lines theme={null}
  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"

  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 lines 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-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D"

  response = http.request(request)
  puts response.read_body
  ```

  ```swift Swift lines expandable 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-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)!)

  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()
  ```
</CodeGroup>

The call can return one of the following results:

<table class="table">
  <thead>
    <tr>
      <th>Result</th>
      <th>Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td><code>authorization\_pending</code></td>
      <td>Error: If the challenge has not been accepted or rejected.</td>
    </tr>

    <tr>
      <td><code>slow\_down</code></td>
      <td>Error: If the polling is too frequent.</td>
    </tr>

    <tr>
      <td><code>access\_token</code> and <code>refresh\_token</code></td>
      <td>If the challenge has been accepted; polling should be stopped at this point.</td>
    </tr>

    <tr>
      <td><code>invalid\_grant</code></td>
      <td>Error: If the challenge has been rejected: polling should be stopped at this point.</td>
    </tr>
  </tbody>
</table>

## Learn more

* [Manage Authentication Factors with Authentication API](/docs/secure/multi-factor-authentication/manage-mfa-auth0-apis/manage-authenticator-factors-mfa-api)
* [Configure Push Notifications for MFA](/docs/secure/multi-factor-authentication/multi-factor-authentication-factors/configure-push-notifications-for-mfa)
* [Challenge with Recovery Codes](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/challenge-with-recovery-codes)
* [Enroll and Challenge Email Authenticators](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-email-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 SMS and Voice Authenticators](/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-challenge-sms-voice-authenticators)
