or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

error-handling.mdindex.mdinstallation-storage.mdoauth-flow.mdstate-management.md

oauth-flow.mddocs/

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

```