Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@slack/oauth

Package Overview
Dependencies
Maintainers
15
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@slack/oauth - npm Package Compare versions

Comparing version 1.1.0-beta.1 to 1.1.0-orgAppsBeta.2

45

dist/index.d.ts

@@ -25,6 +25,10 @@ /// <reference types="node" />

/**
* Fetches data from the installationStore.
* Fetches data from the installationStore for non Org Installations.
*/
authorize(source: InstallationQuery): Promise<AuthorizeResult>;
/**
* Fetches data from the installationStore for Org Installations.
*/
orgAuthorize(source: OrgInstallationQuery): Promise<AuthorizeResult>;
/**
* Returns a URL that is suitable for including in an Add to Slack button

@@ -63,3 +67,3 @@ * Uses stateStore to generate a value for the state query param.

export interface CallbackOptions {
success?: (installation: Installation, options: InstallURLOptions, callbackReq: IncomingMessage, callbackRes: ServerResponse) => void;
success?: (installation: Installation | OrgInstallation, options: InstallURLOptions, callbackReq: IncomingMessage, callbackRes: ServerResponse) => void;
failure?: (error: CodedError, options: InstallURLOptions, callbackReq: IncomingMessage, callbackRes: ServerResponse) => void;

@@ -73,3 +77,5 @@ }

storeInstallation: (installation: Installation, logger?: Logger) => Promise<void>;
storeOrgInstallation?: (installation: OrgInstallation, logger?: Logger) => Promise<void>;
fetchInstallation: (query: InstallationQuery, logger?: Logger) => Promise<Installation>;
fetchOrgInstallation?: (query: OrgInstallationQuery, logger?: Logger) => Promise<OrgInstallation>;
}

@@ -80,3 +86,3 @@ export interface Installation {

name: string;
} | null;
};
enterprise?: {

@@ -107,2 +113,28 @@ id: string;

}
export interface OrgInstallation {
enterprise: {
id: string;
name?: string;
};
bot?: {
token: string;
scopes: string[];
id?: string;
userId: string;
};
user: {
token?: string;
scopes?: string[];
id: string;
};
incomingWebhook?: {
url: string;
channel: string;
channelId: string;
configurationUrl: string;
};
appId: string | undefined;
tokenType?: string;
isEnterpriseInstall: boolean;
}
export interface InstallationQuery {

@@ -114,2 +146,8 @@ teamId: string;

}
export interface OrgInstallationQuery {
enterpriseId: string;
teamId?: string;
userId?: string;
conversationId?: string;
}
export interface AuthorizeResult {

@@ -120,4 +158,5 @@ botToken?: string;

botUserId?: string;
teamId?: string;
}
export { Logger, LogLevel } from './logger';
//# sourceMappingURL=index.d.ts.map

195

dist/index.js
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

@@ -86,6 +97,7 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }

this.authorize = this.authorize.bind(this);
this.orgAuthorize = this.orgAuthorize.bind(this);
this.authVersion = authVersion;
}
/**
* Fetches data from the installationStore.
* Fetches data from the installationStore for non Org Installations.
*/

