@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
JavaScript
"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