Official library for using the Slack Platform's Web API
—
Handle OAuth flows, token management, and authentication verification.
Verify authentication tokens and get information about the authenticated user/bot.
/**
* Test authentication and get basic info about the token
* @param options - Test parameters (optional)
* @returns Promise resolving to authentication details
*/
auth.test(options?: AuthTestArguments): Promise<AuthTestResponse>;
interface AuthTestArguments {
/** Token to test (defaults to client's token) */
token?: string;
}Usage Examples:
import { WebClient } from "@slack/web-api";
const web = new WebClient(token);
// Test current token
const authInfo = await web.auth.test();
console.log('Token is valid:', authInfo.ok);
console.log('User/Bot ID:', authInfo.user_id);
console.log('Team ID:', authInfo.team_id);
console.log('Team name:', authInfo.team);
console.log('Is bot:', authInfo.is_enterprise_install);
// Test specific token
const specificAuth = await web.auth.test({
token: 'xoxb-different-token'
});Revoke authentication tokens when no longer needed.
/**
* Revoke an authentication token
* @param options - Revocation parameters
* @returns Promise resolving to revocation confirmation
*/
auth.revoke(options?: AuthRevokeArguments): Promise<AuthRevokeResponse>;
interface AuthRevokeArguments {
/** Whether to revoke all tokens for this app (default: false) */
test?: boolean;
/** Token to revoke (defaults to client's token) */
token?: string;
}Usage Examples:
// Revoke current token
const revocationResult = await web.auth.revoke();
if (revocationResult.ok) {
console.log('Token revoked successfully');
console.log('Revoked:', revocationResult.revoked);
}
// Test revocation (doesn't actually revoke)
const testRevoke = await web.auth.revoke({
test: true
});List teams that the authenticated user/bot has access to.
/**
* List teams the authenticated user is on
* @param options - List parameters
* @returns Promise resolving to teams list
*/
auth.teams.list(options?: AuthTeamsListArguments): Promise<AuthTeamsListResponse>;
interface AuthTeamsListArguments {
/** Cursor for pagination */
cursor?: string;
/** Include the number of members on each team */
include_icon?: boolean;
/** Maximum number of teams to return */
limit?: number;
}Usage Examples:
// List all teams
const teams = await web.auth.teams.list();
console.log(`User is on ${teams.teams.length} teams`);
for (const team of teams.teams) {
console.log(`Team: ${team.name} (${team.id})`);
}
// Paginate through teams
let cursor;
const allTeams = [];
do {
const result = await web.auth.teams.list({
cursor,
limit: 100
});
allTeams.push(...result.teams);
cursor = result.response_metadata?.next_cursor;
} while (cursor);Exchange authorization codes for access tokens using OAuth 2.0.
/**
* Exchange an OAuth authorization code for an access token
* @param options - OAuth access parameters
* @returns Promise resolving to OAuth access response
*/
oauth.v2.access(options: OauthV2AccessArguments): Promise<OauthV2AccessResponse>;
interface OauthV2AccessArguments {
/** Client ID from your Slack app */
client_id: string;
/** Client secret from your Slack app */
client_secret: string;
/** Authorization code from OAuth redirect */
code: string;
/** Redirect URI that was used to generate the code */
redirect_uri?: string;
}Usage Examples:
// Exchange authorization code for access token
const oauthResult = await web.oauth.v2.access({
client_id: process.env.SLACK_CLIENT_ID,
client_secret: process.env.SLACK_CLIENT_SECRET,
code: 'authorization-code-from-redirect'
});
if (oauthResult.ok) {
console.log('OAuth successful!');
console.log('Access token:', oauthResult.access_token);
console.log('Token type:', oauthResult.token_type);
console.log('Scope:', oauthResult.scope);
console.log('Bot user ID:', oauthResult.bot_user_id);
console.log('Team ID:', oauthResult.team.id);
console.log('Team name:', oauthResult.team.name);
// Store the access token for future use
const userToken = oauthResult.access_token;
const botToken = oauthResult.access_token; // For bot tokens
}Exchange refresh tokens for new access tokens.
/**
* Exchange a refresh token for a new access token
* @param options - Token exchange parameters
* @returns Promise resolving to new token details
*/
oauth.v2.exchange(options: OauthV2ExchangeArguments): Promise<OauthV2ExchangeResponse>;
interface OauthV2ExchangeArguments {
/** Client ID from your Slack app */
client_id: string;
/** Client secret from your Slack app */
client_secret: string;
/** Grant type (should be 'refresh_token') */
grant_type: string;
/** Refresh token to exchange */
refresh_token: string;
}Usage Examples:
// Exchange refresh token for new access token
const exchangeResult = await web.oauth.v2.exchange({
client_id: process.env.SLACK_CLIENT_ID,
client_secret: process.env.SLACK_CLIENT_SECRET,
grant_type: 'refresh_token',
refresh_token: storedRefreshToken
});
if (exchangeResult.ok) {
console.log('Token refreshed!');
console.log('New access token:', exchangeResult.access_token);
console.log('New refresh token:', exchangeResult.refresh_token);
console.log('Expires in:', exchangeResult.expires_in, 'seconds');
// Update stored tokens
updateStoredTokens({
access_token: exchangeResult.access_token,
refresh_token: exchangeResult.refresh_token
});
}Get OpenID Connect tokens and user information for identity verification.
/**
* Exchange an authorization code for OpenID Connect tokens
* @param options - OpenID Connect token parameters
* @returns Promise resolving to OpenID tokens
*/
openid.connect.token(options: OpenidConnectTokenArguments): Promise<OpenidConnectTokenResponse>;
/**
* Get user information using OpenID Connect
* @param options - User info parameters
* @returns Promise resolving to user information
*/
openid.connect.userInfo(options?: OpenidConnectUserInfoArguments): Promise<OpenidConnectUserInfoResponse>;
interface OpenidConnectTokenArguments {
/** Client ID from your Slack app */
client_id: string;
/** Client secret from your Slack app */
client_secret: string;
/** Authorization code from OAuth redirect */
code: string;
/** Grant type (should be 'authorization_code') */
grant_type?: string;
/** Redirect URI used to generate the code */
redirect_uri?: string;
}
interface OpenidConnectUserInfoArguments {
/** OpenID Connect token */
token?: string;
}Usage Examples:
// Get OpenID Connect token
const oidcToken = await web.openid.connect.token({
client_id: process.env.SLACK_CLIENT_ID,
client_secret: process.env.SLACK_CLIENT_SECRET,
code: 'authorization-code',
grant_type: 'authorization_code'
});
if (oidcToken.ok) {
console.log('OpenID token:', oidcToken.id_token);
console.log('Access token:', oidcToken.access_token);
}
// Get user info with OpenID Connect
const userInfo = await web.openid.connect.userInfo();
console.log('User ID:', userInfo.sub);
console.log('Email:', userInfo.email);
console.log('Name:', userInfo.name);
console.log('Team ID:', userInfo['https://slack.com/team_id']);Legacy OAuth 1.0 implementation (deprecated - use OAuth V2 instead).
/**
* Exchange OAuth 1.0 authorization code for access token (DEPRECATED)
* @param options - OAuth V1 parameters
* @returns Promise resolving to OAuth V1 response
*/
oauth.access(options: OauthAccessArguments): Promise<OauthAccessResponse>;
interface OauthAccessArguments {
/** Client ID from your Slack app */
client_id: string;
/** Client secret from your Slack app */
client_secret: string;
/** Authorization code from OAuth redirect */
code: string;
/** Redirect URI used to generate the code */
redirect_uri?: string;
/** Set to true to retrieve a bot token */
single_channel?: boolean;
}Usage Examples:
// Legacy OAuth V1 (deprecated - use oauth.v2.access instead)
const legacyOauth = await web.oauth.access({
client_id: process.env.SLACK_CLIENT_ID,
client_secret: process.env.SLACK_CLIENT_SECRET,
code: 'authorization-code'
});
console.log('⚠️ Using deprecated OAuth V1 - migrate to OAuth V2');A complete example showing how to implement OAuth 2.0 flow in a web application.
/**
* Example OAuth implementation for web applications
*/
interface OAuthState {
access_token?: string;
refresh_token?: string;
user_id?: string;
team_id?: string;
expires_at?: number;
}
class SlackOAuthManager {
private clientId: string;
private clientSecret: string;
private redirectUri: string;
constructor(clientId: string, clientSecret: string, redirectUri: string) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.redirectUri = redirectUri;
}
/**
* Generate OAuth authorization URL
*/
getAuthorizationUrl(scopes: string[], state?: string): string {
const params = new URLSearchParams({
client_id: this.clientId,
scope: scopes.join(','),
redirect_uri: this.redirectUri,
response_type: 'code'
});
if (state) {
params.set('state', state);
}
return `https://slack.com/oauth/v2/authorize?${params.toString()}`;
}
/**
* Complete OAuth flow
*/
async completeOAuth(code: string): Promise<OAuthState> {
const web = new WebClient();
const result = await web.oauth.v2.access({
client_id: this.clientId,
client_secret: this.clientSecret,
code,
redirect_uri: this.redirectUri
});
return {
access_token: result.access_token,
refresh_token: result.refresh_token,
user_id: result.authed_user?.id,
team_id: result.team?.id,
expires_at: result.expires_in ? Date.now() + (result.expires_in * 1000) : undefined
};
}
/**
* Refresh access token
*/
async refreshToken(refreshToken: string): Promise<OAuthState> {
const web = new WebClient();
const result = await web.oauth.v2.exchange({
client_id: this.clientId,
client_secret: this.clientSecret,
grant_type: 'refresh_token',
refresh_token: refreshToken
});
return {
access_token: result.access_token,
refresh_token: result.refresh_token,
expires_at: result.expires_in ? Date.now() + (result.expires_in * 1000) : undefined
};
}
}Usage Examples:
// Initialize OAuth manager
const oauthManager = new SlackOAuthManager(
process.env.SLACK_CLIENT_ID,
process.env.SLACK_CLIENT_SECRET,
'https://myapp.com/oauth/callback'
);
// Step 1: Redirect user to Slack for authorization
const authUrl = oauthManager.getAuthorizationUrl([
'chat:write',
'channels:read',
'users:read'
], 'random-state-string');
console.log('Redirect user to:', authUrl);
// Step 2: Handle OAuth callback
app.get('/oauth/callback', async (req, res) => {
const { code, state } = req.query;
try {
const oauthState = await oauthManager.completeOAuth(code);
// Store tokens securely
await storeUserTokens(oauthState.user_id, oauthState);
res.redirect('/success');
} catch (error) {
console.error('OAuth error:', error);
res.redirect('/error');
}
});
// Step 3: Use stored tokens
async function makeSlackCall(userId: string) {
const tokens = await getUserTokens(userId);
// Check if token needs refresh
if (tokens.expires_at && Date.now() > tokens.expires_at) {
const refreshed = await oauthManager.refreshToken(tokens.refresh_token);
await storeUserTokens(userId, refreshed);
tokens.access_token = refreshed.access_token;
}
const web = new WebClient(tokens.access_token);
return await web.chat.postMessage({
channel: '#general',
text: 'Hello from OAuth!'
});
}interface AuthTestResponse extends WebAPICallResult {
url: string;
team: string;
user: string;
team_id: string;
user_id: string;
bot_id?: string;
is_enterprise_install?: boolean;
}
interface OauthV2AccessResponse extends WebAPICallResult {
access_token: string;
token_type: string;
scope: string;
bot_user_id?: string;
app_id: string;
team: {
id: string;
name: string;
};
enterprise?: {
id: string;
name: string;
};
authed_user?: {
id: string;
scope?: string;
access_token?: string;
token_type?: string;
};
refresh_token?: string;
expires_in?: number;
}
interface AuthTeamsListResponse extends WebAPICallResult {
teams: {
id: string;
name: string;
icon?: {
image_34?: string;
image_44?: string;
image_68?: string;
image_88?: string;
image_102?: string;
image_132?: string;
image_230?: string;
};
}[];
response_metadata?: {
next_cursor?: string;
};
}
interface OpenidConnectUserInfoResponse extends WebAPICallResult {
sub: string;
email: string;
email_verified: boolean;
name: string;
picture: string;
given_name: string;
family_name: string;
locale: string;
'https://slack.com/team_id': string;
'https://slack.com/user_id': string;
}Install with Tessl CLI
npx tessl i tessl/npm-slack--web-api