UNPKG

@mvx/identity

Version:

identity is oidc for mvc, type-mvc is base on koa. Decorator, Ioc, AOP mvc framework on server.

277 lines (275 loc) 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OAuth2 = exports.OAuth2Error = void 0; var tslib_1 = require("tslib"); var http = require("http"); var https = require("https"); var querystring = require("querystring"); var url_1 = require("url"); var errors_1 = require("../errors"); /** * oauth2 error. * * @export * @class OAuth2Error * @extends {AuthenticationError} */ var OAuth2Error = /** @class */ (function (_super) { tslib_1.__extends(OAuth2Error, _super); // tslint:disable-next-line:variable-name function OAuth2Error(status, message, error_description) { return _super.call(this, status, message, error_description) || this; } OAuth2Error.ρAnn = function () { return { "name": "OAuth2Error" }; }; return OAuth2Error; }(errors_1.AuthenticationError)); exports.OAuth2Error = OAuth2Error; /** * oauth2 * * @export * @class OAuth2 */ var OAuth2 = /** @class */ (function () { function OAuth2(clientId, clientSecret, baseSite, authorizeUrl, accessTokenUrl, customHeader) { if (authorizeUrl === void 0) { authorizeUrl = '/oauth/authorize'; } if (accessTokenUrl === void 0) { accessTokenUrl = '/oauth/access_token'; } if (customHeader === void 0) { customHeader = {}; } this.clientId = clientId; this.clientSecret = clientSecret; this.baseSite = baseSite; this.authorizeUrl = authorizeUrl; this.accessTokenUrl = accessTokenUrl; this.customHeader = customHeader; this.accessTokenName = 'access_token'; this.authMethod = 'Bearer'; this.useAuthorizationHeaderForGET = false; this.agent = undefined; } Object.defineProperty(OAuth2.prototype, "Agent", { get: function () { return this.agent; }, // Allows you to set an agent to use instead of the default HTTP or // HTTPS agents. Useful when dealing with your own certificates. set: function (agent) { this.agent = agent; }, enumerable: false, configurable: true }); Object.defineProperty(OAuth2.prototype, "AccessTokenName", { get: function () { return this.accessTokenName; }, // This 'hack' method is required for sites that don't use // 'access_token' as the name of the access token (for requests). // ( http://tools.ietf.org/html/draft-ietf-oauth-v2-16#section-7 ) // it isn't clear what the correct value should be atm, so allowing // for specific (temporary?) override for now. set: function (name) { this.accessTokenName = name; }, enumerable: false, configurable: true }); Object.defineProperty(OAuth2.prototype, "AuthMethod", { get: function () { return this.authMethod; }, // Sets the authorization method for Authorization header. // e.g. Authorization: Bearer <token> # "Bearer" is the authorization method. set: function (authMethod) { this.authMethod = authMethod; }, enumerable: false, configurable: true }); Object.defineProperty(OAuth2.prototype, "UseAuthorizationHeaderForGET", { get: function () { return this.useAuthorizationHeaderForGET; }, // If you use the OAuth2 exposed 'get' method (and don't construct your own _request call ) // this will specify whether to use an 'Authorize' header instead of passing the access_token as a query parameter set: function (useIt) { this.useAuthorizationHeaderForGET = useIt; }, enumerable: false, configurable: true }); Object.defineProperty(OAuth2.prototype, "ClientId", { get: function () { return this.clientId; }, enumerable: false, configurable: true }); Object.defineProperty(OAuth2.prototype, "AuthorizeUrl", { get: function () { return this.authorizeUrl; }, enumerable: false, configurable: true }); Object.defineProperty(OAuth2.prototype, "AccessTokenUrl", { get: function () { return "" + this.baseSite + this.accessTokenUrl; /* + "?" + querystring.stringify(params); */ }, enumerable: false, configurable: true }); // Build the authorization header. In particular, build the part after the colon. // e.g. Authorization: Bearer <token> # Build "Bearer <token>" OAuth2.prototype.buildAuthHeader = function (token) { return this.authMethod + " " + token; }; OAuth2.prototype.getAuthorizeUrl = function (params) { if (params === void 0) { params = {}; } params.client_id = this.clientId; return "" + this.baseSite + this.authorizeUrl + "?" + querystring.stringify(params); }; OAuth2.prototype.getOAuthAccessToken = function (code, params) { if (params === void 0) { params = {}; } return tslib_1.__awaiter(this, void 0, void 0, function () { var codeParam, postData, postHeaders, result, data, accessToken, refreshToken; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: params.client_id = this.clientId; params.client_secret = this.clientSecret; codeParam = (params.grant_type === 'refresh_token') ? 'refresh_token' : 'code'; params[codeParam] = code; postData = querystring.stringify(params); postHeaders = { 'Content-Type': 'application/x-www-form-urlencoded', }; return [4 /*yield*/, this.request('POST', this.AccessTokenUrl, postHeaders, postData, null)]; case 1: result = (_a.sent()).result; try { // As of http://tools.ietf.org/html/draft-ietf-oauth-v2-07 // responses should be in JSON data = JSON.parse(result); } catch (error) { // .... However both Facebook + Github currently use rev05 of the spec // and neither seem to specify a content-type correctly in their response headers :( // clients of these services will suffer a *minor* performance cost of the exception // being thrown data = querystring.parse(result); } accessToken = data[this.AccessTokenName]; if (!accessToken) { throw new OAuth2Error(400, JSON.stringify(params)); } refreshToken = data.refresh_token; delete data.refresh_token; return [2 /*return*/, { accessToken: accessToken, refreshToken: refreshToken, result: data, }]; } }); }); }; OAuth2.prototype.get = function (url, accessToken) { return tslib_1.__awaiter(this, void 0, void 0, function () { var headers; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: headers = {}; if (this.useAuthorizationHeaderForGET) { headers = { Authorization: this.buildAuthHeader(accessToken) }; accessToken = null; } return [4 /*yield*/, this.request('GET', url, headers, '', accessToken)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; OAuth2.prototype.request = function (method, url, headers, postBody, accessToken) { var _this = this; if (headers === void 0) { headers = {}; } var parsedUrl = url_1.parse(url, true); if (parsedUrl.protocol === 'https:' && !parsedUrl.port) { parsedUrl.port = '443'; } var realHeaders = Object.assign({}, this.customHeader, headers); realHeaders.Host = parsedUrl.host; if (!realHeaders['User-Agent']) { realHeaders['User-Agent'] = 'Node-oauth'; } realHeaders['Content-Length'] = 0; if (postBody) { realHeaders['Content-Length'] = Buffer.isBuffer(postBody) ? postBody.length : Buffer.byteLength(postBody); } if (accessToken && !('Authorization' in realHeaders)) { // It seems that the default value of .query return by URL.parse is {}. // if (!parsedUrl.query) { // parsedUrl.query = {}; // } parsedUrl.query[this.accessTokenName] = accessToken; } var queryStr = querystring.stringify(parsedUrl.query); if (queryStr) { queryStr = '?' + queryStr; } var options = { protocol: parsedUrl.protocol, host: parsedUrl.hostname, port: parsedUrl.port, path: parsedUrl.pathname + queryStr, method: method, headers: realHeaders, }; return new Promise(function (resolve, reject) { _this.executeRequest(options, postBody, function (err, result, response) { return err ? reject(err) : resolve({ result: result, response: response }); }); }); }; OAuth2.prototype.executeRequest = function (options, postBody, callback) { var callbackCalled = false; var result = ''; // set the agent on the request options if (this.agent) { options.agent = this.agent; } var request = options.protocol !== 'https:' ? http.request(options) : https.request(options); request.on('response', function (response) { response.on('data', function (chunk) { result += chunk; }); response.addListener('end', function () { if (!callbackCalled) { callbackCalled = true; if (!(response.statusCode >= 200 && response.statusCode <= 299) && (response.statusCode !== 301) && (response.statusCode !== 302)) { callback(new OAuth2Error(response.statusCode, result)); } else { callback(null, result, response); } } }); }); request.on('error', function (e) { callbackCalled = true; callback(e); }); if ((options.method === 'POST' || options.method === 'PUT') && postBody) { request.write(postBody); } request.end(); }; OAuth2.ρAnn = function () { return { "name": "OAuth2" }; }; return OAuth2; }()); exports.OAuth2 = OAuth2; //# sourceMappingURL=../sourcemaps/passports/oauth2.js.map