Back to Blog
Guide

Slack Revoke Token: What auth.revoke Breaks, Tested After a Fake Leak

We revoked a user token and a bot token with auth.revoke, then every token at once with the Revoke Tokens button, and logged each response, each event and what kept working. Then we reinstalled and checked the new tokens.

Slack Green Team
October 2, 2026
October 2, 2026
4 min read
Share:
slack api
developers
tokens
security

To revoke a Slack token, call auth.revoke with that token, or open your app's OAuth & Permissions page and click Revoke Tokens to kill every bot and user token the app has. Neither gives you a replacement. You get a new token by installing the app again. On 2 October 2026 we did all of this to a test app in our own workspace, as if its tokens had leaked, and logged every response. A revoked user token answered token_revoked, a revoked bot token answered account_inactive, and revoking the bot token uninstalled the app.

Revoke one token with auth.revoke

auth.revoke takes no token argument. It revokes the token you call it with, so you need the leaked token itself. This is the script we ran with slack_sdk 3.x. TOKEN_VAR names the environment variable that holds the token:

import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

client = WebClient(token=os.environ[os.environ.get("TOKEN_VAR", "SLACK_BOT_TOKEN")])

def call(label, method, **kw):
    try:
        r = getattr(client, method)(**kw).data
        print(f"{label:28} ok   " + ", ".join(f"{k}={r[k]}" for k in ("user", "revoked") if k in r))
    except SlackApiError as e:
        print(f"{label:28} {e.response['error']}")

call("auth.test", "auth_test")
call("auth.revoke test=true", "auth_revoke", test=True)
call("auth.test", "auth_test")
call("auth.revoke", "auth_revoke")
call("auth.test after revoke", "auth_test")
call("chat.postMessage", "chat_postMessage", channel=os.environ["CHANNEL_ID"], text="still here?")
call("auth.revoke again", "auth_revoke")

With the user token (xoxp-):

auth.test                    ok   user=sieun
auth.revoke test=true        ok   revoked=False
auth.test                    ok   user=sieun
auth.revoke                  ok   revoked=True
auth.test after revoke       token_revoked
chat.postMessage             token_revoked
auth.revoke again            token_revoked

With the bot token (xoxb-):

auth.test                    ok   user=sglabw2
auth.revoke test=true        ok   revoked=False
auth.test                    ok   user=sglabw2
auth.revoke                  ok   revoked=True
auth.test after revoke       account_inactive
chat.postMessage             account_inactive
auth.revoke again            account_inactive

test=true only checks the call: it returned revoked=False and the token kept working. Without it, the token died at once. The error differs by token type, so code that watches for a dead token should treat token_revoked, account_inactive and invalid_auth the same way. A made-up token returned invalid_auth, and a call with no token returned not_authed.

What broke and what kept working

After we revokedResult
The user tokentoken_revoked on every call. The bot token still worked.
The person's own Slack sessionStill signed in. Revoking an app's user token does not sign the person out.
The bot tokenaccount_inactive on every call, and the app was uninstalled from the workspace
The bot's channel membershipGone. conversations.members listed only the person.
Messages the bot had postedStill in the channel
The app-level token (xapp-)Still valid. apps.connections.open returned ok, and our Socket Mode listener stayed connected.

The last row matters after a leak. An app-level token is a separate token on the app's Basic Information page, with its own Revoke button. Revoking OAuth tokens does not touch it.

The events your app gets

Our Socket Mode listener was subscribed to tokens_revoked and app_uninstalled. Revoking the user token sent this envelope (the deprecated verification token is redacted):

{
  "token": "<redacted>",
  "team_id": "T0B7JBCDKC1",
  "api_app_id": "A0C71JYC6U8",
  "event": {
    "type": "tokens_revoked",
    "tokens": {"oauth": ["U0B7L4YK420"], "bot": []},
    "event_ts": "1790925080.122762"
  },
  "type": "event_callback",
  "event_id": "Ev0C674TBXPC",
  "event_time": 1790925080
}