@@ -107,2 +119,3 @@ InstallProvider.prototype.authorize = function (source) {

authResult.userToken = queryResult.user.token;
authResult.teamId = queryResult.team.id;
if (queryResult.bot !== undefined) {

@@ -123,2 +136,37 @@ authResult.botToken = queryResult.bot.token;

/**
* Fetches data from the installationStore for Org Installations.
*/
InstallProvider.prototype.orgAuthorize = function (source) {
return __awaiter(this, void 0, void 0, function () {
var queryResult, authResult, error_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
if (this.installationStore.fetchOrgInstallation === undefined) {
throw new Error('Installation Store is missing the fetchOrgInstallation method');
}
return [4 /*yield*/, this.installationStore.fetchOrgInstallation(source, this.logger)];
case 1:
queryResult = _a.sent();
if (queryResult === undefined) {
throw new Error('Failed fetching data from the Installation Store');
}
authResult = {};
authResult.userToken = queryResult.user.token;
if (queryResult.bot !== undefined) {
authResult.botToken = queryResult.bot.token;
authResult.botId = queryResult.bot.id;
authResult.botUserId = queryResult.bot.userId;
}
return [2 /*return*/, authResult];
case 2:
error_2 = _a.sent();
throw new errors_1.AuthorizationError(error_2.message);
case 3: return [2 /*return*/];
}
});
});
};
/**
* Returns a URL that is suitable for including in an Add to Slack button

@@ -189,7 +237,7 @@ * Uses stateStore to generate a value for the state query param.

return __awaiter(this, void 0, void 0, function () {
var parsedUrl, code, state, installOptions, client, resp, installation, botId, botId, error_2;
var parsedUrl, code, state, installOptions, client, resp, installation, botId, botId, error_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 10, , 11]);
_a.trys.push([0, 13, , 14]);
if (req.url !== undefined) {

@@ -263,25 +311,35 @@ parsedUrl = url_1.parse(req.url, true);

// resp obj for v2 - https://api.slack.com/methods/oauth.v2.access#response
installation = {
team: resp.team,
appId: resp.app_id,
user: {
token: resp.authed_user.access_token,
scopes: resp.authed_user.scope !== undefined ? resp.authed_user.scope.split(',') : undefined,
id: resp.authed_user.id,
},
bot: {
scopes: resp.scope.split(','),
token: resp.access_token,
userId: resp.bot_user_id,
id: botId,
},
tokenType: resp.token_type,
isEnterpriseInstall: resp.is_enterprise_install,
};
if (resp.enterprise !== null) {
installation.enterprise = {
id: resp.enterprise.id,
name: resp.enterprise.name,
if (resp.is_enterprise_install) {
// org installation
installation = {
enterprise: resp.enterprise,
appId: resp.app_id,
user: {
token: resp.authed_user.access_token,
scopes: resp.authed_user.scope !== undefined ? resp.authed_user.scope.split(',') : undefined,
id: resp.authed_user.id,
},
bot: {
scopes: resp.scope.split(','),
token: resp.access_token,
userId: resp.bot_user_id,
id: botId,
},
tokenType: resp.token_type,
isEnterpriseInstall: resp.is_enterprise_install,
};
}
else {
// workspace or non org enterprise installation
installation = __assign(__assign(__assign({ team: resp.team }, (resp.enterprise !== null && resp.enterprise !== undefined) ? { enterprise: resp.enterprise } : {}), { appId: resp.app_id, user: {
token: resp.authed_user.access_token,
scopes: resp.authed_user.scope !== undefined ? resp.authed_user.scope.split(',') : undefined,
id: resp.authed_user.id,
}, bot: {
scopes: resp.scope.split(','),
token: resp.access_token,
userId: resp.bot_user_id,
id: botId,
}, tokenType: resp.token_type }), (resp.is_enterprise_install !== undefined) ? { isEnterpriseInstall: resp.is_enterprise_install } : {});
}
_a.label = 8;

@@ -297,7 +355,20 @@ case 8:

}
// save access code to installationStore
return [4 /*yield*/, this.installationStore.storeInstallation(installation, this.logger)];
if (!installation.isEnterpriseInstall) return [3 /*break*/, 10];
if (this.installationStore.storeOrgInstallation === undefined) {
throw new Error('Installation store is missing the storeOrgInstallation method');
}
// save token to orgInstallationStore
return [4 /*yield*/, this.installationStore.storeOrgInstallation(installation, this.logger)];
case 9:
// save access code to installationStore
// save token to orgInstallationStore
_a.sent();
return [3 /*break*/, 12];
case 10:
// save token to InstallationStore
return [4 /*yield*/, this.installationStore.storeInstallation(installation, this.logger)];
case 11:
// save token to InstallationStore
_a.sent();
_a.label = 12;
case 12:
if (options !== undefined && options.success !== undefined) {

@@ -311,16 +382,16 @@ this.logger.debug('calling passed in options.success');

}
return [3 /*break*/, 11];
case 10:
error_2 = _a.sent();
this.logger.error(error_2);
return [3 /*break*/, 14];
case 13:
error_3 = _a.sent();
this.logger.error(error_3);
if (options !== undefined && options.failure !== undefined) {
this.logger.debug('calling passed in options.failure');
options.failure(error_2, installOptions, req, res);
options.failure(error_3, installOptions, req, res);
}
else {
this.logger.debug('run built-in failure function');
callbackFailure(error_2, installOptions, req, res);
callbackFailure(error_3, installOptions, req, res);
}
return [3 /*break*/, 11];
case 11: return [2 /*return*/];
return [3 /*break*/, 14];
case 14: return [2 /*return*/];
}

@@ -371,6 +442,3 @@ });

