Migrate to Passwordless Endpoint from Confidential Applications

Auth0 is deprecating the use of the /passwordless/start endpoint from confidential applications when Auth0 cannot authenticate that the call is made on behalf of the application.

OAuth uses the term 'confidential' for applications that can store secrets. In Auth0, those are 'Regular Web Applications', which serve web pages from a backend app. Single Page Applications and Native Applications are considered 'public' applications, and are not affected by this change.

Auth0 can authenticate calls to /passwordless/start when they include a client_secret as a parameter, or when the calls are made from the custom login page in Universal Login and forward the state parameter.

Features affected

If any of your applications currently call the /passwordless/start endpoint directly to begin passwordless authentication from a Web Application, and you are not sending the client_secret as a parameter, this deprecation does affect you.

If you are implementing passwordless authentication through the Universal Login page and you changed the default way Auth0 libraries are initialized, it might also affect you too.

You can verify whether you are affected by checking the tenant logs, filtering by "Deprecation Notice" and check for logs saying "Enforce client authentication for passwordless connections". You can also perform this search directly with the following query: type:depnote AND description:*passwordless*. Note that this specific query will only work for public cloud tenants, as private cloud logs cannot be searched on the description field.


If you are calling the /passwordless/start endpoint without proper application authentication you should:

  • Follow the instructions described below to adjust the code to properly call /passwordless/start.

  • Check your tenant logs to verify the change was made correctly and no deprecation logs are being generated for "Enforce client authentication for passwordless connections".

  • In the Migrations section of Advanced Tenant Settings, turn on the Enforce client authentication for passwordless connections toggle.

There are a few use cases that might be affected, but for each, the migration path is fairly straightforward:

API calls from backend

For any calls from your backend to the /passwordless/start endpoint, your call must include the client secret as a parameter.

If making a POST request directly to /passwordless/start, include the client_secret as part of the payload:

to configure this snippet with your account
POST https://{yourDomain}/passwordless/start
    Content-Type: application/json
      "client_id": "{yourClientId}",
      "client_secret": "{yourClientSecret}",
      "connection": "email|sms",
      "email": "{userEmailAddress}", //set for connection=email
      "phone_number": "{userPhoneNumber}", //set for connection=sms
      "send": "link|code",
      "authParams": { 
          "scope": "openid",
          "state": "{yourState}"

Was this helpful?


If you are using an SDK, add the parameter to the method that initiates the passwordless flow. This is different for each SDK, and not all SDKs have been updated yet. If you are using an SDK that was not updated, you can make the HTTP call directly until that work is completed.

Auth0.js or Lock.js in the Universal Login page

If the Universal Login page is used for Passwordless Authentication for a Web Application, it will be making calls to the /passwordless/start endpoint, by either using Lock.js or Auth0.js.

Given you can't store a client secret in a web page, the way to authenticate the call is by forwarding the state parameter that is received in the Universal Login page to the /passwordless/start endpoint. That parameter is stored in the config.internalOptions field in the custom login page.

The default templates for customizing the login page use it in the following way when initializing Lock.js or auth0.js:

var lock = new Auth0Lock(
    auth: {
      // .. other fields set
      params: {
       scope: config.internalOptions.scope,
       _csrf: config.internalOptions._csrf,
       state: config.internalOptions.state,

Was this helpful?


var params = Object.assign({
    scope: config.internalOptions.scope,
    _csrf: config.internalOptions._csrf,
    state: config.internalOptions.state,
  }, {
    // ...auth params

var webAuth = new auth0.WebAuth(params);

Was this helpful?


Please check in your custom page implementation to verify that you have not removed that code.

Call /passwordless/start from the client in a web application

If you are calling the /passwordless/start endpoint from a page using JavaScript (for example, using Auth0.js on the page) from regular web apps, you will not be able to specify a client secret in a call made using JavaScript. If this is the case for your application, you will need to change your apps so that /passwordless/start is called from the backend of your web application, rather than from the frontend.

Rate Limits

A consequence of adding client authentication to /passwordless/start is that Auth0 can trust the headers sent with the request. If you set the auth0-forwarded-for header, the IP address will show in the logs and be used for attack protection purposes.

Authenticated /passwordless/start requests will be treated as regular Authenticated API requests and the corresponding global Authentication API rate limit will apply.