oauth lists the user IDs whose user tokens died; bot lists bot user IDs. Revoking the bot token 9 seconds later sent tokens_revoked with "bot": ["U0C5RSHVBQF"], then app_uninstalled. Use these to delete stored tokens for that workspace. They arrive on the app-level connection, which is why the listener still received them.

Never appear "away" on Slack again

Cloud-based. No downloads. Works 24/7 even when your laptop is off.

Revoke every token at once

When you do not know which tokens leaked, or you no longer have the leaked token, use the app settings. On api.slack.com/apps, open the app, then OAuth & Permissions, and scroll to the bottom:

Slack app settings: the "Restrict API Token Usage" card with an empty IP allow list, and below it the "Revoke All OAuth Tokens" card with a red Revoke Tokens button

The button asks for confirmation and warns that it can take a moment:

Slack's "Are you sure?" dialog: all existing tokens will become invalid, the operation can take some time, and users will need to grant the app permissions again, with No, Go Back and Yes, I'm Sure buttons

We clicked Yes at 16:12:36 KST. One second later both tokens still returned ok. Six seconds after the click the listener received app_uninstalled and a tokens_revoked event for the bot and for the user. At the next check, 12 seconds after the click, the bot token returned account_inactive and the user token token_revoked. The app-level token still worked. So wait about a minute before you reinstall, as the dialog says.

The card above it, Restrict API Token Usage, takes a list of IP ranges; the card says Slack then rejects Web API calls from other addresses. We did not test that list, but for a server app with fixed IPs it limits what a leaked token can do.

Get a new token

After a revoke, the app's OAuth Tokens section shows Install to Slack again, with no token:

The OAuth Tokens card after the bot token was revoked: "OAuth Tokens will be automatically generated when you finish installing your app to your workspace" and an Install to Slack button

We reinstalled through the same OAuth flow. Both new tokens were different strings from the revoked ones, and the bot kept its user ID (U0C5RSHVBQF). The bot was not back in its channels, so conversations.join or an invite is needed again. A plain reinstall without a revoke gives the same token back: when we reinstalled earlier the same day only to add a scope, oauth.v2.access returned the identical bot token. Reinstalling alone does not fix a leak.

The order that worked for us after a leak:

  • Revoke: auth.revoke with the leaked token, or Revoke Tokens if you are unsure which ones leaked.
  • Revoke the app-level token on Basic Information if it was in the same file or repo.
  • Reinstall, store the new token in your secret store, and redeploy.
  • Rejoin channels or re-invite the bot.

Our bot token guide explains what each prefix (xoxb-, xoxp-, xapp-) can do, which tells you how much a leaked one exposed. If you want tokens that expire on their own, see token rotation.

FAQ

Does auth.revoke need a scope? No. Both our tokens could revoke themselves without any extra scope.

Can I revoke someone else's token? Not with auth.revoke, which only revokes the calling token. As the app's owner, Revoke Tokens covers every token of your app.

Does revoking delete the app's messages? No. The bot's earlier message stayed in the channel after its token was revoked and the app was uninstalled.

Always Active

Stop Jiggling Your Mouse.

Join hundreds of remote workers who never worry about their Slack status. Set it up once, stay green forever.

Related Articles

Guide

Slack Bot Scopes: The Scope Each API Method Needs, Measured on 44 Methods

We gave a Slack bot one scope, called 44 common Web API methods, and read the needed field of every missing_scope error. Then we added the scopes and called them again. The table shows which scope clears each method.

Slack Green Team
Guide

Slack File Size Limit: 1 GB Is Exactly 1,073,741,824 Bytes, Tested

We uploaded files of 50 MB, exactly 1 GiB and 1 GiB plus one byte to Slack through its upload API. The limit is 1,073,741,824 bytes, and a failed upload can still leave a broken file behind.

Slack Green Team
Guide

Slack Dark Mode: Where the Setting Is, and Which Custom Emoji Disappear

Slack's dark mode is under Preferences > Appearance > Color Mode, with Light, Dark and System. We switched modes in Slack web with three test emoji and measured which ones vanish.

Slack Green Team