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

> Découvrez comment authentifier des utilisateurs à l’aide du flux Resource Owner Password avec MFA.

# Authentifier à l’aide du flux Resource Owner Password avec MFA

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

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

Vous pouvez utiliser l’[API MFA d’Auth0](https://auth0.com/docs/api/authentication#multi-factor-authentication) pour terminer le flux d’authentification au moyen du [flux Resource Owner Password](/fr-CA/docs/get-started/authentication-and-authorization-flow/resource-owner-password-flow) (parfois appelé <Tooltip tip="Propriétaire de la ressource : entité (comme un utilisateur ou une application) capable d’accorder l’accès à une ressource protégée." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=Resource+Owner">Resource Owner</Tooltip> Password Grant ou ROPG) lorsque <Tooltip tip="Propriétaire de la ressource : entité (comme un utilisateur ou une application) capable d’accorder l’accès à une ressource protégée." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=MFA">MFA</Tooltip> est activée.

<div id="prerequisites">
  ## Prérequis
</div>

Avant de pouvoir utiliser les API MFA, vous devez activer le type d’autorisation MFA pour votre application. Accédez à [Auth0 Dashboard > Applications > Advanced Settings > Grant Types](https://manage.auth0.com/#/applications), puis sélectionnez **MFA**.

<div id="authenticate-user">
  ## Authentifier un utilisateur
</div>

Lorsque vous utilisez le flux Resource Owner Password pour authentifier un utilisateur, appelez le point de terminaison `/oauth/token` avec son nom d’utilisateur et son mot de passe.

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/oauth/token' \
    --header 'content-type: application/x-www-form-urlencoded' \
    --data grant_type=password \
    --data username=user@example.com \
    --data password=pwd \
    --data 'client_id={yourClientId}' \
    --data 'client_secret={yourClientSecret}' \
    --data audience=https://someapi.com/api \
    --data 'scope=openid profile read:sample'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/oauth/token");
  var request = new RestRequest(Method.POST);
  request.AddHeader("content-type", "application/x-www-form-urlencoded");
  request.AddParameter("application/x-www-form-urlencoded", "grant_type=password&username=user%40example.com&password=pwd&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&audience=https%3A%2F%2Fsomeapi.com%2Fapi&scope=openid%20profile%20read%3Asample", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

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

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

  func main() {

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

  	payload := strings.NewReader("grant_type=password&username=user%40example.com&password=pwd&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&audience=https%3A%2F%2Fsomeapi.com%2Fapi&scope=openid%20profile%20read%3Asample")

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

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

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

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

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

  }
  ```

  ```java Java theme={null}
  HttpResponse response = Unirest.post("https://{yourDomain}/oauth/token")
    .header("content-type", "application/x-www-form-urlencoded")
    .body("grant_type=password&username=user%40example.com&password=pwd&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&audience=https%3A%2F%2Fsomeapi.com%2Fapi&scope=openid%20profile%20read%3Asample")
    .asString();
  ```

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

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/oauth/token',
    headers: {'content-type': 'application/x-www-form-urlencoded'},
    data: new URLSearchParams({
      grant_type: 'password',
      username: 'user@example.com',
      password: 'pwd',
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret}',
      audience: 'https://someapi.com/api',
      scope: 'openid profile read:sample'
    })
  };

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

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

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/oauth/token",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "grant_type=password&username=user%40example.com&password=pwd&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&audience=https%3A%2F%2Fsomeapi.com%2Fapi&scope=openid%20profile%20read%3Asample",
    CURLOPT_HTTPHEADER => [
      "content-type: application/x-www-form-urlencoded"
    ],
  ]);

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

  curl_close($curl);

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

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

  conn = http.client.HTTPSConnection("")

  payload = "grant_type=password&username=user%40example.com&password=pwd&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&audience=https%3A%2F%2Fsomeapi.com%2Fapi&scope=openid%20profile%20read%3Asample"

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

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

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

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

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

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

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

  request = Net::HTTP::Post.new(url)
  request["content-type"] = 'application/x-www-form-urlencoded'
  request.body = "grant_type=password&username=user%40example.com&password=pwd&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&audience=https%3A%2F%2Fsomeapi.com%2Fapi&scope=openid%20profile%20read%3Asample"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

Lorsque la MFA est activée, la réponse inclut une erreur `mfa_required` et un `mfa_token`.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  La durée de validité par défaut des jetons d’accès avec l’audience `https://{yourDomain}/mfa/*` est de 10 minutes. Cette valeur ne peut pas être configurée.
</Callout>

```json lines theme={null}
{
    "error": "mfa_required",
    "error_description": "Multifactor authentication required",
    "mfa_token": "Fe26...Ha"
}
```

<div id="retrieve-enrolled-authenticators">
  ## Récupérer les authentificateurs inscrits
</div>

Après avoir obtenu l’erreur ci-dessus, vous devez vérifier si l’utilisateur a inscrit un facteur MFA ou non. Appelez le [point de terminaison MFA Authenticators](/fr-CA/docs/secure/multi-factor-authentication/manage-mfa-auth0-apis/manage-authenticator-factors-mfa-api) en utilisant le jeton MFA obtenu dans la section précédente.

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

  ```csharp C# 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 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 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 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);
  });
  ```

  ```php PHP 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 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 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
  ```
</AuthCodeGroup>

Vous obtiendrez un tableau contenant les authentificateurs disponibles. Le tableau sera vide si l’utilisateur n’a inscrit aucun facteur.

```json lines theme={null}
[
    {
        "id": "recovery-code|dev_O4KYL4FtcLAVRsCl",
        "authenticator_type": "recovery-code",
        "active": true
    },
    {
        "id": "email|dev_NU1Ofuw3Cw0XCt5x",
        "authenticator_type": "oob",
        "active": true,
        "oob_channel": "email",
        "name": "email@address.com"
    }
]
```

<div id="enroll-mfa-factor">
  ## Inscrire un facteur MFA
</div>

Si l’utilisateur n’est pas inscrit à MFA, utilisez le jeton MFA obtenu précédemment pour l’inscrire à l’aide du point de terminaison MFA Associate. Consultez les liens suivants pour implémenter ce flux selon le facteur d’authentification :

* [SMS ou voix](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-challenge-sms-voice-authenticators)
* [Mot de passe à usage unique (OTP)](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-otp-authenticators)
* [Push](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-push-authenticators)
* [Courriel](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-email-authenticators)

<div id="challenge-user-with-mfa">
  ## Présenter un défi MFA à l’utilisateur
</div>

Si l’utilisateur est déjà inscrit à MFA, vous devez lui présenter un défi à l’aide de l’un des facteurs existants. Utilisez le `authenticator_id` renvoyé par le point de terminaison MFA Authenticators lorsque vous appelez le point de terminaison MFA Challenge.

Une fois le défi terminé, appelez de nouveau le point de terminaison `/oauth/token` pour finaliser le flux d’authentification et obtenir les jetons d’authentification.

Consultez les liens ci-dessous pour implémenter ce flux selon le facteur d’authentification :

* [SMS ou voix](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-challenge-sms-voice-authenticators)
* [Mot de passe à usage unique (OTP)](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-otp-authenticators)
* [Push](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-push-authenticators)
* [Courriel](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-email-authenticators)

<div id="mfa-otp-code-limitations-and-restrictions">
  ### Limites et restrictions des codes OTP de MFA
</div>

**Délai d’expiration** : Le délai d’expiration des codes OTP de MFA est de 5 minutes. Cette valeur n’est pas configurable.

**Validation du code** : Une fois qu’un utilisateur a validé un code OTP de MFA, il ne peut plus être réutilisé.

**Limitation du nombre de tentatives de validation de code** : Les tentatives de validation infructueuses d’un utilisateur sont soumises à une limite de débit au moyen d’un algorithme de seau. Le seau commence à 10 tentatives et se recharge au rythme de 1 tentative toutes les 6 minutes.

<div id="customize-mfa">
  ## Personnaliser la MFA
</div>

<Warning>
  La personnalisation de la MFA avec les flux Resource Owner Password Grant, Embedded ou Refresh Token est en accès anticipé. En utilisant cette fonctionnalité, vous acceptez les conditions applicables de l’essai gratuit énoncées dans le [Master Subscription Agreement](https://www.okta.com/legal/) d’Okta. Pour en savoir plus sur les phases de lancement d’Auth0, consultez [Product Release Stages](/fr-CA/docs/troubleshoot/product-lifecycle/product-release-stages). Pour participer à l’accès anticipé, communiquez avec l’[assistance Auth0](https://support.auth0.com/).
</Warning>

Personnalisez vos flux MFA avec l’API MFA. Avec l’API MFA, vous pouvez permettre à vos utilisateurs de s’inscrire et d’effectuer un défi à l’aide d’un choix précis de facteurs pris en charge par votre application.

Lorsque la MFA est activée avec le flux Resource Owner Password pour l’authentification, appelez le point de terminaison `/oauth/token` afin de demander un jeton d’accès. Le serveur d’autorisation renvoie une erreur `mfa_required` qui fournit :

* Le `mfa_token` dont vous avez besoin pour appeler l’API MFA lors de l’inscription et des défis.
* Le paramètre `mfa_requirements`, qui indique le type de facteur pris en charge par votre application pour les défis.

```json theme={null}
{
  "error": "mfa_required",
  "error_description": "Multifactor authentication required",
  "mfa_token": "Fe26...Ha",
  "mfa_requirements": {
    "challenge": [
      { "type": "otp" },
      { "type": "push-notification" },
      { "type": "phone" },
      { "type": "recovery-code" }
    ]
  }
}
```

Utilisez le `mfa_token` pour appeler le [`point de terminaison mfa/authenticator`](/fr-CA/docs/api/authentication/muti-factor-authentication/list-authenticators) afin de répertorier tous les facteurs auxquels l’utilisateur s’est déjà inscrit et de repérer celui du même type que celui pris en charge par votre application.  Vous devez aussi obtenir l’`authenticator_type` correspondant pour lancer des défis :

```json theme={null}
[
  {
    "type": "recovery-code",
    "id": "recovery-code|dev_qpOkGUOxBpw6R16t",
    "authenticator_type": "recovery-code",
    "active": true
  },
  {
    "type": "otp",
    "id": "totp|dev_6NWz8awwC8brh2dN",
    "authenticator_type": "otp",
    "active": true
  }
]
```

Imposez le défi MFA en appelant le point de terminaison [`request/mfa/challenge`](/fr-CA/docs/api/authentication/muti-factor-authentication/request-mfa-challenge).

Personnalisez davantage votre flux MFA avec Auth0 Actions. Pour en savoir plus, consultez [Déclencheurs d’Actions : post-challenge - objet API](/fr-CA/docs/customize/actions/explore-triggers/password-reset-triggers/post-challenge-trigger/post-challenge-api-object).

<div id="learn-more">
  ## En savoir plus
</div>

* [Inscrire des authentificateurs SMS et vocaux et lancer un défi d’authentification](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-challenge-sms-voice-authenticators)
* [Inscrire des authentificateurs OTP et lancer un défi d’authentification](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-otp-authenticators)
* [Inscrire des authentificateurs Push et lancer un défi d’authentification](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-push-authenticators)
* [Inscrire des authentificateurs par courriel et lancer un défi d’authentification](/fr-CA/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-email-authenticators)
* [Gérer les facteurs d’authentification avec l’Authentication API](/fr-CA/docs/secure/multi-factor-authentication/manage-mfa-auth0-apis/manage-authenticator-factors-mfa-api)
* [Facteurs d’authentification multifacteur](/fr-CA/docs/secure/multi-factor-authentication/multi-factor-authentication-factors)
