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

> Learn how to avoid common issues encountered when using the Resource Owner Password Flow to call server-side APIs with attack protection enabled.

# Avoid Common Issues with Resource Owner Password Flow and Attack Protection

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

<Warning>
  Because the Resource Owner Password (ROP) Flow involves the application handling the user's password, it must not be used by third-party clients.
</Warning>

Though we do not recommend it, highly-trusted applications can call server-side APIs using the [Resource Owner Password Flow](/docs/get-started/authentication-and-authorization-flow/resource-owner-password-flow) (sometimes called <Tooltip tip="Resource Owner: Entity (such as a user or application) capable of granting access to a protected resource." cta="View Glossary" href="/docs/glossary?term=Resource+Owner">Resource Owner</Tooltip> Password Grant or ROPG), which requests that users provide credentials (username and password), typically using an interactive form. If [brute-force protection is enabled](/docs/secure/attack-protection/brute-force-protection), when Auth0 validates the credentials, we may also [check for attacks](/docs/secure/attack-protection) and perform appropriate actions if an attack is detected.

Unfortunately, when using this flow with <Tooltip tip="Brute-force Protection: Form of attack protection that safeguards against brute-force attacks that occur from a single IP address and target a single user account." cta="View Glossary" href="/docs/glossary?term=brute-force+protection">brute-force protection</Tooltip>, some <Tooltip tip="Brute-force Protection: Form of attack protection that safeguards against brute-force attacks that occur from a single IP address and target a single user account." cta="View Glossary" href="/docs/glossary?term=attack+protection">attack protection</Tooltip> features may fail. Some common issues, however, can be avoided.

## Attack protection and server-side APIs

Brute-force protection and <Tooltip tip="Suspicious IP Throttling: Form of attack protection that protects your tenant against suspicious logins targeting too many accounts from a single IP address." cta="View Glossary" href="/docs/glossary?term=suspicious+IP+throttling">suspicious IP throttling</Tooltip> rely on having the user's IP address. When calling an API from your server, Auth0 treats the IP address of your server as the IP address of the user and provides it as input to the brute-force protection and suspicious IP throttling functionality. This could potentially trigger false positives, causing attack protection to block users or trigger warnings for legitimate requests.

To avoid this, send the user's IP address to Auth0 along with their credentials, and configure your application to trust the IP address.

<Warning>
  Due to security considerations, you may only configure authenticated applications (such as those with authentication based on a client secret) this way. Authenticated applications must only be used from protected resources, which are typically server-side. Do not use them from native applications or Single-page applications (SPAs) because they are not capable of storing secrets.
</Warning>

## Configure your Application to trust the IP address

Register either a [regular web application](/docs/get-started/auth0-overview/create-applications/regular-web-apps) or a [machine-to-machine application](/docs/get-started/auth0-overview/create-applications/machine-to-machine-apps). While configuring the application:

1. Under **Credentials**, select an **Authentication Method** other than `None`.
2. Under **Settings > Advanced Settings**, locate the **OAuth** tab, and enable **Trust Token Endpoint IP Header**, which will set the `auth0-forwarded-for` header as a trusted source of the user's IP address for brute-force protection. This setting will not be available for non-authenticated applications.

## Send the user's IP address from your server

1. When you request tokens using the [Resource Owner Password Flow](/docs/get-started/authentication-and-authorization-flow/resource-owner-password-flow/call-your-api-using-resource-owner-password-flow), include an `auth0-forwarded-for` header that contains the value of the user's IP address. Be sure that the IP address you provide really belongs to your user.

   <Warning>
     Trusting headers like the `auth0-forwarded-for` (or, in general, data from applications) as sources for the user's IP address can be risky. Because this header is easy to spoof and makes it possible to bypass attack protection validation, only do this if you know you can trust that header.
   </Warning>
2. Specify AllowLists of IPs to be ignored when triggering brute-force protection and suspicious IP throttling.

<Card title="Allow listing with brute-force protection and suspicious IP throttling">
  If your authenticated application is configured to send the `auth0-forwarded-for` header:

  * Only the IP address contained in the `auth0-forwarded-for` header is checked against the brute-force protection and suspicious IP throttling AllowLists.
  * The proxy IP address is ignored by brute-force protection and suspicious IP throttling, so doesn't need to be added to the AllowLists.
  * If specific clients that use the proxy should not be subject to brute-force protection or suspicious IP throttling, add them to the AllowLists.

  The `auth0-forwarded-for` header will only be accepted for authenticated calls with the Client Secret. If your application is not authenticated or is not configured to send the `auth0-forwarded-for` header:

  * The originating IP address of each request is checked against the brute-force protection and suspicious IP throttling AllowLists.
  * If you AllowList the IP proxy, all traffic passing through the proxy will be exempt from brute-force protection and suspicious IP throttling. This is probably not what you want.
</Card>

### Example

export const codeExample = `var request = require("request");

app.post('/api/auth', function(req, res, next) {
  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/oauth/token',
    headers: {
      'content-type': 'application/x-www-form-urlencoded',
      'auth0-forwarded-for': req.ip // End user ip
    },
    form: {
      grant_type: 'password',
      username: 'USERNAME',
      password: 'PASSWORD',
      audience: 'YOUR_API_IDENTIFIER',
      scope: 'SCOPE',
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret}' // Client is authenticated
    }
  };

  request(options, function (error, response, body) {
    if (error) return next(error);

    // ...
  });
});`;

<AuthCodeBlock children={codeExample} language="javascript" />

## Handle Breached Password Detection responses

If you’ve enabled [Breached Password Detection](/docs/secure/attack-protection/breached-password-detection) for your tenant, you need to configure your application to handle responses from the [Auth0 Authentication API](https://auth0.com/docs/api/authentication) accordingly.

For example, if you send a password using the ROP flow, and Auth0 detects that it’s been compromised, the Authentication API returns a response with the HTTP `401 Unauthorized` status code and the following body:

```json lines theme={null}
{
    "error": "password_leaked",
    "error_description": "This login attempt has been blocked because the password you're using was previously disclosed through a data breach (not in this application). Please check your email for more information."
}
```

Your application should handle this error, render a message to the user, and [trigger an interactive password reset flow](/docs/authenticate/database-connections/password-change#authentication-api).

## Validate with logs

If your settings are working correctly, you will see the following in the logs:

```bash lines theme={null}
type:  sepft
...
ip:  <ip from auth0-forwarded-for header>
client_ip:  <ip of actual client/proxy>
...
```

## Learn more

* [Resource Owner Password Flow](/docs/get-started/authentication-and-authorization-flow/resource-owner-password-flow)
* [Call Your API Using Resource Owner Password Flow](/docs/get-started/authentication-and-authorization-flow/resource-owner-password-flow/call-your-api-using-resource-owner-password-flow)
* [Attack Protection](/docs/secure/attack-protection)
