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

> Describes the migration steps you need to take because Auth0 is deprecating the usage of the /passwordless/start endpoint from confidential applications without a client secret in the request.

# Migrate to Passwordless Endpoint from Confidential Applications

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

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.

<Tooltip tip="OAuth 2.0: Authorization framework that defines authorization protocols and workflows." cta="View Glossary" href="/docs/glossary?term=OAuth">OAuth</Tooltip> 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 Classic Login and forward the `state` parameter.

## Features affected

If any of your applications currently call the `/passwordless/start` endpoint directly to begin <Tooltip tip="Passwordless: Form of authentication that does not rely on a password as the first factor." cta="View Glossary" href="/docs/glossary?term=passwordless">passwordless</Tooltip> 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 Classic 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](https://manage.auth0.com/#/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.

## Actions

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](https://manage.auth0.com/#/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 <Tooltip tip="Client Secret: Secret used by a client (application) to authenticate with the Authorization Server; it should be known to only the client and the Authorization Server and must be sufficiently random to not be guessable." cta="View Glossary" href="/docs/glossary?term=client+secret">client secret</Tooltip> as a parameter.

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

export const codeExample = `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}"
        }
      }`;

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

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 Classic Login page

If the Classic 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 Classic 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:

```javascript lines theme={null}
var lock = new Auth0Lock(
  config.clientID, 
  config.auth0Domain, 
  {
    auth: {
      // .. other fields set
      params: {
       scope: config.internalOptions.scope,
       _csrf: config.internalOptions._csrf,
       state: config.internalOptions.state,
      }
    }
  });
```

```javascript lines theme={null}
var params = Object.assign({
    scope: config.internalOptions.scope,
    _csrf: config.internalOptions._csrf,
    state: config.internalOptions.state,
  }, {
    // ...auth params
  });

var webAuth = new auth0.WebAuth(params);
```

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 <Tooltip tip="Attack Protection: Features that Auth0 provides to detect and mitigate attacks, including brute-force protection, suspicious IP throttling, breached password detection, bot detection, and adaptive multi-factor authentication." cta="View Glossary" href="/docs/glossary?term=attack+protection">attack protection</Tooltip> purposes.

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