0
# OAuth Flow Management
1
2
Complete OAuth 2.0 flow implementation for Slack app installations, handling URL generation, callback processing, and authorization queries with support for both OAuth v1 and v2.
3
4
## Capabilities
5
6
### InstallProvider Class
7
8
Main OAuth coordinator that manages the complete OAuth flow from installation to authorization.
9
10
```typescript { .api }
11
/**
12
* InstallProvider manages the complete OAuth flow for Slack app installations
13
*/
14
class InstallProvider {
15
/** OAuth state store for CSRF protection */
16
public stateStore?: StateStore;
17
/** Installation data storage */
18
public installationStore: InstallationStore;
19
20
/**
21
* Initialize OAuth provider with configuration options
22
* @param options - OAuth configuration including client credentials and stores
23
*/
24
constructor(options: InstallProviderOptions);
25
26
/**
27
* Handle requests to the install path, rendering install page or redirecting to OAuth
28
* @param req - Incoming HTTP request
29
* @param res - HTTP response for rendering install page
30
* @param options - Optional install path configuration
31
* @param installOptions - Optional OAuth parameters for this installation
32
*/
33
async handleInstallPath(
34
req: IncomingMessage,
35
res: ServerResponse,
36
options?: InstallPathOptions,
37
installOptions?: InstallURLOptions
38
): Promise<void>;
39
40
/**
41
* Generate Slack OAuth installation URL
42
* @param options - OAuth parameters including scopes and redirect settings
43
* @returns OAuth URL for redirecting users to Slack
44
*/
45
async generateInstallUrl(options: InstallURLOptions): Promise<string>;
46
47
/**
48
* Handle OAuth callback from Slack after user authorization
49
* @param req - Incoming callback request with authorization code
50
* @param res - HTTP response for success/failure handling
51
* @param options - Optional callback handlers for success/failure
52
*/
53
async handleCallback(
54
req: IncomingMessage,
55
res: ServerResponse,
56
options?: CallbackOptions
57
): Promise<void>;
58
59
/**
60
* Authorize API requests by fetching installation data
61
* @param source - Query parameters to identify the installation
62
* @returns Authorization result with tokens and identifiers
63
*/
64
async authorize(source: InstallationQuery<boolean>): Promise<AuthorizeResult>;
65
}
66
```
67
68
### InstallProviderOptions
69
70
Configuration options for initializing the OAuth provider.
71
72
```typescript { .api }
73
interface InstallProviderOptions {
74
/** Client ID from Slack app configuration */
75
clientId: string;
76
/** Client Secret from Slack app configuration */
77
clientSecret: string;
78
/** Optional custom installation store (defaults to MemoryInstallationStore) */
79
installationStore?: InstallationStore;
80
/** Optional custom Slack authorization URL */
81
authorizationUrl?: string;
82
/** Optional custom state store for OAuth state management */
83
stateStore?: StateStore;
84
/** Secret for built-in state store encryption */
85
stateSecret?: string;
86
/** OAuth version: "v1" for Classic Apps, "v2" for modern Apps (default: "v2") */
87
authVersion?: "v1" | "v2";
88
/** Enable/disable state verification for CSRF protection (default: true) */
89
stateVerification?: boolean;
90
/** Legacy state verification mode for backward compatibility (default: false) */
91
legacyStateVerification?: boolean;
92
/** Cookie name for state parameter storage (default: "slack-app-oauth-state") */
93
stateCookieName?: string;
94
/** State cookie expiration in seconds (default: 600) */
95
stateCookieExpirationSeconds?: number;
96
/** Skip install path rendering and redirect immediately (default: false) */
97
directInstall?: boolean;
98
/** Custom HTML renderer for install path */
99
renderHtmlForInstallPath?: (url: string) => string;
100
/** Custom logger instance */
101
logger?: Logger;
102
/** Log level when using default logger */
103
logLevel?: LogLevel;
104
/** Default installation URL options */
105
installUrlOptions?: InstallURLOptions;
106
/** Additional WebClient options (excluding logger and logLevel) */
107
clientOptions?: Omit<WebClientOptions, 'logger' | 'logLevel'>;
108
}
109
```
110
111
### InstallURLOptions
112
113
Options for configuring OAuth installation URLs.
114
115
```typescript { .api }
116
interface InstallURLOptions {
117
/** OAuth scopes to request from user (required) */
118
scopes: string | string[];
119
/** Additional user scopes for user token (OAuth v2 only) */
120
userScopes?: string | string[];
121
/** Custom redirect URI (must match app configuration) */
122
redirectUri?: string;
123
/** Team ID for direct team installation */
124
teamId?: string;
125
/** Additional metadata to pass through OAuth flow */
126
metadata?: string;
127
}
128
```
129
130
### CallbackOptions
131
132
Options for handling OAuth callback responses.
133
134
```typescript { .api }
135
interface CallbackOptions {
136
/**
137
* Custom logic before installation execution
138
* Return false to skip installation and handle response manually
139
*/
140
beforeInstallation?: (
141
options: InstallURLOptions,
142
callbackReq: IncomingMessage,
143
callbackRes: ServerResponse
144
) => Promise<boolean>;
145
146
/**
147
* Custom logic after installation but before storage
148
* Return false to skip storage and handle response manually
149
*/
150
afterInstallation?: (
151
installation: Installation<"v1" | "v2", boolean>,
152
options: InstallURLOptions,
153
callbackReq: IncomingMessage,
154
callbackRes: ServerResponse
155
) => Promise<boolean>;
156
157
/** Custom success handler after successful OAuth flow */
158
success?: (
159
installation: Installation<"v1" | "v2", boolean>,
160
installOptions: InstallURLOptions,
161
req: IncomingMessage,
162
res: ServerResponse
163
) => void;
164
165
/** Async version of success handler (both execute if provided) */
166
successAsync?: (
167
installation: Installation<"v1" | "v2", boolean>,
168
installOptions: InstallURLOptions,
169
req: IncomingMessage,
170
res: ServerResponse
171
) => Promise<void>;
172
173
/** Custom failure handler for OAuth errors */
174
failure?: (
175
error: CodedError,
176
installOptions: InstallURLOptions,
177
req: IncomingMessage,
178
res: ServerResponse
179
) => void;
180
181
/** Async version of failure handler (both execute if provided) */
182
failureAsync?: (
183
error: CodedError,
184
installOptions: InstallURLOptions,
185
req: IncomingMessage,
186
res: ServerResponse
187
) => Promise<void>;
188
}
189
190
/**
191
* Default success handler - sends HTML success page
192
*/
193
function defaultCallbackSuccess(
194
installation: Installation<"v1" | "v2", boolean>,
195
installOptions: InstallURLOptions,
196
req: IncomingMessage,
197
res: ServerResponse
198
): void;
199
200
/**
201
* Default failure handler - sends HTML error page
202
*/
203
function defaultCallbackFailure(
204
error: CodedError,
205
installOptions: InstallURLOptions,
206
req: IncomingMessage,
207
res: ServerResponse
208
): void;
209
```
210
211
### AuthorizeResult
212
213
Result returned from the authorize method containing tokens and identifiers.
214
215
```typescript { .api }
216
interface AuthorizeResult {
217
/** Bot access token for API calls */
218
botToken?: string;
219
/** Bot refresh token for token renewal */
220
botRefreshToken?: string;
221
/** Bot token expiration timestamp (UTC seconds) */
222
botTokenExpiresAt?: number;
223
/** User access token for user-context API calls */
224
userToken?: string;
225
/** User refresh token for token renewal */
226
userRefreshToken?: string;
227
/** User token expiration timestamp (UTC seconds) */
228
userTokenExpiresAt?: number;
229
/** Bot user ID */
230
botId?: string;
231
/** Bot user ID in the workspace */
232
botUserId?: string;
233
/** Team (workspace) ID */
234
teamId?: string;
235
/** Enterprise Grid organization ID */
236
enterpriseId?: string;
237
}
238
```
239
240
### OAuth API Responses
241
242
Response types from Slack OAuth API endpoints.
243
244
```typescript { .api }
245
interface OAuthV2Response extends WebAPICallResult {
246
app_id: string;
247
authed_user: {
248
id: string;
249
scope?: string;
250
access_token?: string;
251
token_type?: string;
252
refresh_token?: string;
253
expires_in?: number;
254
};
255
scope?: string;
256
token_type?: "bot";
257
access_token?: string;
258
refresh_token?: string;
259
expires_in?: number;
260
bot_user_id?: string;
261
team: { id: string; name: string } | null;
262
enterprise: { name: string; id: string } | null;
263
is_enterprise_install: boolean;
264
incoming_webhook?: {
265
url: string;
266
channel: string;
267
channel_id: string;
268
configuration_url: string;
269
};
270
}
271
272
interface OAuthV2TokenRefreshResponse extends WebAPICallResult {
273
app_id: string;
274
scope: string;
275
token_type: "bot" | "user";
276
access_token: string;
277
refresh_token: string;
278
expires_in: number;
279
bot_user_id?: string;
280
team: { id: string; name: string };
281
enterprise: { name: string; id: string } | null;
282
is_enterprise_install: boolean;
283
}
284
```
285
286
### Default HTML Renderer
287
288
Default HTML renderer function for the install path.
289
290
```typescript { .api }
291
/**
292
* Default HTML renderer for install path - creates simple install page
293
* @param url - OAuth installation URL to redirect to
294
* @returns HTML string for install page
295
*/
296
function defaultRenderHtmlForInstallPath(url: string): string;
297
```
298
299
**Usage Examples:**
300
301
```typescript
302
import { InstallProvider, InstallURLOptions } from "@slack/oauth";
303
304
// Basic setup
305
const installer = new InstallProvider({
306
clientId: process.env.SLACK_CLIENT_ID!,
307
clientSecret: process.env.SLACK_CLIENT_SECRET!,
308
stateSecret: "my-secret-key",
309
});
310
311
// Generate install URL
312
const installUrl = await installer.generateInstallUrl({
313
scopes: ["chat:write", "commands"],
314
userScopes: ["chat:write"],
315
metadata: "custom-data",
316
});
317
318
// Handle install path
319
app.get("/slack/install", async (req, res) => {
320
await installer.handleInstallPath(req, res, {
321
scopes: ["chat:write", "commands"],
322
});
323
});
324
325
// Handle OAuth callback
326
app.get("/slack/oauth_redirect", async (req, res) => {
327
await installer.handleCallback(req, res, {
328
success: (installation, options, req, res) => {
329
console.log("Installation successful:", installation.team?.id);
330
res.send("Success!");
331
},
332
failure: (error, options, req, res) => {
333
console.error("Installation failed:", error.message);
334
res.send("Installation failed");
335
},
336
});
337
});
338
339
// Authorize requests
340
const auth = await installer.authorize({
341
teamId: "T1234567890",
342
isEnterpriseInstall: false,
343
});
344
345
if (auth.botToken) {
346
// Use bot token for API calls
347
const client = new WebClient(auth.botToken);
348
}
349
```