1 | import { Subject } from 'rxjs';
|
2 | import { Amplify, Logger, Hub } from '@aws-amplify/core';
|
3 | import { AuthState } from './auth.state';
|
4 | import * as _ from 'lodash';
|
5 |
|
6 | const logger = new Logger('AuthDecorator');
|
7 |
|
8 | function check(authState: Subject<AuthState>, Auth) {
|
9 |
|
10 | Auth.currentAuthenticatedUser()
|
11 | .then(user => {
|
12 | logger.debug('has authenticated user', user);
|
13 | authState.next({ state: 'signedIn', user });
|
14 | })
|
15 | .catch(err => {
|
16 | logger.debug('no authenticated user', err);
|
17 | authState.next({ state: 'signedOut', user: null });
|
18 | });
|
19 | }
|
20 |
|
21 | function listen(authState: Subject<AuthState>) {
|
22 | const config = Amplify.configure(null);
|
23 | if (_.has(config, 'Auth.oauth')) {
|
24 | Hub.listen(
|
25 | 'auth',
|
26 | {
|
27 | onHubCapsule: capsule => {
|
28 | const { channel, payload } = capsule;
|
29 | if (channel === 'auth') {
|
30 | const { username } = payload.data;
|
31 | logger.debug('authentication oauth event', payload);
|
32 | authState.next({ state: payload.event, user: { username } });
|
33 | }
|
34 | },
|
35 | },
|
36 | 'angularAuthListener'
|
37 | );
|
38 | }
|
39 | }
|
40 |
|
41 | function decorateSignIn(authState: Subject<AuthState>, Auth) {
|
42 | const _signIn = Auth.signIn;
|
43 | Auth.signIn = (username: string, password: string): Promise<any> => {
|
44 | return _signIn
|
45 | .call(Auth, username, password)
|
46 | .then(user => {
|
47 | logger.debug('signIn success');
|
48 | if (!user.challengeName) {
|
49 | authState.next({ state: 'signedIn', user });
|
50 | return user;
|
51 | }
|
52 |
|
53 | logger.debug('signIn challenge: ' + user.challengeName);
|
54 | if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
|
55 | authState.next({ state: 'requireNewPassword', user });
|
56 | } else if (user.challengeName === 'MFA_SETUP') {
|
57 | authState.next({ state: 'setupMFA', user });
|
58 | } else if (
|
59 | user.challengeName === 'SMS_MFA' ||
|
60 | user.challengeName === 'SOFTWARE_TOKEN_MFA'
|
61 | ) {
|
62 | authState.next({ state: 'confirmSignIn', user });
|
63 | } else {
|
64 | logger.debug(
|
65 | 'warning: unhandled challengeName ' + user.challengeName
|
66 | );
|
67 | }
|
68 | return user;
|
69 | })
|
70 | .catch(err => {
|
71 | logger.debug('signIn error', err);
|
72 | throw err;
|
73 | });
|
74 | };
|
75 | }
|
76 |
|
77 | function decorateSignOut(authState: Subject<AuthState>, Auth) {
|
78 | const _signOut = Auth.signOut;
|
79 | Auth.signOut = (opts: { global: boolean } | undefined): Promise<any> => {
|
80 | return _signOut
|
81 | .call(Auth, opts)
|
82 | .then(data => {
|
83 | logger.debug('signOut success');
|
84 | authState.next({ state: 'signedOut', user: null });
|
85 | return data;
|
86 | })
|
87 | .catch(err => {
|
88 | logger.debug('signOut error', err);
|
89 | throw err;
|
90 | });
|
91 | };
|
92 | }
|
93 |
|
94 | function decorateSignUp(authState: Subject<AuthState>, Auth) {
|
95 | const _signUp = Auth.signUp;
|
96 | Auth.signUp = (
|
97 | username: string,
|
98 | password: string,
|
99 | email: string,
|
100 | phone_number: string
|
101 | ): Promise<any> => {
|
102 | return _signUp
|
103 | .call(Auth, username, password, email, phone_number)
|
104 | .then(data => {
|
105 | logger.debug('signUp success');
|
106 | authState.next({ state: 'confirmSignUp', user: { username } });
|
107 | return data;
|
108 | })
|
109 | .catch(err => {
|
110 | logger.debug('signUp error', err);
|
111 | throw err;
|
112 | });
|
113 | };
|
114 | }
|
115 |
|
116 | function decorateConfirmSignUp(authState: Subject<AuthState>, Auth) {
|
117 | const _confirmSignUp = Auth.confirmSignUp;
|
118 | Auth.confirmSignUp = (username: string, code: string): Promise<any> => {
|
119 | return _confirmSignUp
|
120 | .call(Auth, username, code)
|
121 | .then(data => {
|
122 | logger.debug('confirmSignUp success');
|
123 | authState.next({ state: 'signIn', user: { username } });
|
124 | return data;
|
125 | })
|
126 | .catch(err => {
|
127 | logger.debug('confirmSignUp error', err);
|
128 | throw err;
|
129 | });
|
130 | };
|
131 | }
|
132 |
|
133 | export function authDecorator(authState: Subject<AuthState>, authModule) {
|
134 | check(authState, authModule);
|
135 | listen(authState);
|
136 | decorateSignIn(authState, authModule);
|
137 | decorateSignOut(authState, authModule);
|
138 | decorateSignUp(authState, authModule);
|
139 | decorateConfirmSignUp(authState, authModule);
|
140 | }
|