@aca-1/a2-composer
Version:
Angular 2 Interface for composer
606 lines • 24.7 kB
JavaScript
import { Location } from '@angular/common';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { COMPOSER } from '../../settings';
import { DataStoreService } from '../data-store.service';
var OAuthService = (function () {
function OAuthService(location, store) {
var _this = this;
this.location = location;
this.store = store;
this.clientId = '';
this.redirectUri = '';
this.loginUrl = '';
this.loginRedirect = '';
this.scope = '';
this.rngUrl = '';
this.oidc = false;
this.state = '';
this.issuer = '';
this.logoutUrl = '';
this.refreshUri = '';
this.login_local = false;
this.login_obs = null;
this._login_obs = null;
this.debug = false;
this._storage = 'local';
this.run_flow = false;
this.needs_login = false;
this.access_token_promise = null;
this.refresh_token_promise = null;
this.valid_access_token_promise = null;
this.valid_id_token_promise = null;
this.auth_header_promise = null;
this.login_obs = new Observable(function (observer) {
_this._login_obs = observer;
});
}
OAuthService.prototype.setStorage = function (storage) {
this._storage = storage;
};
Object.defineProperty(OAuthService.prototype, "login_url", {
get: function () {
return this.createLoginUrl('').then(function (url) {
return url;
});
},
enumerable: true,
configurable: true
});
Object.defineProperty(OAuthService.prototype, "refresh_url", {
get: function () {
return this.createRefreshUrl('').then(function (url) {
return url;
}, function (err) {
return '';
});
},
enumerable: true,
configurable: true
});
OAuthService.prototype.needsLogin = function () {
var _this = this;
setTimeout(function () {
_this._login_obs.next(_this.needs_login);
}, 200);
return this.login_obs;
};
OAuthService.prototype.tryLogin = function (options) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.attemptLogin(options, resolve, reject);
});
};
OAuthService.prototype.tryLoginWithIFrame = function () {
throw new Error('tryLoginWithIFrame has not been implemented so far');
};
OAuthService.prototype.tryRefresh = function (timeoutInMsec) {
throw new Error('tryRefresh has not been implemented so far');
};
OAuthService.prototype.getIdentityClaims = function () {
var claims = this.store[this._storage].getItem(this.clientId + "_id_token_claims_obj")
.then(function (res) { return res; });
if (!claims) {
return null;
}
return JSON.parse(claims);
};
OAuthService.prototype.getIdToken = function () {
return this.store[this._storage].getItem(this.clientId + "_id_token").then(function (res) { return res; });
};
OAuthService.prototype.getAccessToken = function () {
var _this = this;
if (!this.access_token_promise) {
this.access_token_promise = new Promise(function (resolve) {
_this.store[_this._storage].getItem(_this.clientId + "_access_token").then(function (token) {
if (!token) {
_this.store[_this._storage].getItem("accessToken").then(function (token_local) {
resolve(token_local);
_this.access_token_promise = null;
});
}
else {
resolve(token);
_this.access_token_promise = null;
}
});
});
}
return this.access_token_promise;
};
OAuthService.prototype.getRefreshToken = function () {
var _this = this;
if (!this.refresh_token_promise) {
this.refresh_token_promise = new Promise(function (resolve) {
_this.store[_this._storage].getItem(_this.clientId + "_refresh_token").then(function (token) {
if (!token) {
_this.store[_this._storage].getItem("refreshToken").then(function (token_local) {
resolve(token_local);
_this.refresh_token_promise = null;
});
}
else {
resolve(token);
_this.refresh_token_promise = null;
}
});
});
}
return this.refresh_token_promise;
};
OAuthService.prototype.hasValidAccessToken = function () {
var _this = this;
if (!this.valid_access_token_promise) {
this.valid_access_token_promise = new Promise(function (resolve, reject) {
_this.getAccessToken().then(function (token) {
_this.store[_this._storage].getItem(_this.clientId + "_expires_at").then(function (expiresAt) {
setTimeout(function () {
_this.valid_access_token_promise = null;
}, 10);
if (!expiresAt) {
_this.store[_this._storage].getItem("accessExpiry").then(function (expiresAt_local) {
var now = new Date();
if (!expiresAt || parseInt(expiresAt_local, 10) < now.getTime()) {
return resolve(false);
}
return resolve(true);
});
}
else {
var now = new Date();
if (expiresAt && parseInt(expiresAt, 10) < now.getTime()) {
return resolve(false);
}
return resolve(true);
}
});
});
});
}
return this.valid_access_token_promise;
};
OAuthService.prototype.hasValidIdToken = function () {
var _this = this;
if (!this.valid_id_token_promise) {
this.valid_id_token_promise = new Promise(function (resolve, reject) {
if (_this.getIdToken) {
_this.store[_this._storage].getItem(_this.clientId + "_id_token_expires_at")
.then(function (expiresAt) {
var now = new Date();
if (expiresAt && parseInt(expiresAt, 10) < now.getTime()) {
return resolve(false);
}
else {
return resolve(true);
}
});
}
else {
resolve(false);
}
});
}
};
OAuthService.prototype.authorizationHeader = function () {
var _this = this;
if (!this.auth_header_promise) {
this.auth_header_promise = new Promise(function (resolve) {
_this.getAccessToken().then(function (token) {
resolve("Bearer " + token);
setTimeout(function () {
_this.auth_header_promise = null;
}, 1000);
});
});
}
return this.auth_header_promise;
};
OAuthService.prototype.logOut = function () {
var _this = this;
COMPOSER.log('OAUTH', 'Logging out. Clear access tokens...');
var id_token = this.getIdToken();
this.clearAuth();
if (!this.logoutUrl) {
setTimeout(function () {
_this.location.replaceState(_this.location.path(), '');
}, 100);
return;
}
var logoutUrl = this.logoutUrl.replace(/\{\{id_token\}\}/, id_token);
COMPOSER.log('OAUTH', 'Redirecting to logout URL...');
location.href = logoutUrl;
};
OAuthService.prototype.clearAuth = function () {
var items = [
'access_token', 'refresh_token', 'accesstoken', 'refreshtoken',
'id_token', 'idtoken', 'nonce', 'expires', 'login', 'oauth',
];
var keys = this.store[this._storage].keys();
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
var lkey = key.toLowerCase();
for (var _a = 0, items_1 = items; _a < items_1.length; _a++) {
var i = items_1[_a];
if (lkey.indexOf(i) >= 0) {
this.store[this._storage].removeItem(key);
break;
}
}
}
};
OAuthService.prototype.createLoginUrl = function (state) {
var _this = this;
var that = this;
if (typeof state === 'undefined') {
state = '';
}
return this.createAndSaveNonce().then(function (nonce) {
if (state) {
state = nonce + ';' + state;
}
else {
state = nonce;
}
var response_type = _this.response_type ? _this.response_type : 'token';
if (_this.oidc) {
response_type = 'id_token+' + response_type;
}
var url = _this.loginUrl
+ (_this.loginUrl.indexOf('?') < 0 ? '?' : '&') + 'response_type='
+ encodeURIComponent(response_type)
+ '&client_id='
+ encodeURIComponent(_this.clientId)
+ '&state='
+ encodeURIComponent(state)
+ '&redirect_uri='
+ encodeURIComponent(_this.redirectUri)
+ '&scope='
+ encodeURIComponent(_this.scope);
if (_this.oidc) {
url += '&nonce=' + encodeURIComponent(nonce);
}
return url;
});
};
OAuthService.prototype.createRefreshUrl = function (state) {
var _this = this;
if (typeof state === 'undefined') {
state = '';
}
return this.createAndSaveNonce().then(function (nonce) {
var url = _this.refreshUri
+ '?client_id='
+ encodeURIComponent(_this.clientId)
+ '&redirect_uri='
+ encodeURIComponent(_this.redirectUri);
return _this.store[_this._storage].getItem(_this.clientId + "_refresh_token")
.then(function (refresh_token) {
if (!refresh_token) {
return _this.store[_this._storage].getItem("refreshToken").then(function (refresh_token_local) {
if (refresh_token_local) {
url += "&refresh_token=" + encodeURIComponent(refresh_token_local);
url += "&grant_type=" + encodeURIComponent('refresh_token');
return url;
}
else {
url += "&code=" + encodeURIComponent(_this.code) + "&";
url += "grant_type=" + encodeURIComponent('authorization_code');
return url;
}
});
}
else {
url += "&refresh_token=" + encodeURIComponent(refresh_token);
url += "&grant_type=" + encodeURIComponent('refresh_token');
return url;
}
});
});
};
OAuthService.prototype.initImplicitFlow = function (additionalState) {
var _this = this;
if (additionalState === void 0) { additionalState = ''; }
if (!this.clientId || this.clientId === '' || this.run_flow) {
return;
}
this.createLoginUrl(additionalState).then(function (url) {
var path = location.href;
if (location.hash.indexOf(path) >= 0 && location.href.indexOf(location.origin + '/#/') >= 0) {
if (path.indexOf('?') >= 0) {
path = path.split('?')[0];
}
}
var here = path;
_this.store.local.setItem("oauth_redirect", here);
_this.run_flow = true;
_this.store.session.getItem(_this.clientId + "_login").then(function (logged) {
if (logged === 'true' && url.indexOf('http') >= 0) {
COMPOSER.log('OAUTH', 'Logged in. Authorizing...');
_this.store.session.removeItem(_this.clientId + "_login");
location.href = url;
}
else {
COMPOSER.log('OAUTH', 'Not logged in redirecting to provider...');
_this.needs_login = true;
if (_this.login_local) {
_this._login_obs.next(_this.needs_login);
_this.run_flow = false;
}
else {
_this.store.session.setItem(_this.clientId + "_login", 'true');
if (!_this.loginRedirect || _this.loginRedirect === '' && location.origin.indexOf('http') >= 0) {
_this.loginRedirect = location.origin + '/auth/login';
}
else if (_this.loginRedirect && _this.loginRedirect !== '') {
COMPOSER.log('OAUTH', "Login: " + _this.loginRedirect);
location.href = _this.loginRedirect;
}
}
}
});
}, function (err) {
return;
});
};
OAuthService.prototype.callEventIfExists = function (options) {
var that = this;
if (options.onTokenReceived) {
var tokenParams = {
idClaims: that.getIdentityClaims(),
idToken: that.getIdToken(),
accessToken: that.getAccessToken(),
state: that.state,
};
options.onTokenReceived(tokenParams);
}
};
OAuthService.prototype.attemptLogin = function (options, resolve, reject) {
var _this = this;
if (this.clientId && this.clientId !== '') {
options = options || {};
var parts_1 = this.getFragment();
if (Object.keys(parts_1).length <= 1) {
this.store.session.getItem('OAUTH.params').then(function (item) {
if (item) {
parts_1 = JSON.parse(item);
}
_this.store.session.removeItem('OAUTH.params');
_this.processLogin(parts_1, options, resolve, reject);
});
}
else {
this.processLogin(parts_1, options, resolve, reject);
}
}
else {
setTimeout(function () {
_this.attemptLogin(options, resolve, reject);
}, 200);
}
};
OAuthService.prototype.processLogin = function (parts, options, resolve, reject) {
var _this = this;
var accessToken = parts.access_token;
var idToken = parts.id_token;
var state = parts.state;
var code = parts.code;
var refreshToken = parts.refreshToken;
COMPOSER.log('OAUTH', "State: " + state);
COMPOSER.log('OAUTH', "Access: " + accessToken + " | Refresh: " + accessToken);
var oidcSuccess = false;
var oauthSuccess = false;
if ((!accessToken && !code && !refreshToken) || !state) {
return resolve(false);
}
if (this.oidc && !idToken) {
return resolve(false);
}
if (code) {
this.code = code;
}
if (refreshToken) {
this.store[this._storage].setItem(this.clientId + "_refresh_token", refreshToken);
}
this.store[this._storage].getItem(this.clientId + "_nonce")
.then(function (savedNonce) {
var stateParts = state.split(';');
var nonceInState = stateParts[0];
if (savedNonce === nonceInState) {
if (accessToken) {
_this.store[_this._storage].setItem(_this.clientId + "_access_token", accessToken);
}
var expiresIn = parts.expires_in;
if (expiresIn) {
var expiresInMilliSeconds = parseInt(expiresIn, 10) * 1000;
var now = new Date();
var expiresAt = now.getTime() + expiresInMilliSeconds;
_this.store[_this._storage].setItem(_this.clientId + "_expires_at", '' + expiresAt);
}
if (stateParts.length > 1) {
_this.state = stateParts[1];
}
oauthSuccess = true;
}
if (!oauthSuccess) {
return resolve(false);
}
if (!_this.oidc && options.onTokenReceived) {
options.onTokenReceived({ accessToken: accessToken });
}
if (_this.oidc) {
_this.processIdToken(idToken, accessToken).then(function (success) {
if (!success) {
return resolve(false);
}
});
}
if (options.validationHandler) {
var validationParams = { accessToken: accessToken, idToken: idToken };
options
.validationHandler(validationParams)
.then(function () {
_this.callEventIfExists(options);
})
.catch(function (reason) {
console.error('Error validating tokens');
console.error(reason);
});
}
else {
_this.callEventIfExists(options);
}
_this.store[_this._storage].removeItem('oauth_redirect');
_this.store[_this._storage].setItem('oauth_finished', 'true');
_this.location.go(_this.location.path(), '');
return resolve(true);
});
};
OAuthService.prototype.processIdToken = function (idToken, accessToken) {
var _this = this;
return new Promise(function (resolve) {
var tokenParts = idToken.split('.');
var claimsBase64 = _this.padBase64(tokenParts[1]);
var claimsJson = '';
var claims = JSON.parse(claimsJson);
_this.store[_this._storage].getItem(_this.clientId + "_nonce").then(function (savedNonce) {
if (claims.aud !== _this.clientId) {
console.warn('Wrong audience: ' + claims.aud);
return resolve(false);
}
if (_this.issuer && claims.iss !== _this.issuer) {
console.warn('Wrong issuer: ' + claims.iss);
return resolve(false);
}
if (claims.nonce !== savedNonce) {
console.warn('Wrong nonce: ' + claims.nonce);
return resolve(false);
}
if (accessToken && !_this.checkAtHash(accessToken, claims)) {
console.warn('Wrong at_hash');
return resolve(false);
}
var now = Date.now();
var issuedAtMSec = claims.iat * 1000;
var expiresAtMSec = claims.exp * 1000;
var tenMinutesInMsec = 1000 * 60 * 10;
if (issuedAtMSec - tenMinutesInMsec >= now || expiresAtMSec + tenMinutesInMsec <= now) {
console.warn('Token has been expired');
console.warn({
now: now,
issuedAtMSec: issuedAtMSec,
expiresAtMSec: expiresAtMSec,
});
return resolve(false);
}
_this.store[_this._storage].setItem(_this.clientId + "_id_token", idToken);
_this.store[_this._storage].setItem(_this.clientId + "_id_token_claims_obj", claimsJson);
_this.store[_this._storage].setItem(_this.clientId + "_id_token_expires_at", '' + expiresAtMSec);
if (_this.validationHandler) {
_this.validationHandler(idToken);
}
return resolve(true);
});
});
};
OAuthService.prototype.padBase64 = function (base64data) {
while (base64data.length % 4 !== 0) {
base64data += '=';
}
return base64data;
};
OAuthService.prototype.createAndSaveNonce = function () {
var _this = this;
return this.createNonce().then(function (nonce) {
_this.store[_this._storage].setItem(_this.clientId + "_nonce", nonce);
return nonce;
}, function (err) {
return '';
});
};
OAuthService.prototype.createNonce = function () {
var _this = this;
return new Promise(function (resolve, reject) {
if (_this.rngUrl) {
throw new Error('createNonce with rng-web-api has not been implemented so far');
}
else {
var text = '';
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < 40; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
resolve(text);
}
});
};
OAuthService.prototype.getFragment = function () {
var path = this.location.path();
if (location.hash.indexOf('#') === 0 && location.hash.indexOf(path) < 0) {
return this.parseQueryString(location.hash.substr(1));
}
else if (location.search.indexOf('?') === 0) {
return this.parseQueryString(location.search.substr(1));
}
else {
return {};
}
};
OAuthService.prototype.parseQueryString = function (queryString) {
var data = {};
var pairs;
var pair;
var separatorIndex;
var escapedKey;
var escapedValue;
var key;
var value;
if (queryString === null) {
return data;
}
pairs = queryString.split('&');
for (var i = 0; i < pairs.length; i++) {
pair = pairs[i];
separatorIndex = pair.indexOf('=');
if (separatorIndex === -1) {
escapedKey = pair;
escapedValue = null;
}
else {
escapedKey = pair.substr(0, separatorIndex);
escapedValue = pair.substr(separatorIndex + 1);
}
key = decodeURIComponent(escapedKey);
value = decodeURIComponent(escapedValue);
if (key.substr(0, 1) === '/') {
key = key.substr(1);
}
data[key] = value;
}
return data;
};
OAuthService.prototype.checkAtHash = function (accessToken, idClaims) {
if (!accessToken || !idClaims || !idClaims.at_hash) {
return true;
}
var tokenHash = [];
var leftMostHalf = tokenHash.slice(0, (tokenHash.length / 2));
var tokenHashBase64 = '';
var atHash = tokenHashBase64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
var claimsAtHash = idClaims.at_hash.replace(/=/g, '');
if (atHash !== claimsAtHash) {
COMPOSER.log('OAUTH', 'exptected at_hash: ' + atHash, null, 'warn');
COMPOSER.log('OAUTH', 'actual at_hash: ' + claimsAtHash, null, 'warn');
}
return (atHash === claimsAtHash);
};
return OAuthService;
}());
export { OAuthService };
OAuthService.decorators = [
{ type: Injectable },
];
OAuthService.ctorParameters = function () { return [
{ type: Location, },
{ type: DataStoreService, },
]; };
//# sourceMappingURL=oauth2.service.js.map