Migrate Your Resource Owner Passwordless Credentials Exchange

Support for resource owner password was added to /oauth/token. Usage of the /oauth/ro endpoint was deprecated on 08 July 2017. The /oauth/ro endpoint was previously used to exchange a one-time password (OTP) received by the end-user email or SMS for an ID token and an access token. Auth0 has implemented a new API that replaces /oauth/ro for this use case and we recommend that you migrate to using the new endpoint.

Features affected

This change affects you if you use the resource owner passwordless credentials exchange and call /oauth/ro directly without the use of any Auth0 libraries or SDKs.


Request changes

Previously, the payload of a request to /oauth/ro looked similar to this:

      "grant_type": "password",
      "client_id": "123",
      "username": "alice",
      "password": "A3ddj3w", 
      "connection": "my-database-connection",
      "scope": "openid email favorite_color offline_access",
      "device": "my-device-name"

Was this helpful?


These are the changes for the new implementation:

  • The endpoint to execute token exchanges is now /oauth/token.

  • Auth0's own grant type is used to authenticate users from a specific connection (or realm).

  • Auth0 supports the standard OIDC scopes, along with the scopes which you have defined in your custom API.

  • A scope that does not fit in one of these categories, such as the above favorite_color, is no longer a valid scope.

  • The device parameter is removed.

  • The audience parameter is optional.

Here is an example of the payload of a request to /oauth/token:

to configure this snippet with your account
      "grant_type" : "http://auth0.com/oauth/grant-type/passwordless/otp",
      "client_id": "{yourClientId}",
      "client_secret": "{yourClientSecret}", // only for web apps, native apps don’t have a client secret
      "username": "{userEmailAddress}", // or "{userPhoneNumber}"
      "otp": "CODE",
      "realm": "email", // or "sms" 
      "audience" : "{yourApiIdentifier}", // in case you need an access token for a specific API
      "scopes": "openid profile email" // whatever scopes you need

Was this helpful?


  • The grant type is specified here as http://auth0.com/oauth/grant-type/passwordless/otp.

  • The parameters client_id and username are unchanged.

  • The client_secret needs to be specified for confidential clients (e.g. regular web apps).

  • The one-time password needs to be sent in the otp parameter instead of the password parameter.

  • The realm is used to identify the connection, and replaces the connection parameter from previous calls.

  • The scope parameter is mostly the same, but does not accept non-OIDC values.

  • The audience parameter can be added, indicating the API audience the token will be intended for.

Response changes

Responses from /oauth/ro were similar in format to the following:

      "access_token": "SlAV32hkKG",
      "token_type": "Bearer",
      "refresh_token": "8xLOxBtZp8",
      "expires_in": 3600,
      "id_token": "eyJ..."

Was this helpful?


  • The returned access token is valid for calling the /userinfo endpoint (provided that the API specified by the audience param uses RS256 as signing algorithm) and optionally the custom API if one was specified.

  • The ID token will be forcibly signed using RS256 if requested by a public client.

  • A refresh token will be returned only if the offline_access scope was granted and the API has Allow offline access set.

Here is an example of the OIDC conformant response from /oauth/token:

      "access_token": "eyJ...",
      "token_type": "Bearer",
      "refresh_token": "8xLOxBtZp8",
      "expires_in": 3600,
      "id_token": "eyJ..."

Was this helpful?


Code changes when using the SDKs

If your application uses the Auth0 native libraries for Android or iOS, be sure that the version of the library you are including is at least the minimum listed below (or higher). Also, be sure to set the OIDC Conformant flag to true when configuring the libraries.

Library Minimum Version
Android SDK 1.2
Lock Android 2.17
Swift SDK 1.20.0
Lock iOS 2.14.0

Verify migration

  1. To verify whether you are using the deprecated endpoint, check the tenant logs, filter by Deprecation Notice and then check for logs that say oauth/ro passwordless: This feature is being deprecated. You can also perform this search directly with the following query: type:depnote AND description:*passwordless*.

  2. Once you have migrated your codebase and are sure that your apps are not calling the endpoint, go to the Dashboard under Tenant Settings > Advanced.

  3. Scroll down to Migrations and toggle off Legacy /oauth/ro Endpoint. Turning off this switch disables the deprecated endpoint for your tenant, preventing it from being used.

Dashboard - Tenant Settings - Advanced - /oauth/ro Endpoint Migration Toggle Screen

If turning this switch off results in failed logins, this is a sign that you have yet to completely remove all instances of legacy code from your applications.

Once migrations have been successfully performed in production environments, the switch can be toggled off and left off, to ensure that the deprecated features can no longer be used.

Learn more