// db write
if (installation.isEnterpriseInstall && installation.enterprise !== undefined) {
this.devDB[installation.enterprise.id] = installation;
}
else if (installation.team !== null && installation.team.id !== undefined) {
if (isNotOrgInstall(installation)) {
this.devDB[installation.team.id] = installation;

@@ -385,5 +453,22 @@ }

};
MemoryInstallationStore.prototype.storeOrgInstallation = function (installation, logger) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (logger !== undefined) {
logger.warn('Storing Access Token. Please use a real Installation Store for production!');
}
// db write
if (installation.isEnterpriseInstall) {
this.devDB[installation.enterprise.id] = installation;
}
else {
throw new Error('Failed saving installation data to installationStore');
}
return [2 /*return*/, Promise.resolve()];
});
});
};
// non org app lookup
MemoryInstallationStore.prototype.fetchInstallation = function (query, logger) {
return __awaiter(this, void 0, void 0, function () {
var item;
return __generator(this, function (_a) {

@@ -393,12 +478,20 @@ if (logger !== undefined) {

}
item = undefined;
// enterprise org app installation lookup
if (query.teamId !== undefined) {
return [2 /*return*/, this.devDB[query.teamId]];
}
throw new Error('Failed fetching installation');
});
});
};
// enterprise org app installation lookup
MemoryInstallationStore.prototype.fetchOrgInstallation = function (query, logger) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (logger !== undefined) {
logger.warn('Retrieving Access Token from DB. Please use a real Installation Store for production!');
}
if (query.enterpriseId !== undefined) {
item = this.devDB[query.enterpriseId];
return [2 /*return*/, this.devDB[query.enterpriseId]];
}
// non org app lookup
if (item === undefined && query.teamId !== undefined) {
item = this.devDB[query.teamId];
}
return [2 /*return*/, item];
throw new Error('Failed fetching installation');
});

@@ -412,3 +505,3 @@ });

