UNPKG

@sneko/ionic-appauth

Version:

Intergration for OpenId/AppAuth-JS into Ionic V3/4/5

413 lines (412 loc) 19.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AuthService = void 0; var tslib_1 = require("tslib"); var auth_subject_1 = require("./auth-subject"); var auth_action_1 = require("./auth-action"); var user_info_request_handler_1 = require("./user-info-request-handler"); var end_session_request_handler_1 = require("./end-session-request-handler"); var authorization_request_handler_1 = require("./authorization-request-handler"); var auth_browser_1 = require("./auth-browser"); var appauth_1 = require("@openid/appauth"); var end_session_request_1 = require("./end-session-request"); var auth_observer_1 = require("./auth-observer"); var TOKEN_RESPONSE_KEY = "token_response"; var AUTH_EXPIRY_BUFFER = 10 * 60 * -1; // 10 mins in seconds var AuthService = /** @class */ (function () { function AuthService(browser, storage, requestor) { if (browser === void 0) { browser = new auth_browser_1.DefaultBrowser(); } if (storage === void 0) { storage = new appauth_1.LocalStorageBackend(); } if (requestor === void 0) { requestor = new appauth_1.JQueryRequestor(); } this.browser = browser; this.storage = storage; this.requestor = requestor; this._authSubject = new auth_subject_1.AuthSubject(); this._actionHistory = new auth_observer_1.ActionHistoryObserver(); this._session = new auth_observer_1.SessionObserver(); this.tokenHandler = new appauth_1.BaseTokenRequestHandler(requestor); this.userInfoHandler = new user_info_request_handler_1.IonicUserInfoHandler(requestor); this.requestHandler = new authorization_request_handler_1.IonicAuthorizationRequestHandler(browser, storage); this.endSessionHandler = new end_session_request_handler_1.IonicEndSessionHandler(browser); this.setupAuthorizationNotifier(); this.addActionObserver(this._actionHistory); this.addActionObserver(this._session); } Object.defineProperty(AuthService.prototype, "authConfig", { get: function () { if (!this._authConfig) throw new Error("AuthConfig Not Defined"); return this._authConfig; }, set: function (value) { this._authConfig = value; }, enumerable: false, configurable: true }); Object.defineProperty(AuthService.prototype, "configuration", { get: function () { if (!this._configuration) { return appauth_1.AuthorizationServiceConfiguration.fetchFromIssuer(this.authConfig.server_host, this.requestor) .catch(function () { throw new Error("Unable To Obtain Server Configuration"); }); } if (this._configuration != undefined) { return Promise.resolve(this._configuration); } else { throw new Error("Unable To Obtain Server Configuration"); } }, enumerable: false, configurable: true }); Object.defineProperty(AuthService.prototype, "history", { get: function () { return this._actionHistory.history.slice(0); }, enumerable: false, configurable: true }); Object.defineProperty(AuthService.prototype, "session", { get: function () { return this._session.session; }, enumerable: false, configurable: true }); AuthService.prototype.notifyActionListers = function (action) { this._authSubject.notify(action); }; AuthService.prototype.setupAuthorizationNotifier = function () { var _this = this; var notifier = new appauth_1.AuthorizationNotifier(); this.requestHandler.setAuthorizationNotifier(notifier); notifier.setAuthorizationListener(function (request, response, error) { return _this.onAuthorizationNotification(request, response, error); }); }; AuthService.prototype.onAuthorizationNotification = function (request, response, error) { var codeVerifier = (request.internal != undefined && this.authConfig.pkce) ? request.internal.code_verifier : undefined; if (response != null) { this.requestAccessToken(response.code, codeVerifier); } else if (error != null) { throw new Error(error.errorDescription); } else { throw new Error("Unknown Error With Authentication"); } }; AuthService.prototype.internalAuthorizationCallback = function (url) { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: this.browser.closeWindow(); return [4 /*yield*/, this.storage.setItem(authorization_request_handler_1.AUTHORIZATION_RESPONSE_KEY, url)]; case 1: _a.sent(); return [2 /*return*/, this.requestHandler.completeAuthorizationRequestIfPossible()]; } }); }); }; AuthService.prototype.internalEndSessionCallback = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: this.browser.closeWindow(); this._actionHistory.clear(); return [4 /*yield*/, this.storage.removeItem(TOKEN_RESPONSE_KEY)]; case 1: _a.sent(); this.notifyActionListers(auth_action_1.AuthActionBuilder.SignOutSuccess()); return [2 /*return*/]; } }); }); }; AuthService.prototype.performEndSessionRequest = function (state) { return tslib_1.__awaiter(this, void 0, void 0, function () { var requestJson, request, returnedUrl, _a, _b; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: if (!(this.session.token != undefined)) return [3 /*break*/, 3]; requestJson = { postLogoutRedirectURI: this.authConfig.end_session_redirect_url, idTokenHint: this.session.token.idToken || '', state: state || undefined, }; request = new end_session_request_1.EndSessionRequest(requestJson); _b = (_a = this.endSessionHandler).performEndSessionRequest; return [4 /*yield*/, this.configuration]; case 1: return [4 /*yield*/, _b.apply(_a, [_c.sent(), request])]; case 2: returnedUrl = _c.sent(); //callback may come from showWindow or via another method if (returnedUrl != undefined) { this.endSessionCallback(); } return [3 /*break*/, 4]; case 3: //if user has no token they should not be logged in in the first place this.endSessionCallback(); _c.label = 4; case 4: return [2 /*return*/]; } }); }); }; AuthService.prototype.performAuthorizationRequest = function (authExtras, state) { return tslib_1.__awaiter(this, void 0, void 0, function () { var requestJson, request, _a, _b; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: requestJson = { response_type: appauth_1.AuthorizationRequest.RESPONSE_TYPE_CODE, client_id: this.authConfig.client_id, redirect_uri: this.authConfig.redirect_url, scope: this.authConfig.scopes, extras: authExtras, state: state || undefined, }; request = new appauth_1.AuthorizationRequest(requestJson, new appauth_1.DefaultCrypto(), this.authConfig.pkce); if (!this.authConfig.pkce) return [3 /*break*/, 2]; return [4 /*yield*/, request.setupCodeVerifier()]; case 1: _c.sent(); _c.label = 2; case 2: _b = (_a = this.requestHandler).performAuthorizationRequest; return [4 /*yield*/, this.configuration]; case 3: return [2 /*return*/, _b.apply(_a, [_c.sent(), request])]; } }); }); }; AuthService.prototype.requestAccessToken = function (code, codeVerifier) { return tslib_1.__awaiter(this, void 0, void 0, function () { var requestJSON, token, _a, _b; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: requestJSON = { grant_type: appauth_1.GRANT_TYPE_AUTHORIZATION_CODE, code: code, refresh_token: undefined, redirect_uri: this.authConfig.redirect_url, client_id: this.authConfig.client_id, extras: (codeVerifier) ? { "code_verifier": codeVerifier } : {} }; _b = (_a = this.tokenHandler).performTokenRequest; return [4 /*yield*/, this.configuration]; case 1: return [4 /*yield*/, _b.apply(_a, [_c.sent(), new appauth_1.TokenRequest(requestJSON)])]; case 2: token = _c.sent(); return [4 /*yield*/, this.storage.setItem(TOKEN_RESPONSE_KEY, JSON.stringify(token.toJson()))]; case 3: _c.sent(); this.notifyActionListers(auth_action_1.AuthActionBuilder.SignInSuccess(token)); return [2 /*return*/]; } }); }); }; AuthService.prototype.requestTokenRefresh = function () { var _a; return tslib_1.__awaiter(this, void 0, void 0, function () { var requestJSON, token, _b, _c; return tslib_1.__generator(this, function (_d) { switch (_d.label) { case 0: if (!this.session.token) { throw new Error("No Token Defined!"); } requestJSON = { grant_type: appauth_1.GRANT_TYPE_REFRESH_TOKEN, refresh_token: (_a = this.session.token) === null || _a === void 0 ? void 0 : _a.refreshToken, redirect_uri: this.authConfig.redirect_url, client_id: this.authConfig.client_id, }; _c = (_b = this.tokenHandler).performTokenRequest; return [4 /*yield*/, this.configuration]; case 1: return [4 /*yield*/, _c.apply(_b, [_d.sent(), new appauth_1.TokenRequest(requestJSON)])]; case 2: token = _d.sent(); return [4 /*yield*/, this.storage.setItem(TOKEN_RESPONSE_KEY, JSON.stringify(token.toJson()))]; case 3: _d.sent(); this.notifyActionListers(auth_action_1.AuthActionBuilder.RefreshSuccess(token)); return [2 /*return*/]; } }); }); }; AuthService.prototype.internalLoadTokenFromStorage = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var token, tokenResponseString; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.storage.getItem(TOKEN_RESPONSE_KEY)]; case 1: tokenResponseString = _a.sent(); if (tokenResponseString != null) { token = new appauth_1.TokenResponse(JSON.parse(tokenResponseString)); if (token) { return [2 /*return*/, this.notifyActionListers(auth_action_1.AuthActionBuilder.LoadTokenFromStorageSuccess(token))]; } } throw new Error("No Token In Storage"); } }); }); }; AuthService.prototype.internalRequestUserInfo = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var userInfo, _a, _b; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: if (!this.session.token) return [3 /*break*/, 3]; _b = (_a = this.userInfoHandler).performUserInfoRequest; return [4 /*yield*/, this.configuration]; case 1: return [4 /*yield*/, _b.apply(_a, [_c.sent(), this.session.token])]; case 2: userInfo = _c.sent(); this.notifyActionListers(auth_action_1.AuthActionBuilder.LoadUserInfoSuccess(userInfo)); return [3 /*break*/, 4]; case 3: throw new Error("No Token Available"); case 4: return [2 /*return*/]; } }); }); }; AuthService.prototype.loadTokenFromStorage = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.internalLoadTokenFromStorage().catch(function (response) { _this.notifyActionListers(auth_action_1.AuthActionBuilder.LoadTokenFromStorageFailed(response)); })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; AuthService.prototype.signIn = function (authExtras, state) { return tslib_1.__awaiter(this, void 0, void 0, function () { var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.performAuthorizationRequest(authExtras, state).catch(function (response) { _this.notifyActionListers(auth_action_1.AuthActionBuilder.SignInFailed(response)); })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; AuthService.prototype.signOut = function (state) { return tslib_1.__awaiter(this, void 0, void 0, function () { var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.performEndSessionRequest(state).catch(function (response) { _this.notifyActionListers(auth_action_1.AuthActionBuilder.SignOutFailed(response)); })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; AuthService.prototype.refreshToken = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.requestTokenRefresh().catch(function (response) { _this.storage.removeItem(TOKEN_RESPONSE_KEY); _this.notifyActionListers(auth_action_1.AuthActionBuilder.RefreshFailed(response)); })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; AuthService.prototype.loadUserInfo = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.internalRequestUserInfo().catch(function (response) { _this.notifyActionListers(auth_action_1.AuthActionBuilder.LoadUserInfoFailed(response)); })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; AuthService.prototype.authorizationCallback = function (callbackUrl) { var _this = this; this.internalAuthorizationCallback(callbackUrl).catch(function (response) { _this.notifyActionListers(auth_action_1.AuthActionBuilder.SignInFailed(response)); }); }; AuthService.prototype.endSessionCallback = function () { var _this = this; this.internalEndSessionCallback().catch(function (response) { _this.notifyActionListers(auth_action_1.AuthActionBuilder.SignOutFailed(response)); }); }; AuthService.prototype.getValidToken = function (buffer) { if (buffer === void 0) { buffer = AUTH_EXPIRY_BUFFER; } return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!this.session.token) return [3 /*break*/, 3]; if (!!this.session.token.isValid(buffer)) return [3 /*break*/, 2]; return [4 /*yield*/, this.refreshToken()]; case 1: _a.sent(); if (this.session.token) { return [2 /*return*/, this.session.token]; } return [3 /*break*/, 3]; case 2: return [2 /*return*/, this.session.token]; case 3: throw new Error("Unable To Obtain Valid Token"); } }); }); }; AuthService.prototype.addActionListener = function (func) { var observer = auth_observer_1.AuthObserver.Create(func); this.addActionObserver(observer); return observer; }; AuthService.prototype.addActionObserver = function (observer) { if (this._actionHistory.lastAction) { observer.update(this._actionHistory.lastAction); } this._authSubject.attach(observer); }; AuthService.prototype.removeActionObserver = function (observer) { this._authSubject.detach(observer); }; return AuthService; }()); exports.AuthService = AuthService;