UNPKG

ngx-amplify

Version:

An angular library for integration AWS cloud services (cognito, s3)

982 lines 75 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; import { Injectable, Inject } from '@angular/core'; import { NGX_AMPLIFY_CONFIG } from '../common/interfaces/ngx-amplify.config'; import * as AWS from 'aws-sdk'; import { CognitoUserPool, CognitoUser, AuthenticationDetails, CognitoUserAttribute } from 'amazon-cognito-identity-js'; import { BehaviorSubject } from 'rxjs'; import { CognitoException, CognitoProfile, AuthUser } from '../common/common.resource'; import * as i0 from "@angular/core"; import * as i1 from "../common/interfaces/ngx-amplify.config"; var AuthService = /** @class */ (function () { function AuthService(config) { this.config = config; this.resetting = false; this.authState = new BehaviorSubject({ state: 'signedOut', user: null }); this.authState$ = this.authState.asObservable(); this.authUserState = new BehaviorSubject({ state: 'signedOut', user: null }); this.authUserState$ = this.authUserState.asObservable(); this.cognitoUserSub = new BehaviorSubject(this.cognitoUser); this.cognitoUser$ = this.cognitoUserSub.asObservable(); AWS.config.region = this.config.region; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: this.config.identityPoolId }); this.poolData = { UserPoolId: config.userPoolId, ClientId: this.config.appId }; this.userPool = new CognitoUserPool(this.poolData); this.user = AuthUser.Factory(); // this.authUserState.next({ state: 'signedOut', user: this.user }); // this.refreshOrResetCreds(); // this.currentAuthUser = this.currentAuthUser.bind(this); } /** * @private * @param {?} creds * @return {?} */ AuthService.prototype.authDetails = /** * @private * @param {?} creds * @return {?} */ function (creds) { return new AuthenticationDetails({ Username: creds.username, Password: creds.password }); }; /** * @private * @return {?} */ AuthService.prototype.buildCreds = /** * @private * @return {?} */ function () { /** @type {?} */ var self = this; /** @type {?} */ var json = self.buildLogins(self.session.getIdToken().getJwtToken()); return new AWS.CognitoIdentityCredentials(json); }; /** * @private * @param {?} token * @return {?} */ AuthService.prototype.buildLogins = /** * @private * @param {?} token * @return {?} */ function (token) { /** @type {?} */ var self = this; /** @type {?} */ var key = self.config.idpUrl + "/" + self.config.userPoolId; /** @type {?} */ var json = { IdentityPoolId: self.config.identityPoolId, Logins: {} }; json.Logins[key] = token; return json; }; /** * @private * @param {?} error * @param {?} caller * @return {?} */ AuthService.prototype.handleError = /** * @private * @param {?} error * @param {?} caller * @return {?} */ function (error, caller) { /** @type {?} */ var exception = new CognitoException(error); console.error("AWS Cognito Service::handleError callerMethod::" + caller, exception); return exception; }; /** * @private * @return {?} */ AuthService.prototype.getCurrentUser = /** * @private * @return {?} */ function () { return this.userPool.getCurrentUser(); }; /** * @private * @param {?} profile * @return {?} */ AuthService.prototype.getCognitoAttributes = /** * @private * @param {?} profile * @return {?} */ function (profile) { /** @type {?} */ var cognitoAttributes = []; for (var key in profile) { if (!key.includes("password") && !key.includes("confirmPassword")) { /** @type {?} */ var attribute = void 0; if (key.includes("username")) { attribute = new CognitoUserAttribute({ Name: "preferred_username", Value: profile[key] }); } else if (key.endsWith("__c")) { /** @type {?} */ var k = key.substring(0, key.length - 3); /** @type {?} */ var name_1 = "custom:" + k; attribute = new CognitoUserAttribute({ Name: name_1, Value: profile[key] }); } else { attribute = new CognitoUserAttribute({ Name: key, Value: profile[key] }); } cognitoAttributes.push(attribute); } } return cognitoAttributes; }; /** * @private * @param {?} creds * @return {?} */ AuthService.prototype.getCognitoUser = /** * @private * @param {?} creds * @return {?} */ function (creds) { /** @type {?} */ var self = this; /** @type {?} */ var result = new CognitoUser({ Username: creds.username, Pool: self.userPool }); return result; }; /** * @return {?} */ AuthService.prototype.getJwtToken = /** * @return {?} */ function () { /** @type {?} */ var self = this; /** @type {?} */ var user = self.getCurrentUser(); /** @type {?} */ var token; if (user !== null) { token = user.getSignInUserSession().getAccessToken().getJwtToken(); } return token; }; /** * @param {?} attributes * @return {?} */ AuthService.prototype.getCognitoProfile = /** * @param {?} attributes * @return {?} */ function (attributes) { /** @type {?} */ var dynObj = CognitoProfile.Factory(); /** @type {?} */ var values = attributes; ((/** @type {?} */ (values))).forEach((/** * @param {?} attr * @return {?} */ function (attr) { if (attr.Name.startsWith('custom:')) { /** @type {?} */ var attributeName = attr.Name.substring(7); dynObj[attributeName + '__c'] = attr.Value; } else { dynObj[attr.Name] = attr.Value; } })); /** @type {?} */ var result = new CognitoProfile(dynObj); return result; }; /** * @private * @param {?} cognitoUser * @return {?} */ AuthService.prototype.setCognitoProfile = /** * @private * @param {?} cognitoUser * @return {?} */ function (cognitoUser) { /** @type {?} */ var self = this; return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { if (cognitoUser === null) { reject(null); } else { cognitoUser.getUserData((/** * @param {?} err * @param {?} result * @return {?} */ function (err, result) { if (err) { reject(self.handleError(err, 'setCognitoProfile')); } /** @type {?} */ var dynObj = self.getCognitoProfile(result.UserAttributes); if (dynObj.sub) { self.user.identityId = dynObj.sub; } self.user.cognitoProfile = dynObj; resolve(dynObj); })); } })); }; /** * @param {?} attributes * @return {?} */ AuthService.prototype.updateCognitoProfile = /** * @param {?} attributes * @return {?} */ function (attributes) { var _this = this; /** @type {?} */ var self = this; return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var _this = this; return tslib_1.__generator(this, function (_a) { try { self.cognitoUser.updateAttributes(attributes, (/** * @param {?} err * @param {?} result * @return {?} */ function (err, result) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { if (err) { reject(self.handleError(err, 'updateAttributes')); } self.setCognitoProfile(self.cognitoUser) .then((/** * @param {?} profile * @return {?} */ function (profile) { resolve(profile); })) .catch((/** * @param {?} error * @return {?} */ function (error) { reject(self.handleError(error, 'setCognitoProfile')); })); return [2 /*return*/]; }); }); })); } catch (error) { reject(self.handleError(error, 'try/catch updateCognitoProfile')); } return [2 /*return*/]; }); }); })); }; /** * @private * @param {?=} clearCache * @return {?} */ AuthService.prototype.resetCreds = /** * @private * @param {?=} clearCache * @return {?} */ function (clearCache) { if (clearCache === void 0) { clearCache = false; } // console.log('Resetting credentials for unauth access'); this.resetting = true; AWS.config.region = this.config.region; this.cognitoUser = null; this.cognitoUserSub.next(null); this.unauthCreds = this.unauthCreds || new AWS.CognitoIdentityCredentials({ IdentityPoolId: this.config.identityPoolId }); if (clearCache) { this.unauthCreds.clearCachedId(); } this.setCredentials(this.unauthCreds); this.resetting = false; }; /** * @return {?} */ AuthService.prototype.currentAuthUser = /** * @return {?} */ function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var self, user; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: self = this; user = this.userPool.getCurrentUser(); if (!(user !== null)) return [3 /*break*/, 2]; return [4 /*yield*/, this.refreshSession(user)]; case 1: _a.sent(); _a.label = 2; case 2: /* else { self.authState.next({state: 'signedOut', user: user }); self.cognitoUserSub.next(user); self.authUserState.next({ state: 'signedOut', user: self.user }); } */ return [2 /*return*/, self.user]; } }); }); }; /** * @return {?} */ AuthService.prototype.refreshOrResetCreds = /** * @return {?} */ function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var session; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: this.cognitoUser = this.userPool.getCurrentUser(); if (!(this.cognitoUser !== null)) return [3 /*break*/, 3]; if (!(this.cognitoUser.getSignInUserSession() === null)) return [3 /*break*/, 2]; return [4 /*yield*/, this.refreshSession()]; case 1: session = _a.sent(); _a.label = 2; case 2: return [3 /*break*/, 4]; case 3: this.resetCreds(); _a.label = 4; case 4: return [2 /*return*/]; } }); }); }; /** * @private * @param {?=} user * @return {?} */ AuthService.prototype.refreshSession = /** * @private * @param {?=} user * @return {?} */ function (user) { var _this = this; /** @type {?} */ var self = this; if (user === undefined) { user = this.userPool.getCurrentUser(); } self.cognitoUser = user; // Object.assign({},user, self.cognitoUser); // console.log('self.user on refresh', self.cognitoUser); // self.session = user.; if (self.session && self.session.isValid) { // console.log('using the current session already refreshed..'); self.cognitoUser.setSignInUserSession(self.session); return new Promise((/** * @param {?} resolve * @return {?} */ function (resolve) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, self.saveCreds(self.cognitoUser, self.session)]; case 1: _a.sent(); resolve(self.session); return [2 /*return*/]; } }); }); })); } else { /* return self.cognitoUser.getSession(async (err, session: CognitoUserSession) => { if (err) { console.log('Error refreshing user session', err); return err; } console.log(`${new Date()} - Refreshed session for ${self.cognitoUser.getUsername()}. Valid?: `, session.isValid()); self.session = session; self.cognitoUser.setSignInUserSession(session); await self.saveCreds(self.cognitoUser, session); return session; }) */ return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var _this = this; return tslib_1.__generator(this, function (_a) { self.cognitoUser.getSession((/** * @param {?} err * @param {?} session * @return {?} */ function (err, session) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (err) { console.log('Error refreshing user session', err); reject(err); } // console.log(`${new Date()} - Refreshed session for ${self.cognitoUser.getUsername()}. Valid?: `, session.isValid()); self.session = session; self.cognitoUser.setSignInUserSession(session); return [4 /*yield*/, self.saveCreds(self.cognitoUser, session)]; case 1: _a.sent(); resolve(session); return [2 /*return*/]; } }); }); })); return [2 /*return*/]; }); }); })); } }; /** * @param {?=} cognitoUser * @param {?=} session * @return {?} */ AuthService.prototype.saveCreds = /** * @param {?=} cognitoUser * @param {?=} session * @return {?} */ function (cognitoUser, session) { return tslib_1.__awaiter(this, void 0, void 0, function () { var self; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: self = this; if (session) { self.session = session; self.user.authenticated = session.isValid(); self.authState.next({ state: 'signedIn', user: cognitoUser }); } if (!cognitoUser) return [3 /*break*/, 2]; self.cognitoUser = cognitoUser; self.user.cognitoUser = cognitoUser; self.authState.next({ state: 'signedIn', user: cognitoUser }); self.cognitoUserSub.next(cognitoUser); self.user.cognitoProfile = CognitoProfile.Factory(); return [4 /*yield*/, self.setCognitoProfile(cognitoUser)]; case 1: _a.sent(); self.authUserState.next({ state: 'signedIn', user: self.user }); _a.label = 2; case 2: self.setCredentials(self.buildCreds()); return [2 /*return*/, self.user]; } }); }); }; /** * @private * @param {?} creds * @return {?} */ AuthService.prototype.setCredentials = /** * @private * @param {?} creds * @return {?} */ function (creds) { AWS.config.credentials = creds; }; /** * @param {?} creds * @return {?} */ AuthService.prototype.signIn = /** * @param {?} creds * @return {?} */ function (creds) { var _this = this; /** @type {?} */ var self = this; /** @type {?} */ var cognitoUser = self.getCognitoUser(creds); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { try { cognitoUser.authenticateUser(self.authDetails(creds), { onSuccess: (/** * @param {?} session * @return {?} */ function (session) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var user; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: // console.log(`Signed in user ${cognitoUser.getUsername()}. Sessiong valid?: `, session.isValid()); return [4 /*yield*/, self.saveCreds(cognitoUser, session)]; case 1: user = _a.sent(); resolve(user); return [2 /*return*/]; } }); }); }), onFailure: (/** * @param {?} err * @return {?} */ function (err) { reject(self.handleError(err, 'signIn')); }), newPasswordRequired: (/** * @param {?} userAttributes * @param {?} requiredAttributes * @return {?} */ function (userAttributes, requiredAttributes) { cognitoUser.completeNewPasswordChallenge(creds.password, requiredAttributes, { onSuccess: (/** * @param {?} session * @return {?} */ function (session) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var aws_creds, user; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: aws_creds = new AWS.CognitoIdentityCredentials(self.buildLogins(session.getIdToken().getJwtToken())); return [4 /*yield*/, self.saveCreds(cognitoUser, session)]; case 1: user = _a.sent(); resolve(user); return [2 /*return*/]; } }); }); }), onFailure: (/** * @param {?} err * @return {?} */ function (err) { reject(self.handleError(err, 'completeNewPasswordChallenge')); }) }); }), mfaRequired: (/** * @param {?} challengeName * @param {?} challengeParameters * @return {?} */ function (challengeName, challengeParameters) { }), customChallenge: (/** * @param {?} challengeParameters * @return {?} */ function (challengeParameters) { }), }); } catch (error) { reject(error); } })); }; /** * @param {?} creds * @return {?} */ AuthService.prototype.signUp = /** * @param {?} creds * @return {?} */ function (creds) { /** @type {?} */ var self = this; // creds.member_since__c = moment().year().toString(); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { try { /** @type {?} */ var attributes = []; attributes = self.getCognitoAttributes(creds); return self.userPool.signUp(creds.username, creds.password, attributes, null, (/** * @param {?} err * @param {?} result * @return {?} */ function (err, result) { if (err) { reject(self.handleError(err, 'signUp')); } else { // console.log('signUp registration successful', result); resolve(result); } })); } catch (error) { reject(self.handleError(error, 'try/catch signUp')); } })); }; /** * @param {?} username * @param {?} code * @return {?} */ AuthService.prototype.confirmSignUp = /** * @param {?} username * @param {?} code * @return {?} */ function (username, code) { var _this = this; /** @type {?} */ var self = this; /** @type {?} */ var userData = { Username: username, Pool: self.userPool }; /** @type {?} */ var cognitoUser = new CognitoUser(userData); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { try { cognitoUser.confirmRegistration(code, true, ((/** * @param {?} err * @param {?} result * @return {?} */ function (err, result) { if (err) { reject(self.handleError(err, 'confirmRegistration')); } else { // console.log('confirm registration successful', result); resolve(result); } }))); } catch (error) { reject(_this.handleError(error, 'try/catch confirm signUp')); } })); }; /** * @param {?} username * @param {?} verificationCode * @param {?} password * @return {?} */ AuthService.prototype.confirmPassword = /** * @param {?} username * @param {?} verificationCode * @param {?} password * @return {?} */ function (username, verificationCode, password) { /** @type {?} */ var self = this; /** @type {?} */ var userData = { Username: username, Pool: this.userPool }; /** @type {?} */ var cognitoUser = new CognitoUser(userData); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { try { cognitoUser.confirmPassword(verificationCode, password, { onFailure: (/** * @param {?} err * @return {?} */ function (err) { reject(self.handleError(err, 'confirmPassword')); }), onSuccess: (/** * @return {?} */ function () { resolve('Confirm Password SUCCESS'); }) }); } catch (error) { reject(self.handleError(error, 'try/catch confirmPassword')); } })); }; /** * @param {?} username * @return {?} */ AuthService.prototype.forgotPassword = /** * @param {?} username * @return {?} */ function (username) { /** @type {?} */ var self = this; /** @type {?} */ var userData = { Username: username, Pool: this.userPool }; /** @type {?} */ var cognitoUser = new CognitoUser(userData); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { try { cognitoUser.forgotPassword({ onFailure: (/** * @param {?} err * @return {?} */ function (err) { reject(self.handleError(err, 'forgotPassword')); }), onSuccess: (/** * @return {?} */ function () { resolve('Verification Code Sent'); }), inputVerificationCode: (/** * @return {?} */ function () { resolve('Verification Code Sent'); }) }); } catch (err) { reject(self.handleError(err, 'try/catch forgotPassword')); } })); }; /** * @param {?} username * @return {?} */ AuthService.prototype.resendConfirmationCode = /** * @param {?} username * @return {?} */ function (username) { /** @type {?} */ var self = this; /** @type {?} */ var userData = { Username: username, Pool: this.userPool }; /** @type {?} */ var cognitoUser = new CognitoUser(userData); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { try { cognitoUser.resendConfirmationCode((/** * @param {?} err * @param {?} result * @return {?} */ function (err, result) { if (err) { // let exception: ICognitoException = self.handleError(err,'resendConfirmationCode'); // console.log('error occurred while confirming registration code', exception); reject(self.handleError(err, 'resendConfirmationCode')); } else { // console.log('confirm registration successful', result); resolve(result); } })); } catch (error) { // let exception: ICognitoException = self.handleError(error,'try/catch resendConfirmationCode');//new CognitoException(error); reject(self.handleError(error, 'try/catch resendConfirmationCode')); } })); }; /** * @return {?} */ AuthService.prototype.signOut = /** * @return {?} */ function () { /** @type {?} */ var self = this; if (self.cognitoUser) { /** @type {?} */ var username = self.cognitoUser.getUsername(); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ function (resolve, reject) { try { self.cognitoUser.signOut(); self.cognitoUserSub.next(null); self.authState.next({ state: 'signedOut', user: null }); self.resetCreds(true); self.user = AuthUser.Factory(); self.authUserState.next({ state: 'signedOut', user: null }); resolve('signOut successful'); } catch (error) { reject(self.handleError(error, 'try/catch signOut')); } })); } }; AuthService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ AuthService.ctorParameters = function () { return [ { type: undefined, decorators: [{ type: Inject, args: [NGX_AMPLIFY_CONFIG,] }] } ]; }; /** @nocollapse */ AuthService.ngInjectableDef = i0.ɵɵdefineInjectable({ factory: function AuthService_Factory() { return new AuthService(i0.ɵɵinject(i1.NGX_AMPLIFY_CONFIG)); }, token: AuthService, providedIn: "root" }); return AuthService; }()); export { AuthService }; if (false) { /** * @type {?} * @private */ AuthService.prototype.poolData; /** * @type {?} * @private */ AuthService.prototype.session; /** * @type {?} * @private */ AuthService.prototype.userPool; /** * @type {?} * @private */ AuthService.prototype.unauthCreds; /** * @type {?} * @private */ AuthService.prototype.resetting; /** * @type {?} * @private */ AuthService.prototype.authState; /** @type {?} */ AuthService.prototype.authState$; /** * @type {?} * @private */ AuthService.prototype.authUserState; /** @type {?} */ AuthService.prototype.authUserState$; /** @type {?} */ AuthService.prototype.cognitoUser; /** * @type {?} * @private */ AuthService.prototype.cognitoUserSub; /** @type {?} */ AuthService.prototype.cognitoUser$; /** @type {?} */ AuthService.prototype.user; /** * @type {?} * @private */ AuthService.prototype.config; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LWFtcGxpZnkvIiwic291cmNlcyI6WyJsaWIvc2VydmljZXMvYXV0aC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFvQixrQkFBa0IsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQy9GLE9BQU8sS0FBSyxHQUFHLE1BQU0sU0FBUyxDQUFDO0FBQy9CLE9BQU8sRUFBd0IsZUFBZSxFQUFFLFdBQVcsRUFBRSxxQkFBcUIsRUFBc0Isb0JBQW9CLEVBQXNELE1BQU0sNEJBQTRCLENBQUM7QUFDck4sT0FBTyxFQUFFLGVBQWUsRUFBdUIsTUFBTSxNQUFNLENBQUM7QUFDNUQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQzs7O0FBR3ZGO0lBc0JFLHFCQUNzQyxNQUF3QjtRQUF4QixXQUFNLEdBQU4sTUFBTSxDQUFrQjtRQWZ0RCxjQUFTLEdBQVksS0FBSyxDQUFDO1FBRTNCLGNBQVMsR0FBZ0MsSUFBSSxlQUFlLENBQUMsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3pHLGVBQVUsR0FBMkIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUUzRCxrQkFBYSxHQUFvQyxJQUFJLGVBQWUsQ0FBQyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDakgsbUJBQWMsR0FBK0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUl2RSxtQkFBYyxHQUFpQyxJQUFJLGVBQWUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDN0YsaUJBQVksR0FBNEIsSUFB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