var redirectUrl;
if (installation.team !== null && installation.team.id !== undefined && installation.appId !== undefined) {
if (isNotOrgInstall(installation) && installation.appId !== undefined) {
// redirect back to Slack native app

@@ -453,4 +546,8 @@ // Changes to the workspace app was installed to, to the app home

}
// type guard to confirm an installation isn't an OrgInstallation
function isNotOrgInstall(installation) {
return installation.team !== undefined && installation.team !== null;
}
var logger_2 = require("./logger");
exports.LogLevel = logger_2.LogLevel;
//# sourceMappingURL=index.js.map
{
"name": "@slack/oauth",
"version": "1.1.0-beta.1",
"version": "1.1.0-orgAppsBeta.2",
"description": "Official library for interacting with Slack's Oauth endpoints",

@@ -5,0 +5,0 @@ "author": "Slack Technologies, Inc.",

@@ -35,3 +35,3 @@ # Slack OAuth

This package exposes an `InstallProvider` class, which sets up the required configuration and exposes methods such as `generateInstallUrl`, `handleCallback`, `authorize` for use within your apps. At a minimum, `InstallProvider` takes a `clientId` and `clientSecret` (both which can be obtained under the **Basic Information** of your app configuration). `InstallProvider` also requires a `stateSecret`, which is used to encode the generated state, and later used to decode that same state to verify it wasn't tampered with during the OAuth flow. **Note**: This example is not ready for production because it only stores installations (tokens) in memory. Please go to the [storing installations in a database](#storing-installations-in-a-database) section to learn how to plug in your own database.
This package exposes an `InstallProvider` class, which sets up the required configuration and exposes methods such as `generateInstallUrl`, `handleCallback`, `authorize`, `orgAuthorize` for use within your apps. At a minimum, `InstallProvider` takes a `clientId` and `clientSecret` (both which can be obtained under the **Basic Information** of your app configuration). `InstallProvider` also requires a `stateSecret`, which is used to encode the generated state, and later used to decode that same state to verify it wasn't tampered with during the OAuth flow. **Note**: This example is not ready for production because it only stores installations (tokens) in memory. Please go to the [storing installations in a database](#storing-installations-in-a-database) section to learn how to plug in your own database.

@@ -166,6 +166,8 @@ ```javascript

An installation store is an object that provides two methods: `storeInstallation` and `fetchInstallation`. `storeInstallation` takes an `installation` as an argument, which is an object that contains all installation related data (like tokens, teamIds, enterpriseIds, etc). `fetchInstallation` takes in a `installQuery`, which is used to query the database. The `installQuery` can contain `teamId`, `enterpriseId`, `userId`, and `conversationId`.
An installation store is an object that provides four methods: `storeInstallation`, `storeOrgInstallation`, `fetchInstallation` and `fetchOrgInstallation`. `storeInstallation` and `storeOrgInstallation` takes an `installation` as an argument, which is an object that contains all installation related data (like tokens, teamIds, enterpriseIds, etc). `fetchInstallation` and `fetchOrgInstallation` takes in a `installQuery`, which is used to query the database. The `installQuery` can contain `teamId`, `enterpriseId`, `userId`, and `conversationId`.
In the following example, the `installationStore` option is used and the object is defined in line. The required methods are implemented by calling an example database library with simple get and set operations.
**Note**: `fetchOrgInstallation` and `storeOrgInstallation` were introduced to support Org wide app installations (currently in beta).
In the following example, the `installationStore` option is used and the object is defined in line. The methods are implemented by calling an example database library with simple get and set operations.
```javascript

@@ -181,12 +183,8 @@ const installer = new InstallProvider({

// replace myDB.set with your own database or OEM setter
if (installation.isEnterpriseInstall && installation.enterprise !== undefined) {
// enterprise app, org wide installation
myDB.set(installation.enterprise.id, installation);
} else if (installation.team.id !== undefined) {
if (installation.team.id !== undefined) {
// non enterprise org app installation
myDB.set(installation.team.id, installation);
return myDB.set(installation.team.id, installation);
} else {
throw new Error('Failed saving installation data to installationStore');
}
return;
},

@@ -198,15 +196,24 @@ // takes in an installQuery as an argument

// replace myDB.get with your own database or OEM getter
let result = undefined;
// enterprise org app installation lookup
if (InstallQuery.enterpriseId !== undefined) {
result = await myDB.get(installQuery.enterpriseId);
}
// non enterprise org app lookup
if (result === undefined && InstallQuery.teamId !== undefined) {
result = await myDB.get(installQuery.teamId);
return await myDB.get(installQuery.teamId);
},
// takes in an installation object as an argument
// returns nothing
storeOrgInstallation: (installation) => {
// replace myDB.set with your own database or OEM setter
if (installation.isEnterpriseInstall && installation.enterprise !== undefined) {
// enterprise app, org wide installation
return myDB.set(installation.enterprise.id, installation);
} else {
throw new Error('Failed saving installation data to installationStore');
}
return result;
},
// takes in an installQuery as an argument
// installQuery = {teamId: 'string', enterpriseId: 'string', userId: string, conversationId: 'string'};
// returns installation object from database
fetchInstallation: async (installQuery) => {
// replace myDB.get with your own database or OEM getter
// enterprise org app installation lookup
return await myDB.get(installQuery.enterpriseId);
},
},

@@ -219,3 +226,3 @@ });

You can use the the `installationProvider.authorize()` function to fetch data that has been saved in your installation store.
You can use the the `installationProvider.authorize()` function to fetch data that has been saved in your installation store. For Org wide app installations, you can use `installationProvider.orgAuthorize()`

@@ -225,3 +232,4 @@ ```javascript

// installQuery = {teamId: 'string', enterpriseId: 'string', userId: string, conversationId: 'string'};
const result = installer.installationStore.fetchInstallation({teamId:'my-team-ID', enterpriseId:'my-enterprise-ID'});
const result = installer.authorize({teamId:'my-team-ID'});
const orgResult = installer.orgAuthorize({enterpriseId:'my-enterprise-ID'});
/*

@@ -242,3 +250,3 @@ result = {

The `installer.authorize()` method only returns a subset of the installation data returned by the installation store. To fetch the entire saved installation, use the `installer.installationStore.fetchInstallation()` method.
The `installer.authorize()`/`installer.orgAuthorize()` methods only returns a subset of the installation data returned by the installation store. To fetch the entire saved installation, use the `installer.installationStore.fetchInstallation()`/`installer.installationStore.fetchOrgInstallation()` methods.

@@ -250,2 +258,3 @@ ```javascript

const result = installer.installationStore.fetchInstallation({teamId:'my-team-ID', enterpriseId:'my-enterprise-ID'});
const orgResult = installer.installationStore.fetchOrgInstallation({enterpriseId:'my-enterprise-ID'});
```

@@ -252,0 +261,0 @@ </details>

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc