Using Resource Owner Password from Server side

Heads up! As part of our efforts to improve security and standards-based interoperability, we have implemented several new features in our authentication flows and made changes to existing ones. For an overview of these changes, and details on how you adopt them, refer to Introducing OIDC Conformant Authentication.

Server-side applications can use the Resource Owner Password Grant to access an API. The flow typically involves prompting the user for username and password as credentials which your server will submit to Auth0 to get an access token. When using this flow from server side, some anomaly detection features might fail because of the particularities of this scenario. This document details how to use Resource Owner Password Grant flow from server side preventing some common issues.

Prerequisites

Before you continue, make sure to have brute force protection enabled from your dashboard.

The flow

  1. Your server prompts the user for credentials (i.e. username and password). This could be achieved in many different ways, for example via a browser UI or providing an API.

  2. The user enters credentials and the client-side application submits them to a backend server under your control.

  3. Your server submits the credentials to Auth0 using the Resource Owner Password Grant flow.

  4. Auth0 validates the credentials and returns an access token. As part of the validation process Auth0 might also execute anomaly-detection verifications and perform appropriate actions if an anomaly is detected.

Brute-force protection and server-side APIs

Brute-force protection relies on having the original user's IP. When calling the API from your server, Auth0 treats the IP of your server as the IP of the end user, and uses it as input for the anomaly-detection functionality, in particular, for brute-force protection. This situation could potentially trigger false positives into the brute-force protection shields, causing it to block users or trigger warnings for legitimate requests.

To prevent this, you may send the end-user's IP address to Auth0 along with the credentials and configure the client to trust the provided IP. Because of security considerations, this configuration is only possible for Authenticated clients (i.e. those with authentication based on a client secret).

Warning! Authenticated clients must only be used from protected resources, typically server-side. Do not use them from native applications or SPAs, as they are not capable of storing secrets.

Configuring the Auth0 Client to receive and trust the IP sent by your server

  1. Navigate to your dashboard and configure a regular web application or non-interactive client using this tutorial.

  2. Choose a Token Endpoint Authentication Method other than None under the Settings section.

Token Endpoint Authentication Method

Due to security considerations, the configuration stated on Step 3 will not be available for Non-Authenticated clients.

  1. Scroll to the bottom and click Show Advanced Settings.

  2. Switch on Trust Token Endpoint IP Header under the OAuth tab to configure the client to trust the IP sent from your server.

Enabling Auth0-Forwarded-For

Sending the end-user IP from your server

To send the end-user IP from your server, include a auth0-forwarded-for header with the value of the end-user IP address. If the IP is valid, Auth0 will use it as the source IP for brute-force protection. It is important to make sure the provided IP address really belongs to your end user.

Warning! Trusting headers like the x-forwarded-for (or, in general, data from client) as source for the end-user IP can be a big risk. This should not be done unless you know you can trust that header, since it is easy to spoof and makes possible to bypass the anomaly-detection validation.

Example

var request = require("request");

app.post('/api/auth', function(req, res, next) {
  var options = {
    method: 'POST',
    url: 'https://YOUR_AUTH0_DOMAIN/oauth/token',
    headers: {
      'content-type': 'application/json',
      'auth0-forwarded-for': req.ip // End user ip
    },
    body: {
      grant_type: 'password',
      username: 'USERNAME',
      password: 'PASSWORD',
      audience: 'API_IDENTIFIER',
      scope: 'SCOPE',
      client_id: 'YOUR_CLIENT_ID',
      client_secret: 'YOUR_CLIENT_SECRET' // Client is authenticated
    },
    json: true
  };

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

    // ...
  });
});