Source: messaging/connectors/slack/SlackAuth.js

/**
 * Licensed Materials - Property of IBM
 * IBM Cognos Products: Collaboration
 * (C) Copyright IBM Corp. 2017, 2021
 *
 * US Government Users Restricted Rights - Use, duplication or disclosure
 * restricted by GSA ADP Schedule Contract with IBM Corp.
 */
define([
	'../../../lib/@waca/core-client/js/core-client/ui/core/Class',
	'../../utils/PopupWindow',
	'../../../nls/StringResources'
], function (Class, PopupWindow, StringResources) {
	'use strict';

	// This template is been encoded
	// Before encoded, it should be
	// let AUTH_URL_TEMPLATE = 'https://{workspaceUrl}.slack.com/?redir=/oauth?client_id={clientId}&scope={authScope}&state={authState}&redirect_uri={redirectUri}'
	var AUTH_URL_TEMPLATE = 'https://{workspaceUrl}.slack.com/?redir=%2Foauth%3Fscope%3D{authScope}%26state%3D{authState}%26client_id%3D{clientId}%26redirect_uri%3D{redirectUri}';
	var REDIRECT_URI = '/v1/collaboration/auth/slack';
	var WINDOW_W = 720;
	var WINDOW_H = 580;

	var SlackAuth = Class.extend( /** @lends SlackAuth */ {

		/**
		 * @desc Creates a Slack auth object that knows how to get saved tokens or sign in with Slack to gain new tokens.
		 * @constructs SlackAuth
		 * @extends Class
		 * @public
		 * @param {Object} glassContext - the Glass context, mandatory
		 * @returns an object for Slack auth operations
		 *
		 * @example var slackAuth = new SlackAuth(glassContext);
		 */
		init: function (glassContext) {
			SlackAuth.inherited('init', this, arguments);
			this.glassContext = glassContext;
		},

		getRedirectUrl: function (location) {
			var origin = location.origin || (location.protocol + '//' + location.host);
			var pathname = location.pathname || '';
			if (pathname.lastIndexOf('/') !== -1) {
				pathname = pathname.substring(0, pathname.lastIndexOf('/'));
			}
			return origin + pathname + REDIRECT_URI;
		},

		/**
		 * Signs in with Slack to get access token.
		 * @instance
		 * @param {object} options Options
		 * @param {string} options.authScope OAuth scope
		 * @param {string} options.authState OAuth state
		 * @param {string} options.clientId app client ID
		 * @param {string} options.workspaceUrl URL of Slack workspace
		 * @returns {promise} a JSON object
		 */
		authWithSlack: function (options) {
			var coords = PopupWindow.center(WINDOW_W, WINDOW_H);
			var uri = this.getRedirectUrl(window.location);
			var resolved = false;

			options.redirectUri = uri + '?redirect_uri=' + uri;
			var authUrl = AUTH_URL_TEMPLATE.replace(/\{([A-Za-z]+)\}/g, function (match, param) {
				return encodeURIComponent(options[param]) || '';
			});

			return new Promise(function (resolve, reject) {
				window.addEventListener('message', function (event) {
					try {
						resolve(JSON.parse(event.data));
						resolved = true;
					} catch (error) {
						// parse can fail parsing the json
						console.error(error);
					}
				}, {
					once: true
				});

				window.slackAuthCallback = function (data) {
					try {
						resolve(JSON.parse(data));
						resolved = true;
					} catch (error) {
						// parse can fail parsing the json
						console.error(error);
					}
				};

				var success = PopupWindow.open(
					authUrl,
					'SlackAuth',
					['width=' + WINDOW_W, 'height=' + WINDOW_H, 'top=' + coords.top, 'left=' + coords.left, 'scrollbars=yes', 'resizable=yes', 'status=yes'].join(','),
					function () {
						if (!resolved) {
							// The popup window was been closed without being resolved. That's an error.
							var error = new Error(StringResources.get('error_auth_failure_generic'));
							error.code = 'auth_closed';
							reject(error);
						}
					}
				);
				if (!success) {
					// The popup window could not be opened. That's an error.
					var error = new Error(StringResources.get('error_popup_window'));
					error.code = 'no_popup_window';
					reject(error);
				}
			});
		}
	});

	return SlackAuth;
});