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

# Revoke Refresh Tokens

> Learn how to revoke a refresh token if it gets compromised using the Auth0 Dashboard, Authentication API, or Management API.

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

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

You can revoke <Tooltip tip="Refresh Token: Token used to obtain a renewed Access Token without forcing users to log in again." cta="View Glossary" href="/docs/glossary?term=refresh+tokens">refresh tokens</Tooltip> if they become compromised. Auth0 handles token revocation as though the token has been potentially exposed to malicious adversaries.

Additionally, you may consider enabling [refresh token rotation](/docs/secure/tokens/refresh-tokens/refresh-token-rotation) so that every time a client exchanges a refresh token to get a new access token, a new refresh token is also returned.

## Choose whether token revocation deletes grants

A grant provides an application with access to a resource on another entity without exposing user credentials. Tokens are issued in the context of a grant.

When a grant is revoked, so are all tokens issued in the context of that grant.  However, when a token is revoked, the grant does not necessarily need to be revoked.

You can choose whether token revocation deletes the associated grant in your tenant settings:

1. Go to [Dashboard > Tenant Settings > Advanced](https://manage.auth0.com/#/tenant/advanced).

2. In the **Settings** section. enable or disable the **Refresh Token Revocation Deletes Grant** toggle.

   * Enable the toggle to delete the underlying grant when you revoke the refresh token.

   Each revocation request invalidates all other tokens based on the same authorization grant, which revokes all refresh tokens that have been issued for the same user, application, and audience.

   * Disable the toggle to retain the underlying grant when you revoke the refresh token.

   When a device is unlinked, only the associated refresh token is revoked, leaving the grant intact.

This feature is disabled by default for all tenants created after 13 January 2021.

## Revoke a refresh token

You can revoke a refresh token in the following ways:

* [Using the Auth0 Dashboard](#using-the-auth0-dashboard)
* [Using the Authentication API](#using-the-authenticaton-api)
* [Using the Management API](#using-the-management-api)

### Using the Auth0 Dashboard

You can use the Auth0 Dashboard to revoke a user's authorized access to the application that issued the token. This renders the refresh token invalid, which is functionally identical to revoking the token itself.

1. Go to [Dashboard > User Management > Users](https://manage.auth0.com/#/users), and select the name of the user to view.
2. Select the **Authorized Applications** tab. This page lists all the applications to which the user has authorized access.
3. To revoke the user's access to an authorized application, and hence invalidate the refresh token, click **Revoke**.

### Using the Authentication API

You can use the Authentication API's [Revoke a refresh token endpoint](https://auth0.com/docs/api/authentication/revoke-refresh-token/revoke-refresh-token) to revoke a refresh token.

The endpoint supports access without 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> for applications that cannot keep the it safe (such as native apps). The application itself must have the its [authentication method](/docs/get-started/applications/credentials) (`tokenEndpointAuthMethod`) set to none.

When you make a request, the API first validates the application credentials and then verifies whether the token was issued to the application making the revocation request. If this validation fails, the request is refused, and the application is informed of the error.

Next, the API invalidates the token. The invalidation takes place immediately, and the token cannot be used again after the revocation. Each revocation request invalidates all the tokens that have been issued for the same authorization grant.

For more information, including body parameters, response schemas, and code examples, read the [Revoke a refresh token endpoint](https://auth0.com/docs/api/authentication/revoke-refresh-token/revoke-refresh-token) Authentication API documentation.

### Using the Management API device credentials endpoints

To revoke a refresh token using the Auth0 Management API device credentials endpoints:

1. Get the `id` of the refresh token you want to revoke using the [Retrieve device credentials endpoint](https://auth0.com/docs/api/management/v2/device-credentials/get-device-credentials).

   Specify `type=refresh_token` and a `user_id` with an access token containing the `read:device_credentials` scope. To narrow the results, you can also specify the `client_id` associated with the token (if known).

2. Revoke the refresh token using the [Delete a device credential endpoint](https://auth0.com/docs/api/management/v2/device-credentials/delete-device-credentials-by-id). Specify an access token containing the `delete:device_credentials` scope and the refresh token ID.

### Using the Management API refresh token endpoints

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  The Auth0 Management API refresh token endpoints are currently only available to customers on Enterprise plans. To learn more, read [Pricing](https://auth0.com/pricing).
</Callout>

The Management API's refresh token endpoints supercede the `/v2/device-credentials` resource endpoints with extended properties and bulk revocation operations.

You can view or revoke a specific refresh token with the following endpoints:

* View a refresh token information by ID with the [Get a refresh token endpoint](https://auth0.com/docs/api/management/v2/refresh-tokens/get-refresh-token)
* Revoke a refresh token by ID with the [Delete a refresh token endpoint](https://auth0.com/docs/api/management/v2/refresh-tokens/delete-refresh-token)
* List all refresh tokens for a user with the [Get refresh tokens for a user endpoint](https://auth0.com/docs/api/management/v2/users/get-refresh-tokens-for-user)
* Revoke all refresh tokens for a user with the [Delete refresh tokens for a user endpoint](https://auth0.com/docs/api/management/v2/users/delete-refresh-tokens-for-user)

## Considerations and limitations

* With the [Device Authorization Flow](/docs/get-started/authentication-and-authorization-flow/device-authorization-flow), the only way to force a device to reauthorize is to revoke the refresh token assigned to the device. The device will not be forced to reauthorize until the current access token expires and the application tries to use the revoked refresh token. For more information, read [Unlink Devices from Users](/docs/manage-users/user-accounts/unlink-devices-from-users).

* When using [Refresh Token Rotation](/docs/secure/tokens/refresh-tokens/refresh-token-rotation), if a previously invalidated token is used, the entire set of refresh tokens issued since that invalidated token was issued will immediately be revoked, requiring the end-user to re-authenticate.

* Refresh token revocation (`DELETE`) operations run asynchronously, and are eventually consistent.

* Refresh tokens issued on or after 21-09-2023 (22-02-2024 for tenants in the US-3 region) contain the session ID (`session_id`) property with the appropriate value. Refresh tokens issued before this date contain this property with a `null` value.

To learn more about refresh tokens limitations, read [Refresh Tokens limitations](/docs/secure/tokens/refresh-tokens).
