@aws-amplify/auth 5.6.3 → 5.6.4-unstable.bdaee91.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Auth.d.ts +81 -4
- package/lib/Auth.js +2252 -45
- package/lib/Auth.js.map +1 -1
- package/lib/OAuth/OAuth.d.ts +1 -1
- package/lib/OAuth/OAuth.js +9 -5
- package/lib/OAuth/OAuth.js.map +1 -1
- package/lib-esm/Auth.d.ts +81 -4
- package/lib-esm/Auth.js +2254 -47
- package/lib-esm/Auth.js.map +1 -1
- package/lib-esm/OAuth/OAuth.d.ts +1 -1
- package/lib-esm/OAuth/OAuth.js +10 -6
- package/lib-esm/OAuth/OAuth.js.map +1 -1
- package/package.json +6 -7
- package/src/Auth.ts +2410 -76
- package/src/OAuth/OAuth.ts +9 -10
- package/internals/package.json +0 -8
- package/lib/internals/InternalAuth.d.ts +0 -353
- package/lib/internals/InternalAuth.js +0 -2630
- package/lib/internals/InternalAuth.js.map +0 -1
- package/lib/internals/index.d.ts +0 -1
- package/lib/internals/index.js +0 -7
- package/lib/internals/index.js.map +0 -1
- package/lib/utils.d.ts +0 -3
- package/lib/utils.js +0 -15
- package/lib/utils.js.map +0 -1
- package/lib-esm/internals/InternalAuth.d.ts +0 -353
- package/lib-esm/internals/InternalAuth.js +0 -2628
- package/lib-esm/internals/InternalAuth.js.map +0 -1
- package/lib-esm/internals/index.d.ts +0 -1
- package/lib-esm/internals/index.js +0 -4
- package/lib-esm/internals/index.js.map +0 -1
- package/lib-esm/utils.d.ts +0 -3
- package/lib-esm/utils.js +0 -11
- package/lib-esm/utils.js.map +0 -1
- package/src/internals/InternalAuth.ts +0 -3270
- package/src/internals/index.ts +0 -3
- package/src/utils.ts +0 -27
|
@@ -1,3270 +0,0 @@
|
|
|
1
|
-
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
AuthOptions,
|
|
6
|
-
FederatedResponse,
|
|
7
|
-
SignUpParams,
|
|
8
|
-
FederatedUser,
|
|
9
|
-
ConfirmSignUpOptions,
|
|
10
|
-
SignOutOpts,
|
|
11
|
-
CurrentUserOpts,
|
|
12
|
-
GetPreferredMFAOpts,
|
|
13
|
-
SignInOpts,
|
|
14
|
-
isUsernamePasswordOpts,
|
|
15
|
-
isCognitoHostedOpts,
|
|
16
|
-
isFederatedSignInOptions,
|
|
17
|
-
isFederatedSignInOptionsCustom,
|
|
18
|
-
hasCustomState,
|
|
19
|
-
FederatedSignInOptionsCustom,
|
|
20
|
-
LegacyProvider,
|
|
21
|
-
FederatedSignInOptions,
|
|
22
|
-
AwsCognitoOAuthOpts,
|
|
23
|
-
ClientMetaData,
|
|
24
|
-
} from '../types';
|
|
25
|
-
|
|
26
|
-
import {
|
|
27
|
-
Amplify,
|
|
28
|
-
AuthAction,
|
|
29
|
-
ConsoleLogger as Logger,
|
|
30
|
-
Credentials,
|
|
31
|
-
CustomUserAgentDetails,
|
|
32
|
-
getAmplifyUserAgent,
|
|
33
|
-
Hub,
|
|
34
|
-
StorageHelper,
|
|
35
|
-
ICredentials,
|
|
36
|
-
Platform,
|
|
37
|
-
browserOrNode,
|
|
38
|
-
parseAWSExports,
|
|
39
|
-
UniversalStorage,
|
|
40
|
-
urlSafeDecode,
|
|
41
|
-
HubCallback,
|
|
42
|
-
} from '@aws-amplify/core';
|
|
43
|
-
import {
|
|
44
|
-
CookieStorage,
|
|
45
|
-
AuthenticationDetails,
|
|
46
|
-
ICognitoUserPoolData,
|
|
47
|
-
ICognitoUserData,
|
|
48
|
-
ISignUpResult,
|
|
49
|
-
CognitoUser,
|
|
50
|
-
MFAOption,
|
|
51
|
-
CognitoUserSession,
|
|
52
|
-
IAuthenticationCallback,
|
|
53
|
-
ICognitoUserAttributeData,
|
|
54
|
-
CognitoUserAttribute,
|
|
55
|
-
CognitoIdToken,
|
|
56
|
-
CognitoRefreshToken,
|
|
57
|
-
CognitoAccessToken,
|
|
58
|
-
NodeCallback,
|
|
59
|
-
CodeDeliveryDetails,
|
|
60
|
-
} from 'amazon-cognito-identity-js';
|
|
61
|
-
import {
|
|
62
|
-
addAuthCategoryToCognitoUserAgent,
|
|
63
|
-
addFrameworkToCognitoUserAgent,
|
|
64
|
-
InternalCognitoUser,
|
|
65
|
-
InternalCognitoUserPool,
|
|
66
|
-
} from 'amazon-cognito-identity-js/internals';
|
|
67
|
-
|
|
68
|
-
import { parse } from 'url';
|
|
69
|
-
import OAuth from '../OAuth/OAuth';
|
|
70
|
-
import { default as urlListener } from '../urlListener';
|
|
71
|
-
import { AuthError, NoUserPoolError } from '../Errors';
|
|
72
|
-
import {
|
|
73
|
-
AuthErrorTypes,
|
|
74
|
-
AutoSignInOptions,
|
|
75
|
-
CognitoHostedUIIdentityProvider,
|
|
76
|
-
IAuthDevice,
|
|
77
|
-
} from '../types/Auth';
|
|
78
|
-
import { getAuthUserAgentDetails, getAuthUserAgentValue } from '../utils';
|
|
79
|
-
|
|
80
|
-
const logger = new Logger('AuthClass');
|
|
81
|
-
const USER_ADMIN_SCOPE = 'aws.cognito.signin.user.admin';
|
|
82
|
-
|
|
83
|
-
// 10 sec, following this guide https://www.nngroup.com/articles/response-times-3-important-limits/
|
|
84
|
-
const OAUTH_FLOW_MS_TIMEOUT = 10 * 1000;
|
|
85
|
-
|
|
86
|
-
const AMPLIFY_SYMBOL = (
|
|
87
|
-
typeof Symbol !== 'undefined' && typeof Symbol.for === 'function'
|
|
88
|
-
? Symbol.for('amplify_default')
|
|
89
|
-
: '@@amplify_default'
|
|
90
|
-
) as Symbol;
|
|
91
|
-
|
|
92
|
-
const dispatchAuthEvent = (event: string, data: any, message: string) => {
|
|
93
|
-
Hub.dispatch('auth', { event, data, message }, 'Auth', AMPLIFY_SYMBOL);
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
// Cognito Documentation for max device
|
|
97
|
-
// tslint:disable-next-line:max-line-length
|
|
98
|
-
// https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListDevices.html#API_ListDevices_RequestSyntax
|
|
99
|
-
const MAX_DEVICES = 60;
|
|
100
|
-
|
|
101
|
-
const MAX_AUTOSIGNIN_POLLING_MS = 3 * 60 * 1000;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Provide authentication steps
|
|
105
|
-
*/
|
|
106
|
-
export class InternalAuthClass {
|
|
107
|
-
private _config: AuthOptions;
|
|
108
|
-
private userPool: InternalCognitoUserPool = null;
|
|
109
|
-
private user: any = null;
|
|
110
|
-
private _oAuthHandler: OAuth;
|
|
111
|
-
private _storage;
|
|
112
|
-
private _storageSync;
|
|
113
|
-
private oAuthFlowInProgress: boolean = false;
|
|
114
|
-
private pendingSignIn: ReturnType<
|
|
115
|
-
InternalAuthClass['signInWithPassword']
|
|
116
|
-
> | null;
|
|
117
|
-
private autoSignInInitiated: boolean = false;
|
|
118
|
-
private inflightSessionPromise: Promise<CognitoUserSession> | null = null;
|
|
119
|
-
private inflightSessionPromiseCounter: number = 0;
|
|
120
|
-
Credentials = Credentials;
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Initialize Auth with AWS configurations
|
|
124
|
-
* @param {Object} config - Configuration of the Auth
|
|
125
|
-
*/
|
|
126
|
-
constructor(config: AuthOptions) {
|
|
127
|
-
this.configure(config);
|
|
128
|
-
this.currentCredentials = this.currentCredentials.bind(this);
|
|
129
|
-
this.currentUserCredentials = this.currentUserCredentials.bind(this);
|
|
130
|
-
|
|
131
|
-
Hub.listen('auth', ({ payload }) => {
|
|
132
|
-
const { event } = payload;
|
|
133
|
-
switch (event) {
|
|
134
|
-
case 'verify':
|
|
135
|
-
case 'signIn':
|
|
136
|
-
this._storage.setItem('amplify-signin-with-hostedUI', 'false');
|
|
137
|
-
break;
|
|
138
|
-
case 'signOut':
|
|
139
|
-
this._storage.removeItem('amplify-signin-with-hostedUI');
|
|
140
|
-
break;
|
|
141
|
-
case 'cognitoHostedUI':
|
|
142
|
-
this._storage.setItem('amplify-signin-with-hostedUI', 'true');
|
|
143
|
-
break;
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
addAuthCategoryToCognitoUserAgent();
|
|
148
|
-
addFrameworkToCognitoUserAgent(Platform.framework);
|
|
149
|
-
Platform.observeFrameworkChanges(() => {
|
|
150
|
-
addFrameworkToCognitoUserAgent(Platform.framework);
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
public getModuleName() {
|
|
155
|
-
return 'InternalAuth';
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
configure(config?) {
|
|
159
|
-
if (!config) return this._config || {};
|
|
160
|
-
logger.debug('configure Auth');
|
|
161
|
-
const conf = Object.assign(
|
|
162
|
-
{},
|
|
163
|
-
this._config,
|
|
164
|
-
parseAWSExports(config).Auth,
|
|
165
|
-
config
|
|
166
|
-
);
|
|
167
|
-
this._config = conf;
|
|
168
|
-
const {
|
|
169
|
-
userPoolId,
|
|
170
|
-
userPoolWebClientId,
|
|
171
|
-
cookieStorage,
|
|
172
|
-
oauth,
|
|
173
|
-
region,
|
|
174
|
-
identityPoolId,
|
|
175
|
-
mandatorySignIn,
|
|
176
|
-
refreshHandlers,
|
|
177
|
-
identityPoolRegion,
|
|
178
|
-
clientMetadata,
|
|
179
|
-
endpoint,
|
|
180
|
-
storage,
|
|
181
|
-
} = this._config;
|
|
182
|
-
|
|
183
|
-
if (!storage) {
|
|
184
|
-
// backward compatability
|
|
185
|
-
if (cookieStorage) this._storage = new CookieStorage(cookieStorage);
|
|
186
|
-
else {
|
|
187
|
-
this._storage = config.ssr
|
|
188
|
-
? new UniversalStorage()
|
|
189
|
-
: new StorageHelper().getStorage();
|
|
190
|
-
}
|
|
191
|
-
} else {
|
|
192
|
-
if (!this._isValidAuthStorage(storage)) {
|
|
193
|
-
logger.error('The storage in the Auth config is not valid!');
|
|
194
|
-
throw new Error('Empty storage object');
|
|
195
|
-
}
|
|
196
|
-
this._storage = storage;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
this._storageSync = Promise.resolve();
|
|
200
|
-
if (typeof this._storage['sync'] === 'function') {
|
|
201
|
-
this._storageSync = this._storage['sync']();
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (userPoolId) {
|
|
205
|
-
const userPoolData: ICognitoUserPoolData = {
|
|
206
|
-
UserPoolId: userPoolId,
|
|
207
|
-
ClientId: userPoolWebClientId,
|
|
208
|
-
endpoint,
|
|
209
|
-
};
|
|
210
|
-
userPoolData.Storage = this._storage;
|
|
211
|
-
|
|
212
|
-
this.userPool = new InternalCognitoUserPool(
|
|
213
|
-
userPoolData,
|
|
214
|
-
this.wrapRefreshSessionCallback
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
this.Credentials.configure({
|
|
219
|
-
mandatorySignIn,
|
|
220
|
-
region,
|
|
221
|
-
userPoolId,
|
|
222
|
-
identityPoolId,
|
|
223
|
-
refreshHandlers,
|
|
224
|
-
storage: this._storage,
|
|
225
|
-
identityPoolRegion,
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
// initialize cognitoauth client if hosted ui options provided
|
|
229
|
-
// to keep backward compatibility:
|
|
230
|
-
const cognitoHostedUIConfig = oauth
|
|
231
|
-
? isCognitoHostedOpts(this._config.oauth)
|
|
232
|
-
? oauth
|
|
233
|
-
: (<any>oauth).awsCognito
|
|
234
|
-
: undefined;
|
|
235
|
-
|
|
236
|
-
if (cognitoHostedUIConfig) {
|
|
237
|
-
const cognitoAuthParams = Object.assign(
|
|
238
|
-
{
|
|
239
|
-
cognitoClientId: userPoolWebClientId,
|
|
240
|
-
UserPoolId: userPoolId,
|
|
241
|
-
domain: cognitoHostedUIConfig['domain'],
|
|
242
|
-
scopes: cognitoHostedUIConfig['scope'],
|
|
243
|
-
redirectSignIn: cognitoHostedUIConfig['redirectSignIn'],
|
|
244
|
-
redirectSignOut: cognitoHostedUIConfig['redirectSignOut'],
|
|
245
|
-
responseType: cognitoHostedUIConfig['responseType'],
|
|
246
|
-
Storage: this._storage,
|
|
247
|
-
urlOpener: cognitoHostedUIConfig['urlOpener'],
|
|
248
|
-
clientMetadata,
|
|
249
|
-
},
|
|
250
|
-
cognitoHostedUIConfig['options']
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
this._oAuthHandler = new OAuth({
|
|
254
|
-
scopes: cognitoAuthParams.scopes,
|
|
255
|
-
config: cognitoAuthParams,
|
|
256
|
-
cognitoClientId: cognitoAuthParams.cognitoClientId,
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
// **NOTE** - Remove this in a future major release as it is a breaking change
|
|
260
|
-
// Prevents _handleAuthResponse from being called multiple times in Expo
|
|
261
|
-
// See https://github.com/aws-amplify/amplify-js/issues/4388
|
|
262
|
-
const usedResponseUrls = {};
|
|
263
|
-
// Only register urlListener once
|
|
264
|
-
if (this.getModuleName() === 'Auth') {
|
|
265
|
-
urlListener(({ url }) => {
|
|
266
|
-
if (usedResponseUrls[url]) {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
usedResponseUrls[url] = true;
|
|
271
|
-
this._handleAuthResponse(url);
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
dispatchAuthEvent(
|
|
277
|
-
'configured',
|
|
278
|
-
null,
|
|
279
|
-
`The Auth category has been configured successfully`
|
|
280
|
-
);
|
|
281
|
-
|
|
282
|
-
if (
|
|
283
|
-
!this.autoSignInInitiated &&
|
|
284
|
-
typeof this._storage['getItem'] === 'function'
|
|
285
|
-
) {
|
|
286
|
-
const pollingInitiated = this.isTrueStorageValue(
|
|
287
|
-
'amplify-polling-started'
|
|
288
|
-
);
|
|
289
|
-
if (pollingInitiated) {
|
|
290
|
-
dispatchAuthEvent(
|
|
291
|
-
'autoSignIn_failure',
|
|
292
|
-
null,
|
|
293
|
-
AuthErrorTypes.AutoSignInError
|
|
294
|
-
);
|
|
295
|
-
this._storage.removeItem('amplify-auto-sign-in');
|
|
296
|
-
}
|
|
297
|
-
this._storage.removeItem('amplify-polling-started');
|
|
298
|
-
}
|
|
299
|
-
return this._config;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
wrapRefreshSessionCallback = (callback: NodeCallback.Any) => {
|
|
303
|
-
const wrapped: NodeCallback.Any = (error, data) => {
|
|
304
|
-
if (data) {
|
|
305
|
-
dispatchAuthEvent('tokenRefresh', undefined, `New token retrieved`);
|
|
306
|
-
} else {
|
|
307
|
-
dispatchAuthEvent(
|
|
308
|
-
'tokenRefresh_failure',
|
|
309
|
-
error,
|
|
310
|
-
`Failed to retrieve new token`
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
return callback(error, data);
|
|
314
|
-
};
|
|
315
|
-
return wrapped;
|
|
316
|
-
} // prettier-ignore
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Sign up with username, password and other attributes like phone, email
|
|
320
|
-
* @param {String | object} params - The user attributes used for signin
|
|
321
|
-
* @param {String[]} restOfAttrs - for the backward compatability
|
|
322
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
323
|
-
* @return - A promise resolves callback data if success
|
|
324
|
-
*/
|
|
325
|
-
public signUp(
|
|
326
|
-
params: string | SignUpParams,
|
|
327
|
-
...restOfAttrs: any
|
|
328
|
-
): Promise<ISignUpResult>;
|
|
329
|
-
public signUp(
|
|
330
|
-
params: string | SignUpParams,
|
|
331
|
-
restOfAttrs?: string[],
|
|
332
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
333
|
-
): Promise<ISignUpResult> {
|
|
334
|
-
if (!this.userPool) {
|
|
335
|
-
return this.rejectNoUserPool();
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
let username: string = null;
|
|
339
|
-
let password: string = null;
|
|
340
|
-
const attributes: CognitoUserAttribute[] = [];
|
|
341
|
-
let validationData: CognitoUserAttribute[] = null;
|
|
342
|
-
let clientMetadata;
|
|
343
|
-
let autoSignIn: AutoSignInOptions = { enabled: false };
|
|
344
|
-
let autoSignInValidationData = {};
|
|
345
|
-
let autoSignInClientMetaData: ClientMetaData = {};
|
|
346
|
-
|
|
347
|
-
if (params && typeof params === 'string') {
|
|
348
|
-
username = params;
|
|
349
|
-
password = restOfAttrs ? restOfAttrs[0] : null;
|
|
350
|
-
const email: string = restOfAttrs ? restOfAttrs[1] : null;
|
|
351
|
-
const phone_number: string = restOfAttrs ? restOfAttrs[2] : null;
|
|
352
|
-
|
|
353
|
-
if (email)
|
|
354
|
-
attributes.push(
|
|
355
|
-
new CognitoUserAttribute({ Name: 'email', Value: email })
|
|
356
|
-
);
|
|
357
|
-
|
|
358
|
-
if (phone_number)
|
|
359
|
-
attributes.push(
|
|
360
|
-
new CognitoUserAttribute({
|
|
361
|
-
Name: 'phone_number',
|
|
362
|
-
Value: phone_number,
|
|
363
|
-
})
|
|
364
|
-
);
|
|
365
|
-
} else if (params && typeof params === 'object') {
|
|
366
|
-
username = params['username'];
|
|
367
|
-
password = params['password'];
|
|
368
|
-
|
|
369
|
-
if (params && params.clientMetadata) {
|
|
370
|
-
clientMetadata = params.clientMetadata;
|
|
371
|
-
} else if (this._config.clientMetadata) {
|
|
372
|
-
clientMetadata = this._config.clientMetadata;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
const attrs = params['attributes'];
|
|
376
|
-
if (attrs) {
|
|
377
|
-
Object.keys(attrs).map(key => {
|
|
378
|
-
attributes.push(
|
|
379
|
-
new CognitoUserAttribute({ Name: key, Value: attrs[key] })
|
|
380
|
-
);
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const validationDataObject = params['validationData'];
|
|
385
|
-
if (validationDataObject) {
|
|
386
|
-
validationData = [];
|
|
387
|
-
Object.keys(validationDataObject).map(key => {
|
|
388
|
-
validationData.push(
|
|
389
|
-
new CognitoUserAttribute({
|
|
390
|
-
Name: key,
|
|
391
|
-
Value: validationDataObject[key],
|
|
392
|
-
})
|
|
393
|
-
);
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
autoSignIn = params.autoSignIn ?? { enabled: false };
|
|
398
|
-
if (autoSignIn.enabled) {
|
|
399
|
-
this._storage.setItem('amplify-auto-sign-in', 'true');
|
|
400
|
-
autoSignInValidationData = autoSignIn.validationData ?? {};
|
|
401
|
-
autoSignInClientMetaData = autoSignIn.clientMetaData ?? {};
|
|
402
|
-
}
|
|
403
|
-
} else {
|
|
404
|
-
return this.rejectAuthError(AuthErrorTypes.SignUpError);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
if (!username) {
|
|
408
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyUsername);
|
|
409
|
-
}
|
|
410
|
-
if (!password) {
|
|
411
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyPassword);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
logger.debug('signUp attrs:', attributes);
|
|
415
|
-
logger.debug('signUp validation data:', validationData);
|
|
416
|
-
|
|
417
|
-
return new Promise((resolve, reject) => {
|
|
418
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
419
|
-
AuthAction.SignUp,
|
|
420
|
-
customUserAgentDetails
|
|
421
|
-
);
|
|
422
|
-
this.userPool.signUp(
|
|
423
|
-
username,
|
|
424
|
-
password,
|
|
425
|
-
attributes,
|
|
426
|
-
validationData,
|
|
427
|
-
(err, data) => {
|
|
428
|
-
if (err) {
|
|
429
|
-
dispatchAuthEvent(
|
|
430
|
-
'signUp_failure',
|
|
431
|
-
err,
|
|
432
|
-
`${username} failed to signup`
|
|
433
|
-
);
|
|
434
|
-
reject(err);
|
|
435
|
-
} else {
|
|
436
|
-
dispatchAuthEvent(
|
|
437
|
-
'signUp',
|
|
438
|
-
data,
|
|
439
|
-
`${username} has signed up successfully`
|
|
440
|
-
);
|
|
441
|
-
if (autoSignIn.enabled) {
|
|
442
|
-
this.handleAutoSignIn(
|
|
443
|
-
username,
|
|
444
|
-
password,
|
|
445
|
-
autoSignInValidationData,
|
|
446
|
-
autoSignInClientMetaData,
|
|
447
|
-
data,
|
|
448
|
-
userAgentDetails
|
|
449
|
-
);
|
|
450
|
-
}
|
|
451
|
-
resolve(data);
|
|
452
|
-
}
|
|
453
|
-
},
|
|
454
|
-
clientMetadata,
|
|
455
|
-
getAmplifyUserAgent(userAgentDetails)
|
|
456
|
-
);
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
private handleAutoSignIn(
|
|
461
|
-
username: string,
|
|
462
|
-
password: string,
|
|
463
|
-
validationData: {},
|
|
464
|
-
clientMetadata: any,
|
|
465
|
-
data: any,
|
|
466
|
-
customUserAgentDetails: CustomUserAgentDetails
|
|
467
|
-
) {
|
|
468
|
-
this.autoSignInInitiated = true;
|
|
469
|
-
const authDetails = new AuthenticationDetails({
|
|
470
|
-
Username: username,
|
|
471
|
-
Password: password,
|
|
472
|
-
ValidationData: validationData,
|
|
473
|
-
ClientMetadata: clientMetadata,
|
|
474
|
-
});
|
|
475
|
-
if (data.userConfirmed) {
|
|
476
|
-
this.signInAfterUserConfirmed(authDetails, customUserAgentDetails);
|
|
477
|
-
} else if (this._config.signUpVerificationMethod === 'link') {
|
|
478
|
-
this.handleLinkAutoSignIn(authDetails, customUserAgentDetails);
|
|
479
|
-
} else {
|
|
480
|
-
this.handleCodeAutoSignIn(authDetails, customUserAgentDetails);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
private handleCodeAutoSignIn(
|
|
485
|
-
authDetails: AuthenticationDetails,
|
|
486
|
-
customUserAgentDetails: CustomUserAgentDetails
|
|
487
|
-
) {
|
|
488
|
-
const listenEvent = ({ payload }) => {
|
|
489
|
-
if (payload.event === 'confirmSignUp') {
|
|
490
|
-
this.signInAfterUserConfirmed(
|
|
491
|
-
authDetails,
|
|
492
|
-
customUserAgentDetails,
|
|
493
|
-
listenEvent
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
};
|
|
497
|
-
Hub.listen('auth', listenEvent);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
private handleLinkAutoSignIn(
|
|
501
|
-
authDetails: AuthenticationDetails,
|
|
502
|
-
customUserAgentDetails: CustomUserAgentDetails
|
|
503
|
-
) {
|
|
504
|
-
this._storage.setItem('amplify-polling-started', 'true');
|
|
505
|
-
const start = Date.now();
|
|
506
|
-
const autoSignInPollingIntervalId = setInterval(() => {
|
|
507
|
-
if (Date.now() - start > MAX_AUTOSIGNIN_POLLING_MS) {
|
|
508
|
-
clearInterval(autoSignInPollingIntervalId);
|
|
509
|
-
dispatchAuthEvent(
|
|
510
|
-
'autoSignIn_failure',
|
|
511
|
-
null,
|
|
512
|
-
'Please confirm your account and use your credentials to sign in.'
|
|
513
|
-
);
|
|
514
|
-
this._storage.removeItem('amplify-auto-sign-in');
|
|
515
|
-
} else {
|
|
516
|
-
this.signInAfterUserConfirmed(
|
|
517
|
-
authDetails,
|
|
518
|
-
customUserAgentDetails,
|
|
519
|
-
undefined,
|
|
520
|
-
autoSignInPollingIntervalId
|
|
521
|
-
);
|
|
522
|
-
}
|
|
523
|
-
}, 5000);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
private async signInAfterUserConfirmed(
|
|
527
|
-
authDetails: AuthenticationDetails,
|
|
528
|
-
customUserAgentDetails: CustomUserAgentDetails,
|
|
529
|
-
listenEvent?: HubCallback,
|
|
530
|
-
autoSignInPollingIntervalId?: ReturnType<typeof setInterval>
|
|
531
|
-
) {
|
|
532
|
-
const user = this.createCognitoUser(authDetails.getUsername());
|
|
533
|
-
try {
|
|
534
|
-
await user.authenticateUser(
|
|
535
|
-
authDetails,
|
|
536
|
-
this.authCallbacks(
|
|
537
|
-
user,
|
|
538
|
-
value => {
|
|
539
|
-
dispatchAuthEvent(
|
|
540
|
-
'autoSignIn',
|
|
541
|
-
value,
|
|
542
|
-
`${authDetails.getUsername()} has signed in successfully`
|
|
543
|
-
);
|
|
544
|
-
if (listenEvent) {
|
|
545
|
-
Hub.remove('auth', listenEvent);
|
|
546
|
-
}
|
|
547
|
-
if (autoSignInPollingIntervalId) {
|
|
548
|
-
clearInterval(autoSignInPollingIntervalId);
|
|
549
|
-
this._storage.removeItem('amplify-polling-started');
|
|
550
|
-
}
|
|
551
|
-
this._storage.removeItem('amplify-auto-sign-in');
|
|
552
|
-
},
|
|
553
|
-
error => {
|
|
554
|
-
logger.error(error);
|
|
555
|
-
this._storage.removeItem('amplify-auto-sign-in');
|
|
556
|
-
},
|
|
557
|
-
customUserAgentDetails
|
|
558
|
-
),
|
|
559
|
-
getAmplifyUserAgent(customUserAgentDetails)
|
|
560
|
-
);
|
|
561
|
-
} catch (error) {
|
|
562
|
-
logger.error(error);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
/**
|
|
567
|
-
* Send the verification code to confirm sign up
|
|
568
|
-
* @param {String} username - The username to be confirmed
|
|
569
|
-
* @param {String} code - The verification code
|
|
570
|
-
* @param {ConfirmSignUpOptions} options - other options for confirm signup
|
|
571
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
572
|
-
* @return - A promise resolves callback data if success
|
|
573
|
-
*/
|
|
574
|
-
public confirmSignUp(
|
|
575
|
-
username: string,
|
|
576
|
-
code: string,
|
|
577
|
-
options?: ConfirmSignUpOptions,
|
|
578
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
579
|
-
): Promise<any> {
|
|
580
|
-
if (!this.userPool) {
|
|
581
|
-
return this.rejectNoUserPool();
|
|
582
|
-
}
|
|
583
|
-
if (!username) {
|
|
584
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyUsername);
|
|
585
|
-
}
|
|
586
|
-
if (!code) {
|
|
587
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyCode);
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
const user = this.createCognitoUser(username);
|
|
591
|
-
const forceAliasCreation =
|
|
592
|
-
options && typeof options.forceAliasCreation === 'boolean'
|
|
593
|
-
? options.forceAliasCreation
|
|
594
|
-
: true;
|
|
595
|
-
|
|
596
|
-
let clientMetadata;
|
|
597
|
-
if (options && options.clientMetadata) {
|
|
598
|
-
clientMetadata = options.clientMetadata;
|
|
599
|
-
} else if (this._config.clientMetadata) {
|
|
600
|
-
clientMetadata = this._config.clientMetadata;
|
|
601
|
-
}
|
|
602
|
-
return new Promise((resolve, reject) => {
|
|
603
|
-
user.confirmRegistration(
|
|
604
|
-
code,
|
|
605
|
-
forceAliasCreation,
|
|
606
|
-
(err, data) => {
|
|
607
|
-
if (err) {
|
|
608
|
-
reject(err);
|
|
609
|
-
} else {
|
|
610
|
-
dispatchAuthEvent(
|
|
611
|
-
'confirmSignUp',
|
|
612
|
-
data,
|
|
613
|
-
`${username} has been confirmed successfully`
|
|
614
|
-
);
|
|
615
|
-
const autoSignIn = this.isTrueStorageValue('amplify-auto-sign-in');
|
|
616
|
-
if (autoSignIn && !this.autoSignInInitiated) {
|
|
617
|
-
dispatchAuthEvent(
|
|
618
|
-
'autoSignIn_failure',
|
|
619
|
-
null,
|
|
620
|
-
AuthErrorTypes.AutoSignInError
|
|
621
|
-
);
|
|
622
|
-
this._storage.removeItem('amplify-auto-sign-in');
|
|
623
|
-
}
|
|
624
|
-
resolve(data);
|
|
625
|
-
}
|
|
626
|
-
},
|
|
627
|
-
clientMetadata,
|
|
628
|
-
getAuthUserAgentValue(AuthAction.ConfirmSignUp, customUserAgentDetails)
|
|
629
|
-
);
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
private isTrueStorageValue(value: string) {
|
|
634
|
-
const item = this._storage.getItem(value);
|
|
635
|
-
return item ? item === 'true' : false;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
/**
|
|
639
|
-
* Resend the verification code
|
|
640
|
-
* @param {String} username - The username to be confirmed
|
|
641
|
-
* @param {ClientMetadata} clientMetadata - Metadata to be passed to Cognito Lambda triggers
|
|
642
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
643
|
-
* @return - A promise resolves code delivery details if successful
|
|
644
|
-
*/
|
|
645
|
-
public resendSignUp(
|
|
646
|
-
username: string,
|
|
647
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
648
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
649
|
-
): Promise<any> {
|
|
650
|
-
if (!this.userPool) {
|
|
651
|
-
return this.rejectNoUserPool();
|
|
652
|
-
}
|
|
653
|
-
if (!username) {
|
|
654
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyUsername);
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
const user = this.createCognitoUser(username);
|
|
658
|
-
return new Promise((resolve, reject) => {
|
|
659
|
-
user.resendConfirmationCode(
|
|
660
|
-
(err, data) => {
|
|
661
|
-
if (err) {
|
|
662
|
-
reject(err);
|
|
663
|
-
} else {
|
|
664
|
-
resolve(data);
|
|
665
|
-
}
|
|
666
|
-
},
|
|
667
|
-
clientMetadata,
|
|
668
|
-
getAuthUserAgentValue(AuthAction.ResendSignUp, customUserAgentDetails)
|
|
669
|
-
);
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
/**
|
|
674
|
-
* Sign in
|
|
675
|
-
* @param {String | SignInOpts} usernameOrSignInOpts - The username to be signed in or the sign in options
|
|
676
|
-
* @param {String} pw - The password of the username
|
|
677
|
-
* @param {ClientMetaData} clientMetadata - Client metadata for custom workflows
|
|
678
|
-
* @return - A promise resolves the CognitoUser
|
|
679
|
-
*/
|
|
680
|
-
public signIn(
|
|
681
|
-
usernameOrSignInOpts: string | SignInOpts,
|
|
682
|
-
pw?: string,
|
|
683
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
684
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
685
|
-
): Promise<CognitoUser | any> {
|
|
686
|
-
if (!this.userPool) {
|
|
687
|
-
return this.rejectNoUserPool();
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
let username = null;
|
|
691
|
-
let password = null;
|
|
692
|
-
let validationData = {};
|
|
693
|
-
|
|
694
|
-
// for backward compatibility
|
|
695
|
-
if (typeof usernameOrSignInOpts === 'string') {
|
|
696
|
-
username = usernameOrSignInOpts;
|
|
697
|
-
password = pw;
|
|
698
|
-
} else if (isUsernamePasswordOpts(usernameOrSignInOpts)) {
|
|
699
|
-
if (typeof pw !== 'undefined') {
|
|
700
|
-
logger.warn(
|
|
701
|
-
'The password should be defined under the first parameter object!'
|
|
702
|
-
);
|
|
703
|
-
}
|
|
704
|
-
username = usernameOrSignInOpts.username;
|
|
705
|
-
password = usernameOrSignInOpts.password;
|
|
706
|
-
validationData = usernameOrSignInOpts.validationData;
|
|
707
|
-
} else {
|
|
708
|
-
return this.rejectAuthError(AuthErrorTypes.InvalidUsername);
|
|
709
|
-
}
|
|
710
|
-
if (!username) {
|
|
711
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyUsername);
|
|
712
|
-
}
|
|
713
|
-
const authDetails = new AuthenticationDetails({
|
|
714
|
-
Username: username,
|
|
715
|
-
Password: password,
|
|
716
|
-
ValidationData: validationData,
|
|
717
|
-
ClientMetadata: clientMetadata,
|
|
718
|
-
});
|
|
719
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
720
|
-
AuthAction.SignIn,
|
|
721
|
-
customUserAgentDetails
|
|
722
|
-
);
|
|
723
|
-
if (password) {
|
|
724
|
-
return this.signInWithPassword(authDetails, userAgentDetails);
|
|
725
|
-
} else {
|
|
726
|
-
return this.signInWithoutPassword(authDetails, userAgentDetails);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
/**
|
|
731
|
-
* Return an object with the authentication callbacks
|
|
732
|
-
* @param {InternalCognitoUser} user - the cognito user object
|
|
733
|
-
* @param {} resolve - function called when resolving the current step
|
|
734
|
-
* @param {} reject - function called when rejecting the current step
|
|
735
|
-
* @return - an object with the callback methods for user authentication
|
|
736
|
-
*/
|
|
737
|
-
private authCallbacks(
|
|
738
|
-
user: InternalCognitoUser,
|
|
739
|
-
resolve: (value?: InternalCognitoUser | any) => void,
|
|
740
|
-
reject: (value?: any) => void,
|
|
741
|
-
customUserAgentDetails: CustomUserAgentDetails
|
|
742
|
-
): IAuthenticationCallback {
|
|
743
|
-
const that = this;
|
|
744
|
-
return {
|
|
745
|
-
onSuccess: async session => {
|
|
746
|
-
logger.debug(session);
|
|
747
|
-
delete user['challengeName'];
|
|
748
|
-
delete user['challengeParam'];
|
|
749
|
-
try {
|
|
750
|
-
await this.Credentials.clear();
|
|
751
|
-
const cred = await this.Credentials.set(session, 'session');
|
|
752
|
-
logger.debug('succeed to get cognito credentials', cred);
|
|
753
|
-
} catch (e) {
|
|
754
|
-
logger.debug('cannot get cognito credentials', e);
|
|
755
|
-
} finally {
|
|
756
|
-
try {
|
|
757
|
-
// In order to get user attributes and MFA methods
|
|
758
|
-
// We need to trigger currentUserPoolUser again
|
|
759
|
-
const currentUser = await this._currentUserPoolUser(
|
|
760
|
-
undefined,
|
|
761
|
-
customUserAgentDetails
|
|
762
|
-
);
|
|
763
|
-
that.user = currentUser;
|
|
764
|
-
dispatchAuthEvent(
|
|
765
|
-
'signIn',
|
|
766
|
-
currentUser,
|
|
767
|
-
`A user ${user.getUsername()} has been signed in`
|
|
768
|
-
);
|
|
769
|
-
resolve(currentUser);
|
|
770
|
-
} catch (e) {
|
|
771
|
-
logger.error('Failed to get the signed in user', e);
|
|
772
|
-
reject(e);
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
},
|
|
776
|
-
onFailure: err => {
|
|
777
|
-
logger.debug('signIn failure', err);
|
|
778
|
-
dispatchAuthEvent(
|
|
779
|
-
'signIn_failure',
|
|
780
|
-
err,
|
|
781
|
-
`${user.getUsername()} failed to signin`
|
|
782
|
-
);
|
|
783
|
-
reject(err);
|
|
784
|
-
},
|
|
785
|
-
customChallenge: challengeParam => {
|
|
786
|
-
logger.debug('signIn custom challenge answer required');
|
|
787
|
-
user['challengeName'] = 'CUSTOM_CHALLENGE';
|
|
788
|
-
user['challengeParam'] = challengeParam;
|
|
789
|
-
resolve(user);
|
|
790
|
-
},
|
|
791
|
-
mfaRequired: (challengeName, challengeParam) => {
|
|
792
|
-
logger.debug('signIn MFA required');
|
|
793
|
-
user['challengeName'] = challengeName;
|
|
794
|
-
user['challengeParam'] = challengeParam;
|
|
795
|
-
resolve(user);
|
|
796
|
-
},
|
|
797
|
-
mfaSetup: (challengeName, challengeParam) => {
|
|
798
|
-
logger.debug('signIn mfa setup', challengeName);
|
|
799
|
-
user['challengeName'] = challengeName;
|
|
800
|
-
user['challengeParam'] = challengeParam;
|
|
801
|
-
resolve(user);
|
|
802
|
-
},
|
|
803
|
-
newPasswordRequired: (userAttributes, requiredAttributes) => {
|
|
804
|
-
logger.debug('signIn new password');
|
|
805
|
-
user['challengeName'] = 'NEW_PASSWORD_REQUIRED';
|
|
806
|
-
user['challengeParam'] = {
|
|
807
|
-
userAttributes,
|
|
808
|
-
requiredAttributes,
|
|
809
|
-
};
|
|
810
|
-
resolve(user);
|
|
811
|
-
},
|
|
812
|
-
totpRequired: (challengeName, challengeParam) => {
|
|
813
|
-
logger.debug('signIn totpRequired');
|
|
814
|
-
user['challengeName'] = challengeName;
|
|
815
|
-
user['challengeParam'] = challengeParam;
|
|
816
|
-
resolve(user);
|
|
817
|
-
},
|
|
818
|
-
selectMFAType: (challengeName, challengeParam) => {
|
|
819
|
-
logger.debug('signIn selectMFAType', challengeName);
|
|
820
|
-
user['challengeName'] = challengeName;
|
|
821
|
-
user['challengeParam'] = challengeParam;
|
|
822
|
-
resolve(user);
|
|
823
|
-
},
|
|
824
|
-
};
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
/**
|
|
828
|
-
* Sign in with a password
|
|
829
|
-
* @private
|
|
830
|
-
* @param {AuthenticationDetails} authDetails - the user sign in data
|
|
831
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
832
|
-
* @return - A promise resolves the CognitoUser object if success or mfa required
|
|
833
|
-
*/
|
|
834
|
-
private signInWithPassword(
|
|
835
|
-
authDetails: AuthenticationDetails,
|
|
836
|
-
customUserAgentDetails: CustomUserAgentDetails
|
|
837
|
-
): Promise<InternalCognitoUser | any> {
|
|
838
|
-
if (this.pendingSignIn) {
|
|
839
|
-
throw new Error('Pending sign-in attempt already in progress');
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
const user = this.createCognitoUser(authDetails.getUsername());
|
|
843
|
-
|
|
844
|
-
this.pendingSignIn = new Promise((resolve, reject) => {
|
|
845
|
-
user.authenticateUser(
|
|
846
|
-
authDetails,
|
|
847
|
-
this.authCallbacks(
|
|
848
|
-
user,
|
|
849
|
-
value => {
|
|
850
|
-
this.pendingSignIn = null;
|
|
851
|
-
resolve(value);
|
|
852
|
-
},
|
|
853
|
-
error => {
|
|
854
|
-
this.pendingSignIn = null;
|
|
855
|
-
reject(error);
|
|
856
|
-
},
|
|
857
|
-
customUserAgentDetails
|
|
858
|
-
),
|
|
859
|
-
getAmplifyUserAgent(customUserAgentDetails)
|
|
860
|
-
);
|
|
861
|
-
});
|
|
862
|
-
|
|
863
|
-
return this.pendingSignIn;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
/**
|
|
867
|
-
* Sign in without a password
|
|
868
|
-
* @private
|
|
869
|
-
* @param {AuthenticationDetails} authDetails - the user sign in data
|
|
870
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
871
|
-
* @return - A promise resolves the InternalCognitoUser object if success or mfa required
|
|
872
|
-
*/
|
|
873
|
-
private signInWithoutPassword(
|
|
874
|
-
authDetails: AuthenticationDetails,
|
|
875
|
-
customUserAgentDetails: CustomUserAgentDetails
|
|
876
|
-
): Promise<InternalCognitoUser | any> {
|
|
877
|
-
const user = this.createCognitoUser(authDetails.getUsername());
|
|
878
|
-
user.setAuthenticationFlowType('CUSTOM_AUTH');
|
|
879
|
-
|
|
880
|
-
return new Promise((resolve, reject) => {
|
|
881
|
-
user.initiateAuth(
|
|
882
|
-
authDetails,
|
|
883
|
-
this.authCallbacks(user, resolve, reject, customUserAgentDetails),
|
|
884
|
-
getAmplifyUserAgent(customUserAgentDetails)
|
|
885
|
-
);
|
|
886
|
-
});
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
/**
|
|
890
|
-
* This was previously used by an authenticated user to get MFAOptions,
|
|
891
|
-
* but no longer returns a meaningful response. Refer to the documentation for
|
|
892
|
-
* how to setup and use MFA: https://docs.amplify.aws/lib/auth/mfa/q/platform/js
|
|
893
|
-
* @deprecated
|
|
894
|
-
* @param {CognitoUser} user - the current user
|
|
895
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
896
|
-
* @return - A promise resolves the current preferred mfa option if success
|
|
897
|
-
*/
|
|
898
|
-
public getMFAOptions(
|
|
899
|
-
user: CognitoUser | any,
|
|
900
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
901
|
-
): Promise<MFAOption[]> {
|
|
902
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
903
|
-
|
|
904
|
-
return new Promise((res, rej) => {
|
|
905
|
-
internalUser.getMFAOptions((err, mfaOptions) => {
|
|
906
|
-
if (err) {
|
|
907
|
-
logger.debug('get MFA Options failed', err);
|
|
908
|
-
rej(err);
|
|
909
|
-
return;
|
|
910
|
-
}
|
|
911
|
-
logger.debug('get MFA options success', mfaOptions);
|
|
912
|
-
res(mfaOptions);
|
|
913
|
-
return;
|
|
914
|
-
}, getAuthUserAgentValue(AuthAction.GetMFAOptions, customUserAgentDetails));
|
|
915
|
-
});
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
/**
|
|
919
|
-
* get preferred mfa method
|
|
920
|
-
* @param {CognitoUser} user - the current cognito user
|
|
921
|
-
* @param {GetPreferredMFAOpts} params - options for getting the current user preferred MFA
|
|
922
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
923
|
-
*/
|
|
924
|
-
public getPreferredMFA(
|
|
925
|
-
user: CognitoUser | any,
|
|
926
|
-
params?: GetPreferredMFAOpts,
|
|
927
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
928
|
-
): Promise<string> {
|
|
929
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
930
|
-
const that = this;
|
|
931
|
-
return new Promise((res, rej) => {
|
|
932
|
-
const clientMetadata = this._config.clientMetadata; // TODO: verify behavior if this is override during signIn
|
|
933
|
-
|
|
934
|
-
const bypassCache = params ? params.bypassCache : false;
|
|
935
|
-
const userAgentValue = getAuthUserAgentValue(
|
|
936
|
-
AuthAction.GetPreferredMFA,
|
|
937
|
-
customUserAgentDetails
|
|
938
|
-
);
|
|
939
|
-
internalUser.getUserData(
|
|
940
|
-
async (err, data) => {
|
|
941
|
-
if (err) {
|
|
942
|
-
logger.debug('getting preferred mfa failed', err);
|
|
943
|
-
if (this.isSessionInvalid(err)) {
|
|
944
|
-
try {
|
|
945
|
-
await this.cleanUpInvalidSession(user, userAgentValue);
|
|
946
|
-
} catch (cleanUpError) {
|
|
947
|
-
rej(
|
|
948
|
-
new Error(
|
|
949
|
-
`Session is invalid due to: ${err.message} and failed to clean up invalid session: ${cleanUpError.message}`
|
|
950
|
-
)
|
|
951
|
-
);
|
|
952
|
-
return;
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
rej(err);
|
|
956
|
-
return;
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
const mfaType = that._getMfaTypeFromUserData(data);
|
|
960
|
-
if (!mfaType) {
|
|
961
|
-
rej('invalid MFA Type');
|
|
962
|
-
return;
|
|
963
|
-
} else {
|
|
964
|
-
res(mfaType);
|
|
965
|
-
return;
|
|
966
|
-
}
|
|
967
|
-
},
|
|
968
|
-
{ bypassCache, clientMetadata },
|
|
969
|
-
userAgentValue
|
|
970
|
-
);
|
|
971
|
-
});
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
private _getMfaTypeFromUserData(data) {
|
|
975
|
-
let ret = null;
|
|
976
|
-
const preferredMFA = data.PreferredMfaSetting;
|
|
977
|
-
// if the user has used Auth.setPreferredMFA() to setup the mfa type
|
|
978
|
-
// then the "PreferredMfaSetting" would exist in the response
|
|
979
|
-
if (preferredMFA) {
|
|
980
|
-
ret = preferredMFA;
|
|
981
|
-
} else {
|
|
982
|
-
// if mfaList exists but empty, then its noMFA
|
|
983
|
-
const mfaList = data.UserMFASettingList;
|
|
984
|
-
if (!mfaList) {
|
|
985
|
-
// if SMS was enabled by using Auth.enableSMS(),
|
|
986
|
-
// the response would contain MFAOptions
|
|
987
|
-
// as for now Cognito only supports for SMS, so we will say it is 'SMS_MFA'
|
|
988
|
-
// if it does not exist, then it should be NOMFA
|
|
989
|
-
const MFAOptions = data.MFAOptions;
|
|
990
|
-
if (MFAOptions) {
|
|
991
|
-
ret = 'SMS_MFA';
|
|
992
|
-
} else {
|
|
993
|
-
ret = 'NOMFA';
|
|
994
|
-
}
|
|
995
|
-
} else if (mfaList.length === 0) {
|
|
996
|
-
ret = 'NOMFA';
|
|
997
|
-
} else {
|
|
998
|
-
logger.debug('invalid case for getPreferredMFA', data);
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
return ret;
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
private _getUserData(
|
|
1005
|
-
user: InternalCognitoUser,
|
|
1006
|
-
params,
|
|
1007
|
-
userAgentValue: string
|
|
1008
|
-
) {
|
|
1009
|
-
return new Promise((res, rej) => {
|
|
1010
|
-
user.getUserData(
|
|
1011
|
-
async (err, data) => {
|
|
1012
|
-
if (err) {
|
|
1013
|
-
logger.debug('getting user data failed', err);
|
|
1014
|
-
if (this.isSessionInvalid(err)) {
|
|
1015
|
-
try {
|
|
1016
|
-
await this.cleanUpInvalidSession(user, userAgentValue);
|
|
1017
|
-
} catch (cleanUpError) {
|
|
1018
|
-
rej(
|
|
1019
|
-
new Error(
|
|
1020
|
-
`Session is invalid due to: ${err.message} and failed to clean up invalid session: ${cleanUpError.message}`
|
|
1021
|
-
)
|
|
1022
|
-
);
|
|
1023
|
-
return;
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
rej(err);
|
|
1027
|
-
return;
|
|
1028
|
-
} else {
|
|
1029
|
-
res(data);
|
|
1030
|
-
}
|
|
1031
|
-
},
|
|
1032
|
-
params,
|
|
1033
|
-
userAgentValue
|
|
1034
|
-
);
|
|
1035
|
-
});
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
/**
|
|
1039
|
-
* set preferred MFA method
|
|
1040
|
-
* @param {CognitoUser} user - the current Cognito user
|
|
1041
|
-
* @param {string} mfaMethod - preferred mfa method
|
|
1042
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1043
|
-
* @return - A promise resolve if success
|
|
1044
|
-
*/
|
|
1045
|
-
public async setPreferredMFA(
|
|
1046
|
-
user: CognitoUser | any,
|
|
1047
|
-
mfaMethod: 'TOTP' | 'SMS' | 'NOMFA' | 'SMS_MFA' | 'SOFTWARE_TOKEN_MFA',
|
|
1048
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1049
|
-
): Promise<string> {
|
|
1050
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
1051
|
-
const userAgentValue = getAuthUserAgentValue(
|
|
1052
|
-
AuthAction.SetPreferredMFA,
|
|
1053
|
-
customUserAgentDetails
|
|
1054
|
-
);
|
|
1055
|
-
const clientMetadata = this._config.clientMetadata; // TODO: verify behavior if this is override during signIn
|
|
1056
|
-
|
|
1057
|
-
const userData = await this._getUserData(
|
|
1058
|
-
user,
|
|
1059
|
-
{
|
|
1060
|
-
bypassCache: true,
|
|
1061
|
-
clientMetadata,
|
|
1062
|
-
},
|
|
1063
|
-
userAgentValue
|
|
1064
|
-
);
|
|
1065
|
-
let smsMfaSettings = null;
|
|
1066
|
-
let totpMfaSettings = null;
|
|
1067
|
-
|
|
1068
|
-
switch (mfaMethod) {
|
|
1069
|
-
case 'TOTP':
|
|
1070
|
-
case 'SOFTWARE_TOKEN_MFA':
|
|
1071
|
-
totpMfaSettings = {
|
|
1072
|
-
PreferredMfa: true,
|
|
1073
|
-
Enabled: true,
|
|
1074
|
-
};
|
|
1075
|
-
break;
|
|
1076
|
-
case 'SMS':
|
|
1077
|
-
case 'SMS_MFA':
|
|
1078
|
-
smsMfaSettings = {
|
|
1079
|
-
PreferredMfa: true,
|
|
1080
|
-
Enabled: true,
|
|
1081
|
-
};
|
|
1082
|
-
break;
|
|
1083
|
-
case 'NOMFA':
|
|
1084
|
-
const mfaList = userData['UserMFASettingList'];
|
|
1085
|
-
const currentMFAType = await this._getMfaTypeFromUserData(userData);
|
|
1086
|
-
if (currentMFAType === 'NOMFA') {
|
|
1087
|
-
return Promise.resolve('No change for mfa type');
|
|
1088
|
-
} else if (currentMFAType === 'SMS_MFA') {
|
|
1089
|
-
smsMfaSettings = {
|
|
1090
|
-
PreferredMfa: false,
|
|
1091
|
-
Enabled: false,
|
|
1092
|
-
};
|
|
1093
|
-
} else if (currentMFAType === 'SOFTWARE_TOKEN_MFA') {
|
|
1094
|
-
totpMfaSettings = {
|
|
1095
|
-
PreferredMfa: false,
|
|
1096
|
-
Enabled: false,
|
|
1097
|
-
};
|
|
1098
|
-
} else {
|
|
1099
|
-
return this.rejectAuthError(AuthErrorTypes.InvalidMFA);
|
|
1100
|
-
}
|
|
1101
|
-
// if there is a UserMFASettingList in the response
|
|
1102
|
-
// we need to disable every mfa type in that list
|
|
1103
|
-
if (mfaList && mfaList.length !== 0) {
|
|
1104
|
-
// to disable SMS or TOTP if exists in that list
|
|
1105
|
-
mfaList.forEach(mfaType => {
|
|
1106
|
-
if (mfaType === 'SMS_MFA') {
|
|
1107
|
-
smsMfaSettings = {
|
|
1108
|
-
PreferredMfa: false,
|
|
1109
|
-
Enabled: false,
|
|
1110
|
-
};
|
|
1111
|
-
} else if (mfaType === 'SOFTWARE_TOKEN_MFA') {
|
|
1112
|
-
totpMfaSettings = {
|
|
1113
|
-
PreferredMfa: false,
|
|
1114
|
-
Enabled: false,
|
|
1115
|
-
};
|
|
1116
|
-
}
|
|
1117
|
-
});
|
|
1118
|
-
}
|
|
1119
|
-
break;
|
|
1120
|
-
default:
|
|
1121
|
-
logger.debug('no validmfa method provided');
|
|
1122
|
-
return this.rejectAuthError(AuthErrorTypes.NoMFA);
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
const that = this;
|
|
1126
|
-
return new Promise<string>((res, rej) => {
|
|
1127
|
-
internalUser.setUserMfaPreference(
|
|
1128
|
-
smsMfaSettings,
|
|
1129
|
-
totpMfaSettings,
|
|
1130
|
-
(err, result) => {
|
|
1131
|
-
if (err) {
|
|
1132
|
-
logger.debug('Set user mfa preference error', err);
|
|
1133
|
-
return rej(err);
|
|
1134
|
-
}
|
|
1135
|
-
logger.debug('Set user mfa success', result);
|
|
1136
|
-
logger.debug('Caching the latest user data into local');
|
|
1137
|
-
// cache the latest result into user data
|
|
1138
|
-
internalUser.getUserData(
|
|
1139
|
-
async (err, data) => {
|
|
1140
|
-
if (err) {
|
|
1141
|
-
logger.debug('getting user data failed', err);
|
|
1142
|
-
if (this.isSessionInvalid(err)) {
|
|
1143
|
-
try {
|
|
1144
|
-
await this.cleanUpInvalidSession(user, userAgentValue);
|
|
1145
|
-
} catch (cleanUpError) {
|
|
1146
|
-
rej(
|
|
1147
|
-
new Error(
|
|
1148
|
-
`Session is invalid due to: ${err.message} and failed to clean up invalid session: ${cleanUpError.message}`
|
|
1149
|
-
)
|
|
1150
|
-
);
|
|
1151
|
-
return;
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
return rej(err);
|
|
1155
|
-
} else {
|
|
1156
|
-
return res(result);
|
|
1157
|
-
}
|
|
1158
|
-
},
|
|
1159
|
-
{
|
|
1160
|
-
bypassCache: true,
|
|
1161
|
-
clientMetadata,
|
|
1162
|
-
},
|
|
1163
|
-
userAgentValue
|
|
1164
|
-
);
|
|
1165
|
-
},
|
|
1166
|
-
userAgentValue
|
|
1167
|
-
);
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
/**
|
|
1172
|
-
* disable SMS
|
|
1173
|
-
* @deprecated
|
|
1174
|
-
* @param {CognitoUser} user - the current user
|
|
1175
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1176
|
-
* @return - A promise resolves is success
|
|
1177
|
-
*/
|
|
1178
|
-
public disableSMS(
|
|
1179
|
-
user: CognitoUser,
|
|
1180
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1181
|
-
): Promise<string> {
|
|
1182
|
-
const internalUser = user as InternalCognitoUser;
|
|
1183
|
-
|
|
1184
|
-
return new Promise((res, rej) => {
|
|
1185
|
-
internalUser.disableMFA((err, data) => {
|
|
1186
|
-
if (err) {
|
|
1187
|
-
logger.debug('disable mfa failed', err);
|
|
1188
|
-
rej(err);
|
|
1189
|
-
return;
|
|
1190
|
-
}
|
|
1191
|
-
logger.debug('disable mfa succeed', data);
|
|
1192
|
-
res(data);
|
|
1193
|
-
return;
|
|
1194
|
-
}, getAuthUserAgentValue(AuthAction.DisableSMS, customUserAgentDetails));
|
|
1195
|
-
});
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
/**
|
|
1199
|
-
* enable SMS
|
|
1200
|
-
* @deprecated
|
|
1201
|
-
* @param {CognitoUser} user - the current user
|
|
1202
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1203
|
-
* @return - A promise resolves is success
|
|
1204
|
-
*/
|
|
1205
|
-
public enableSMS(
|
|
1206
|
-
user: CognitoUser,
|
|
1207
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1208
|
-
): Promise<string> {
|
|
1209
|
-
const internalUser = user as InternalCognitoUser;
|
|
1210
|
-
|
|
1211
|
-
return new Promise((res, rej) => {
|
|
1212
|
-
internalUser.enableMFA((err, data) => {
|
|
1213
|
-
if (err) {
|
|
1214
|
-
logger.debug('enable mfa failed', err);
|
|
1215
|
-
rej(err);
|
|
1216
|
-
return;
|
|
1217
|
-
}
|
|
1218
|
-
logger.debug('enable mfa succeed', data);
|
|
1219
|
-
res(data);
|
|
1220
|
-
return;
|
|
1221
|
-
}, getAuthUserAgentValue(AuthAction.EnableSMS, customUserAgentDetails));
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
/**
|
|
1226
|
-
* Setup TOTP
|
|
1227
|
-
* @param {CognitoUser} user - the current user
|
|
1228
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1229
|
-
* @return - A promise resolves with the secret code if success
|
|
1230
|
-
*/
|
|
1231
|
-
public setupTOTP(
|
|
1232
|
-
user: CognitoUser | any,
|
|
1233
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1234
|
-
): Promise<string> {
|
|
1235
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
1236
|
-
|
|
1237
|
-
return new Promise((res, rej) => {
|
|
1238
|
-
internalUser.associateSoftwareToken(
|
|
1239
|
-
{
|
|
1240
|
-
onFailure: err => {
|
|
1241
|
-
logger.debug('associateSoftwareToken failed', err);
|
|
1242
|
-
rej(err);
|
|
1243
|
-
return;
|
|
1244
|
-
},
|
|
1245
|
-
associateSecretCode: secretCode => {
|
|
1246
|
-
logger.debug('associateSoftwareToken success', secretCode);
|
|
1247
|
-
res(secretCode);
|
|
1248
|
-
return;
|
|
1249
|
-
},
|
|
1250
|
-
},
|
|
1251
|
-
getAuthUserAgentValue(AuthAction.SetupTOTP, customUserAgentDetails)
|
|
1252
|
-
);
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
/**
|
|
1257
|
-
* verify TOTP setup
|
|
1258
|
-
* @param {CognitoUser} user - the current user
|
|
1259
|
-
* @param {string} challengeAnswer - challenge answer
|
|
1260
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1261
|
-
* @return - A promise resolves is success
|
|
1262
|
-
*/
|
|
1263
|
-
public verifyTotpToken(
|
|
1264
|
-
user: CognitoUser | any,
|
|
1265
|
-
challengeAnswer: string,
|
|
1266
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1267
|
-
): Promise<CognitoUserSession> {
|
|
1268
|
-
logger.debug('verification totp token', user, challengeAnswer);
|
|
1269
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
1270
|
-
|
|
1271
|
-
let signInUserSession;
|
|
1272
|
-
if (
|
|
1273
|
-
internalUser &&
|
|
1274
|
-
typeof internalUser.getSignInUserSession === 'function'
|
|
1275
|
-
) {
|
|
1276
|
-
signInUserSession = (user as InternalCognitoUser).getSignInUserSession();
|
|
1277
|
-
}
|
|
1278
|
-
const isLoggedIn = signInUserSession?.isValid();
|
|
1279
|
-
|
|
1280
|
-
return new Promise((res, rej) => {
|
|
1281
|
-
internalUser.verifySoftwareToken(
|
|
1282
|
-
challengeAnswer,
|
|
1283
|
-
'My TOTP device',
|
|
1284
|
-
{
|
|
1285
|
-
onFailure: err => {
|
|
1286
|
-
logger.debug('verifyTotpToken failed', err);
|
|
1287
|
-
rej(err);
|
|
1288
|
-
return;
|
|
1289
|
-
},
|
|
1290
|
-
onSuccess: data => {
|
|
1291
|
-
if (!isLoggedIn) {
|
|
1292
|
-
dispatchAuthEvent(
|
|
1293
|
-
'signIn',
|
|
1294
|
-
internalUser,
|
|
1295
|
-
`A user ${internalUser.getUsername()} has been signed in`
|
|
1296
|
-
);
|
|
1297
|
-
}
|
|
1298
|
-
dispatchAuthEvent(
|
|
1299
|
-
'verify',
|
|
1300
|
-
internalUser,
|
|
1301
|
-
`A user ${internalUser.getUsername()} has been verified`
|
|
1302
|
-
);
|
|
1303
|
-
logger.debug('verifyTotpToken success', data);
|
|
1304
|
-
res(data);
|
|
1305
|
-
return;
|
|
1306
|
-
},
|
|
1307
|
-
},
|
|
1308
|
-
getAuthUserAgentValue(
|
|
1309
|
-
AuthAction.VerifyTotpToken,
|
|
1310
|
-
customUserAgentDetails
|
|
1311
|
-
)
|
|
1312
|
-
);
|
|
1313
|
-
});
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
/**
|
|
1317
|
-
* Send MFA code to confirm sign in
|
|
1318
|
-
* @param {Object} user - The CognitoUser object
|
|
1319
|
-
* @param {String} code - The confirmation code
|
|
1320
|
-
* @param {string} mfaType - optional mfaType: 'SMS_MFA' | 'SOFTWARE_TOKEN_MFA'
|
|
1321
|
-
* @param {ClientMetaData} clientMetadata - optional client metadata defaults to config
|
|
1322
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1323
|
-
*/
|
|
1324
|
-
public confirmSignIn(
|
|
1325
|
-
user: CognitoUser | any,
|
|
1326
|
-
code: string,
|
|
1327
|
-
mfaType?: 'SMS_MFA' | 'SOFTWARE_TOKEN_MFA' | null,
|
|
1328
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
1329
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1330
|
-
): Promise<CognitoUser | any> {
|
|
1331
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
1332
|
-
|
|
1333
|
-
if (!code) {
|
|
1334
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyCode);
|
|
1335
|
-
}
|
|
1336
|
-
|
|
1337
|
-
const that = this;
|
|
1338
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
1339
|
-
AuthAction.ConfirmSignIn,
|
|
1340
|
-
customUserAgentDetails
|
|
1341
|
-
);
|
|
1342
|
-
return new Promise((resolve, reject) => {
|
|
1343
|
-
internalUser.sendMFACode(
|
|
1344
|
-
code,
|
|
1345
|
-
{
|
|
1346
|
-
onSuccess: async session => {
|
|
1347
|
-
logger.debug(session);
|
|
1348
|
-
try {
|
|
1349
|
-
await this.Credentials.clear();
|
|
1350
|
-
const cred = await this.Credentials.set(session, 'session');
|
|
1351
|
-
logger.debug('succeed to get cognito credentials', cred);
|
|
1352
|
-
} catch (e) {
|
|
1353
|
-
logger.debug('cannot get cognito credentials', e);
|
|
1354
|
-
} finally {
|
|
1355
|
-
that.user = internalUser;
|
|
1356
|
-
try {
|
|
1357
|
-
const currentUser = await this._currentUserPoolUser(
|
|
1358
|
-
undefined,
|
|
1359
|
-
userAgentDetails
|
|
1360
|
-
);
|
|
1361
|
-
Object.assign(internalUser, {
|
|
1362
|
-
attributes: currentUser.attributes,
|
|
1363
|
-
});
|
|
1364
|
-
} catch (e) {
|
|
1365
|
-
logger.debug('cannot get updated Cognito User', e);
|
|
1366
|
-
}
|
|
1367
|
-
dispatchAuthEvent(
|
|
1368
|
-
'signIn',
|
|
1369
|
-
internalUser,
|
|
1370
|
-
`A user ${internalUser.getUsername()} has been signed in`
|
|
1371
|
-
);
|
|
1372
|
-
resolve(internalUser);
|
|
1373
|
-
}
|
|
1374
|
-
},
|
|
1375
|
-
onFailure: err => {
|
|
1376
|
-
logger.debug('confirm signIn failure', err);
|
|
1377
|
-
reject(err);
|
|
1378
|
-
},
|
|
1379
|
-
},
|
|
1380
|
-
mfaType,
|
|
1381
|
-
clientMetadata,
|
|
1382
|
-
getAmplifyUserAgent(userAgentDetails)
|
|
1383
|
-
);
|
|
1384
|
-
});
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
public completeNewPassword(
|
|
1388
|
-
user: CognitoUser | any,
|
|
1389
|
-
password: string,
|
|
1390
|
-
requiredAttributes: any = {},
|
|
1391
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
1392
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1393
|
-
): Promise<CognitoUser | any> {
|
|
1394
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
1395
|
-
|
|
1396
|
-
if (!password) {
|
|
1397
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyPassword);
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
const that = this;
|
|
1401
|
-
return new Promise((resolve, reject) => {
|
|
1402
|
-
internalUser.completeNewPasswordChallenge(
|
|
1403
|
-
password,
|
|
1404
|
-
requiredAttributes,
|
|
1405
|
-
{
|
|
1406
|
-
onSuccess: async session => {
|
|
1407
|
-
logger.debug(session);
|
|
1408
|
-
try {
|
|
1409
|
-
await this.Credentials.clear();
|
|
1410
|
-
const cred = await this.Credentials.set(session, 'session');
|
|
1411
|
-
logger.debug('succeed to get cognito credentials', cred);
|
|
1412
|
-
} catch (e) {
|
|
1413
|
-
logger.debug('cannot get cognito credentials', e);
|
|
1414
|
-
} finally {
|
|
1415
|
-
that.user = internalUser;
|
|
1416
|
-
dispatchAuthEvent(
|
|
1417
|
-
'signIn',
|
|
1418
|
-
internalUser,
|
|
1419
|
-
`A user ${internalUser.getUsername()} has been signed in`
|
|
1420
|
-
);
|
|
1421
|
-
resolve(internalUser);
|
|
1422
|
-
}
|
|
1423
|
-
},
|
|
1424
|
-
onFailure: err => {
|
|
1425
|
-
logger.debug('completeNewPassword failure', err);
|
|
1426
|
-
dispatchAuthEvent(
|
|
1427
|
-
'completeNewPassword_failure',
|
|
1428
|
-
err,
|
|
1429
|
-
`${this.user} failed to complete the new password flow`
|
|
1430
|
-
);
|
|
1431
|
-
reject(err);
|
|
1432
|
-
},
|
|
1433
|
-
mfaRequired: (challengeName, challengeParam) => {
|
|
1434
|
-
logger.debug('signIn MFA required');
|
|
1435
|
-
internalUser['challengeName'] = challengeName;
|
|
1436
|
-
internalUser['challengeParam'] = challengeParam;
|
|
1437
|
-
resolve(internalUser);
|
|
1438
|
-
},
|
|
1439
|
-
mfaSetup: (challengeName, challengeParam) => {
|
|
1440
|
-
logger.debug('signIn mfa setup', challengeName);
|
|
1441
|
-
internalUser['challengeName'] = challengeName;
|
|
1442
|
-
internalUser['challengeParam'] = challengeParam;
|
|
1443
|
-
resolve(internalUser);
|
|
1444
|
-
},
|
|
1445
|
-
totpRequired: (challengeName, challengeParam) => {
|
|
1446
|
-
logger.debug('signIn mfa setup', challengeName);
|
|
1447
|
-
internalUser['challengeName'] = challengeName;
|
|
1448
|
-
internalUser['challengeParam'] = challengeParam;
|
|
1449
|
-
resolve(internalUser);
|
|
1450
|
-
},
|
|
1451
|
-
},
|
|
1452
|
-
clientMetadata,
|
|
1453
|
-
getAuthUserAgentValue(
|
|
1454
|
-
AuthAction.CompleteNewPassword,
|
|
1455
|
-
customUserAgentDetails
|
|
1456
|
-
)
|
|
1457
|
-
);
|
|
1458
|
-
});
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
/**
|
|
1462
|
-
* Send the answer to a custom challenge
|
|
1463
|
-
* @param {CognitoUser} user - The CognitoUser object
|
|
1464
|
-
* @param {String} challengeResponses - The confirmation code
|
|
1465
|
-
* @param {ClientMetaData} clientMetadata - optional client metadata defaults to config
|
|
1466
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1467
|
-
*
|
|
1468
|
-
*/
|
|
1469
|
-
public sendCustomChallengeAnswer(
|
|
1470
|
-
user: CognitoUser | any,
|
|
1471
|
-
challengeResponses: string,
|
|
1472
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
1473
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1474
|
-
): Promise<CognitoUser | any> {
|
|
1475
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
1476
|
-
|
|
1477
|
-
if (!this.userPool) {
|
|
1478
|
-
return this.rejectNoUserPool();
|
|
1479
|
-
}
|
|
1480
|
-
if (!challengeResponses) {
|
|
1481
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyChallengeResponse);
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
const that = this;
|
|
1485
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
1486
|
-
AuthAction.SendCustomChallengeAnswer,
|
|
1487
|
-
customUserAgentDetails
|
|
1488
|
-
);
|
|
1489
|
-
return new Promise((resolve, reject) => {
|
|
1490
|
-
internalUser.sendCustomChallengeAnswer(
|
|
1491
|
-
challengeResponses,
|
|
1492
|
-
this.authCallbacks(internalUser, resolve, reject, userAgentDetails),
|
|
1493
|
-
clientMetadata,
|
|
1494
|
-
getAmplifyUserAgent(userAgentDetails)
|
|
1495
|
-
);
|
|
1496
|
-
});
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
/**
|
|
1500
|
-
* Delete an authenticated users' attributes
|
|
1501
|
-
* @param {CognitoUser} user - The currently logged in user object
|
|
1502
|
-
* @param {string[]} attributeNames - Attributes to delete
|
|
1503
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1504
|
-
* @return {Promise}
|
|
1505
|
-
**/
|
|
1506
|
-
public deleteUserAttributes(
|
|
1507
|
-
user: CognitoUser | any,
|
|
1508
|
-
attributeNames: string[],
|
|
1509
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1510
|
-
) {
|
|
1511
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
1512
|
-
const that = this;
|
|
1513
|
-
const userAgentValue = getAuthUserAgentValue(
|
|
1514
|
-
AuthAction.DeleteUserAttributes,
|
|
1515
|
-
customUserAgentDetails
|
|
1516
|
-
);
|
|
1517
|
-
return new Promise((resolve, reject) => {
|
|
1518
|
-
that._userSession(userAgentValue, internalUser).then(session => {
|
|
1519
|
-
internalUser.deleteAttributes(
|
|
1520
|
-
attributeNames,
|
|
1521
|
-
(err, result) => {
|
|
1522
|
-
if (err) {
|
|
1523
|
-
return reject(err);
|
|
1524
|
-
} else {
|
|
1525
|
-
return resolve(result);
|
|
1526
|
-
}
|
|
1527
|
-
},
|
|
1528
|
-
userAgentValue
|
|
1529
|
-
);
|
|
1530
|
-
});
|
|
1531
|
-
});
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
/**
|
|
1535
|
-
* Delete the current authenticated user
|
|
1536
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1537
|
-
* @return {Promise}
|
|
1538
|
-
**/
|
|
1539
|
-
// TODO: Check return type void
|
|
1540
|
-
public async deleteUser(
|
|
1541
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1542
|
-
): Promise<string | void> {
|
|
1543
|
-
try {
|
|
1544
|
-
await this._storageSync;
|
|
1545
|
-
} catch (e) {
|
|
1546
|
-
logger.debug('Failed to sync cache info into memory', e);
|
|
1547
|
-
throw new Error(e);
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
|
-
const isSignedInHostedUI =
|
|
1551
|
-
this._oAuthHandler &&
|
|
1552
|
-
this._storage.getItem('amplify-signin-with-hostedUI') === 'true';
|
|
1553
|
-
|
|
1554
|
-
return new Promise(async (res, rej) => {
|
|
1555
|
-
if (this.userPool) {
|
|
1556
|
-
const internalUser =
|
|
1557
|
-
this.userPool.getCurrentUser() as InternalCognitoUser;
|
|
1558
|
-
|
|
1559
|
-
if (!internalUser) {
|
|
1560
|
-
logger.debug('Failed to get user from user pool');
|
|
1561
|
-
return rej(new Error('No current user.'));
|
|
1562
|
-
} else {
|
|
1563
|
-
const userAgentValue = getAuthUserAgentValue(
|
|
1564
|
-
AuthAction.DeleteUser,
|
|
1565
|
-
customUserAgentDetails
|
|
1566
|
-
);
|
|
1567
|
-
internalUser.getSession(async (err, session) => {
|
|
1568
|
-
if (err) {
|
|
1569
|
-
logger.debug('Failed to get the user session', err);
|
|
1570
|
-
if (this.isSessionInvalid(err)) {
|
|
1571
|
-
try {
|
|
1572
|
-
await this.cleanUpInvalidSession(
|
|
1573
|
-
internalUser,
|
|
1574
|
-
userAgentValue
|
|
1575
|
-
);
|
|
1576
|
-
} catch (cleanUpError) {
|
|
1577
|
-
rej(
|
|
1578
|
-
new Error(
|
|
1579
|
-
`Session is invalid due to: ${err.message} and failed to clean up invalid session: ${cleanUpError.message}`
|
|
1580
|
-
)
|
|
1581
|
-
);
|
|
1582
|
-
return;
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
return rej(err);
|
|
1586
|
-
} else {
|
|
1587
|
-
internalUser.deleteUser(
|
|
1588
|
-
(err, result: string) => {
|
|
1589
|
-
if (err) {
|
|
1590
|
-
rej(err);
|
|
1591
|
-
} else {
|
|
1592
|
-
dispatchAuthEvent(
|
|
1593
|
-
'userDeleted',
|
|
1594
|
-
result,
|
|
1595
|
-
'The authenticated user has been deleted.'
|
|
1596
|
-
);
|
|
1597
|
-
internalUser.signOut(undefined, userAgentValue);
|
|
1598
|
-
this.user = null;
|
|
1599
|
-
try {
|
|
1600
|
-
this.cleanCachedItems(); // clean aws credentials
|
|
1601
|
-
} catch (e) {
|
|
1602
|
-
// TODO: change to rejects in refactor
|
|
1603
|
-
logger.debug('failed to clear cached items');
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
if (isSignedInHostedUI) {
|
|
1607
|
-
this.oAuthSignOutRedirect(res, rej);
|
|
1608
|
-
} else {
|
|
1609
|
-
dispatchAuthEvent(
|
|
1610
|
-
'signOut',
|
|
1611
|
-
this.user,
|
|
1612
|
-
`A user has been signed out`
|
|
1613
|
-
);
|
|
1614
|
-
res(result);
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
},
|
|
1618
|
-
undefined,
|
|
1619
|
-
userAgentValue
|
|
1620
|
-
);
|
|
1621
|
-
}
|
|
1622
|
-
});
|
|
1623
|
-
}
|
|
1624
|
-
} else {
|
|
1625
|
-
logger.debug('no Congito User pool');
|
|
1626
|
-
rej(new Error('Cognito User pool does not exist'));
|
|
1627
|
-
}
|
|
1628
|
-
});
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
|
-
/**
|
|
1632
|
-
* Update an authenticated users' attributes
|
|
1633
|
-
* @param {CognitoUser} user - The currently logged in user object
|
|
1634
|
-
* @param {object} attributes - attributes to update
|
|
1635
|
-
* @param {ClientMetaData} clientMetadata - optional client metadata, defaults to config
|
|
1636
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1637
|
-
* @return {Promise}
|
|
1638
|
-
**/
|
|
1639
|
-
public updateUserAttributes(
|
|
1640
|
-
user: CognitoUser | any,
|
|
1641
|
-
attributes: object,
|
|
1642
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
1643
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1644
|
-
): Promise<string> {
|
|
1645
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
1646
|
-
const attributeList: ICognitoUserAttributeData[] = [];
|
|
1647
|
-
const that = this;
|
|
1648
|
-
const userAgentValue = getAuthUserAgentValue(
|
|
1649
|
-
AuthAction.UpdateUserAttributes,
|
|
1650
|
-
customUserAgentDetails
|
|
1651
|
-
);
|
|
1652
|
-
return new Promise((resolve, reject) => {
|
|
1653
|
-
that._userSession(userAgentValue, internalUser).then(session => {
|
|
1654
|
-
for (const key in attributes) {
|
|
1655
|
-
if (key !== 'sub' && key.indexOf('_verified') < 0) {
|
|
1656
|
-
const attr: ICognitoUserAttributeData = {
|
|
1657
|
-
Name: key,
|
|
1658
|
-
Value: attributes[key],
|
|
1659
|
-
};
|
|
1660
|
-
attributeList.push(attr);
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
internalUser.updateAttributes(
|
|
1664
|
-
attributeList,
|
|
1665
|
-
(err, result, details) => {
|
|
1666
|
-
if (err) {
|
|
1667
|
-
dispatchAuthEvent(
|
|
1668
|
-
'updateUserAttributes_failure',
|
|
1669
|
-
err,
|
|
1670
|
-
'Failed to update attributes'
|
|
1671
|
-
);
|
|
1672
|
-
return reject(err);
|
|
1673
|
-
} else {
|
|
1674
|
-
const attrs = this.createUpdateAttributesResultList(
|
|
1675
|
-
attributes as Record<string, string>,
|
|
1676
|
-
details?.CodeDeliveryDetailsList
|
|
1677
|
-
);
|
|
1678
|
-
dispatchAuthEvent(
|
|
1679
|
-
'updateUserAttributes',
|
|
1680
|
-
attrs,
|
|
1681
|
-
'Attributes successfully updated'
|
|
1682
|
-
);
|
|
1683
|
-
return resolve(result);
|
|
1684
|
-
}
|
|
1685
|
-
},
|
|
1686
|
-
clientMetadata,
|
|
1687
|
-
userAgentValue
|
|
1688
|
-
);
|
|
1689
|
-
});
|
|
1690
|
-
});
|
|
1691
|
-
}
|
|
1692
|
-
|
|
1693
|
-
private createUpdateAttributesResultList(
|
|
1694
|
-
attributes: Record<string, string>,
|
|
1695
|
-
codeDeliveryDetailsList?: CodeDeliveryDetails[]
|
|
1696
|
-
): Record<string, string> {
|
|
1697
|
-
const attrs = {};
|
|
1698
|
-
Object.keys(attributes).forEach(key => {
|
|
1699
|
-
attrs[key] = {
|
|
1700
|
-
isUpdated: true,
|
|
1701
|
-
};
|
|
1702
|
-
const codeDeliveryDetails = codeDeliveryDetailsList?.find(
|
|
1703
|
-
value => value.AttributeName === key
|
|
1704
|
-
);
|
|
1705
|
-
if (codeDeliveryDetails) {
|
|
1706
|
-
attrs[key].isUpdated = false;
|
|
1707
|
-
attrs[key].codeDeliveryDetails = codeDeliveryDetails;
|
|
1708
|
-
}
|
|
1709
|
-
});
|
|
1710
|
-
return attrs;
|
|
1711
|
-
}
|
|
1712
|
-
|
|
1713
|
-
/**
|
|
1714
|
-
* Return user attributes
|
|
1715
|
-
* @param {Object} user - The CognitoUser object
|
|
1716
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1717
|
-
* @return - A promise resolves to user attributes if success
|
|
1718
|
-
*/
|
|
1719
|
-
public userAttributes(
|
|
1720
|
-
user: CognitoUser | any,
|
|
1721
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1722
|
-
): Promise<CognitoUserAttribute[]> {
|
|
1723
|
-
return this._userAttributes(user, customUserAgentDetails);
|
|
1724
|
-
}
|
|
1725
|
-
|
|
1726
|
-
private _userAttributes(
|
|
1727
|
-
user: CognitoUser | any,
|
|
1728
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1729
|
-
): Promise<CognitoUserAttribute[]> {
|
|
1730
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
1731
|
-
const userAgentValue = getAuthUserAgentValue(
|
|
1732
|
-
AuthAction.UserAttributes,
|
|
1733
|
-
customUserAgentDetails
|
|
1734
|
-
);
|
|
1735
|
-
return new Promise((resolve, reject) => {
|
|
1736
|
-
this._userSession(userAgentValue, internalUser).then(session => {
|
|
1737
|
-
internalUser.getUserAttributes((err, attributes) => {
|
|
1738
|
-
if (err) {
|
|
1739
|
-
reject(err);
|
|
1740
|
-
} else {
|
|
1741
|
-
resolve(attributes);
|
|
1742
|
-
}
|
|
1743
|
-
}, userAgentValue);
|
|
1744
|
-
});
|
|
1745
|
-
});
|
|
1746
|
-
}
|
|
1747
|
-
|
|
1748
|
-
public verifiedContact(
|
|
1749
|
-
user: CognitoUser | any,
|
|
1750
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1751
|
-
) {
|
|
1752
|
-
const that = this;
|
|
1753
|
-
return this._userAttributes(
|
|
1754
|
-
user,
|
|
1755
|
-
getAuthUserAgentDetails(
|
|
1756
|
-
AuthAction.VerifiedContact,
|
|
1757
|
-
customUserAgentDetails
|
|
1758
|
-
)
|
|
1759
|
-
).then(attributes => {
|
|
1760
|
-
const attrs = that.attributesToObject(attributes);
|
|
1761
|
-
const unverified = {};
|
|
1762
|
-
const verified = {};
|
|
1763
|
-
if (attrs['email']) {
|
|
1764
|
-
if (attrs['email_verified']) {
|
|
1765
|
-
verified['email'] = attrs['email'];
|
|
1766
|
-
} else {
|
|
1767
|
-
unverified['email'] = attrs['email'];
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
if (attrs['phone_number']) {
|
|
1771
|
-
if (attrs['phone_number_verified']) {
|
|
1772
|
-
verified['phone_number'] = attrs['phone_number'];
|
|
1773
|
-
} else {
|
|
1774
|
-
unverified['phone_number'] = attrs['phone_number'];
|
|
1775
|
-
}
|
|
1776
|
-
}
|
|
1777
|
-
return {
|
|
1778
|
-
verified,
|
|
1779
|
-
unverified,
|
|
1780
|
-
};
|
|
1781
|
-
});
|
|
1782
|
-
}
|
|
1783
|
-
|
|
1784
|
-
private isErrorWithMessage(err: any): err is { message: string } {
|
|
1785
|
-
return (
|
|
1786
|
-
typeof err === 'object' &&
|
|
1787
|
-
Object.prototype.hasOwnProperty.call(err, 'message')
|
|
1788
|
-
);
|
|
1789
|
-
}
|
|
1790
|
-
|
|
1791
|
-
// Session revoked by another app
|
|
1792
|
-
private isTokenRevokedError(
|
|
1793
|
-
err: any
|
|
1794
|
-
): err is { message: 'Access Token has been revoked' } {
|
|
1795
|
-
return (
|
|
1796
|
-
this.isErrorWithMessage(err) &&
|
|
1797
|
-
err.message === 'Access Token has been revoked'
|
|
1798
|
-
);
|
|
1799
|
-
}
|
|
1800
|
-
|
|
1801
|
-
private isRefreshTokenRevokedError(
|
|
1802
|
-
err: any
|
|
1803
|
-
): err is { message: 'Refresh Token has been revoked' } {
|
|
1804
|
-
return (
|
|
1805
|
-
this.isErrorWithMessage(err) &&
|
|
1806
|
-
err.message === 'Refresh Token has been revoked'
|
|
1807
|
-
);
|
|
1808
|
-
}
|
|
1809
|
-
|
|
1810
|
-
private isUserDisabledError(
|
|
1811
|
-
err: any
|
|
1812
|
-
): err is { message: 'User is disabled.' } {
|
|
1813
|
-
return this.isErrorWithMessage(err) && err.message === 'User is disabled.';
|
|
1814
|
-
}
|
|
1815
|
-
|
|
1816
|
-
private isUserDoesNotExistError(
|
|
1817
|
-
err: any
|
|
1818
|
-
): err is { message: 'User does not exist.' } {
|
|
1819
|
-
return (
|
|
1820
|
-
this.isErrorWithMessage(err) && err.message === 'User does not exist.'
|
|
1821
|
-
);
|
|
1822
|
-
}
|
|
1823
|
-
|
|
1824
|
-
private isRefreshTokenExpiredError(
|
|
1825
|
-
err: any
|
|
1826
|
-
): err is { message: 'Refresh Token has expired' } {
|
|
1827
|
-
return (
|
|
1828
|
-
this.isErrorWithMessage(err) &&
|
|
1829
|
-
err.message === 'Refresh Token has expired'
|
|
1830
|
-
);
|
|
1831
|
-
}
|
|
1832
|
-
|
|
1833
|
-
private isPasswordResetRequiredError(
|
|
1834
|
-
err: any
|
|
1835
|
-
): err is { message: 'Password reset required for the user' } {
|
|
1836
|
-
return (
|
|
1837
|
-
this.isErrorWithMessage(err) &&
|
|
1838
|
-
err.message === 'Password reset required for the user'
|
|
1839
|
-
);
|
|
1840
|
-
}
|
|
1841
|
-
|
|
1842
|
-
private isSignedInHostedUI() {
|
|
1843
|
-
return (
|
|
1844
|
-
this._oAuthHandler &&
|
|
1845
|
-
this._storage.getItem('amplify-signin-with-hostedUI') === 'true'
|
|
1846
|
-
);
|
|
1847
|
-
}
|
|
1848
|
-
|
|
1849
|
-
private isSessionInvalid(err: any) {
|
|
1850
|
-
return (
|
|
1851
|
-
this.isUserDisabledError(err) ||
|
|
1852
|
-
this.isUserDoesNotExistError(err) ||
|
|
1853
|
-
this.isTokenRevokedError(err) ||
|
|
1854
|
-
this.isRefreshTokenRevokedError(err) ||
|
|
1855
|
-
this.isRefreshTokenExpiredError(err) ||
|
|
1856
|
-
this.isPasswordResetRequiredError(err)
|
|
1857
|
-
);
|
|
1858
|
-
}
|
|
1859
|
-
|
|
1860
|
-
private async cleanUpInvalidSession(
|
|
1861
|
-
internalUser: InternalCognitoUser,
|
|
1862
|
-
userAgentValue: string
|
|
1863
|
-
) {
|
|
1864
|
-
internalUser.signOut(undefined, userAgentValue);
|
|
1865
|
-
this.user = null;
|
|
1866
|
-
try {
|
|
1867
|
-
await this.cleanCachedItems(); // clean aws credentials
|
|
1868
|
-
} catch (e) {
|
|
1869
|
-
logger.debug('failed to clear cached items');
|
|
1870
|
-
}
|
|
1871
|
-
if (this.isSignedInHostedUI()) {
|
|
1872
|
-
return new Promise((res, rej) => {
|
|
1873
|
-
this.oAuthSignOutRedirect(res, rej);
|
|
1874
|
-
});
|
|
1875
|
-
} else {
|
|
1876
|
-
dispatchAuthEvent('signOut', this.user, `A user has been signed out`);
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
/**
|
|
1881
|
-
* Get current authenticated user
|
|
1882
|
-
* @param {CurrentUserOpts} params - options for getting the current user
|
|
1883
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
1884
|
-
* @return - A promise resolves to current authenticated CognitoUser if success
|
|
1885
|
-
*/
|
|
1886
|
-
public currentUserPoolUser(
|
|
1887
|
-
params?: CurrentUserOpts,
|
|
1888
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1889
|
-
): Promise<CognitoUser | any> {
|
|
1890
|
-
return this._currentUserPoolUser(params, customUserAgentDetails);
|
|
1891
|
-
}
|
|
1892
|
-
|
|
1893
|
-
private _currentUserPoolUser(
|
|
1894
|
-
params?: CurrentUserOpts,
|
|
1895
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
1896
|
-
): Promise<CognitoUser | any> {
|
|
1897
|
-
if (!this.userPool) {
|
|
1898
|
-
return this.rejectNoUserPool();
|
|
1899
|
-
}
|
|
1900
|
-
|
|
1901
|
-
return new Promise((res, rej) => {
|
|
1902
|
-
this._storageSync
|
|
1903
|
-
.then(async () => {
|
|
1904
|
-
if (this.isOAuthInProgress()) {
|
|
1905
|
-
logger.debug('OAuth signIn in progress, waiting for resolution...');
|
|
1906
|
-
|
|
1907
|
-
await new Promise(res => {
|
|
1908
|
-
const timeoutId = setTimeout(() => {
|
|
1909
|
-
logger.debug('OAuth signIn in progress timeout');
|
|
1910
|
-
|
|
1911
|
-
Hub.remove('auth', hostedUISignCallback);
|
|
1912
|
-
|
|
1913
|
-
res();
|
|
1914
|
-
}, OAUTH_FLOW_MS_TIMEOUT);
|
|
1915
|
-
|
|
1916
|
-
Hub.listen('auth', hostedUISignCallback);
|
|
1917
|
-
|
|
1918
|
-
function hostedUISignCallback({ payload }) {
|
|
1919
|
-
const { event } = payload;
|
|
1920
|
-
|
|
1921
|
-
if (
|
|
1922
|
-
event === 'cognitoHostedUI' ||
|
|
1923
|
-
event === 'cognitoHostedUI_failure'
|
|
1924
|
-
) {
|
|
1925
|
-
logger.debug(`OAuth signIn resolved: ${event}`);
|
|
1926
|
-
clearTimeout(timeoutId);
|
|
1927
|
-
|
|
1928
|
-
Hub.remove('auth', hostedUISignCallback);
|
|
1929
|
-
|
|
1930
|
-
res();
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
});
|
|
1934
|
-
}
|
|
1935
|
-
|
|
1936
|
-
const internalUser =
|
|
1937
|
-
this.userPool.getCurrentUser() as InternalCognitoUser;
|
|
1938
|
-
|
|
1939
|
-
if (!internalUser) {
|
|
1940
|
-
logger.debug('Failed to get user from user pool');
|
|
1941
|
-
rej('No current user');
|
|
1942
|
-
return;
|
|
1943
|
-
}
|
|
1944
|
-
|
|
1945
|
-
// refresh the session if the session expired.
|
|
1946
|
-
try {
|
|
1947
|
-
const userAgentValue = getAuthUserAgentValue(
|
|
1948
|
-
AuthAction.CurrentUserPoolUser,
|
|
1949
|
-
customUserAgentDetails
|
|
1950
|
-
);
|
|
1951
|
-
const session = await this._userSession(
|
|
1952
|
-
userAgentValue,
|
|
1953
|
-
internalUser
|
|
1954
|
-
);
|
|
1955
|
-
|
|
1956
|
-
// get user data from Cognito
|
|
1957
|
-
const bypassCache = params ? params.bypassCache : false;
|
|
1958
|
-
|
|
1959
|
-
if (bypassCache) {
|
|
1960
|
-
await this.Credentials.clear();
|
|
1961
|
-
}
|
|
1962
|
-
|
|
1963
|
-
const clientMetadata = this._config.clientMetadata;
|
|
1964
|
-
|
|
1965
|
-
// validate the token's scope first before calling this function
|
|
1966
|
-
const { scope = '' } = session.getAccessToken().decodePayload();
|
|
1967
|
-
if (scope.split(' ').includes(USER_ADMIN_SCOPE)) {
|
|
1968
|
-
internalUser.getUserData(
|
|
1969
|
-
async (err, data) => {
|
|
1970
|
-
if (err) {
|
|
1971
|
-
logger.debug('getting user data failed', err);
|
|
1972
|
-
if (this.isSessionInvalid(err)) {
|
|
1973
|
-
try {
|
|
1974
|
-
await this.cleanUpInvalidSession(
|
|
1975
|
-
internalUser,
|
|
1976
|
-
userAgentValue
|
|
1977
|
-
);
|
|
1978
|
-
} catch (cleanUpError) {
|
|
1979
|
-
rej(
|
|
1980
|
-
new Error(
|
|
1981
|
-
`Session is invalid due to: ${err.message} and failed to clean up invalid session: ${cleanUpError.message}`
|
|
1982
|
-
)
|
|
1983
|
-
);
|
|
1984
|
-
return;
|
|
1985
|
-
}
|
|
1986
|
-
rej(err);
|
|
1987
|
-
} else {
|
|
1988
|
-
res(internalUser);
|
|
1989
|
-
}
|
|
1990
|
-
return;
|
|
1991
|
-
}
|
|
1992
|
-
const preferredMFA = data.PreferredMfaSetting || 'NOMFA';
|
|
1993
|
-
const attributeList: CognitoUserAttribute[] = [];
|
|
1994
|
-
|
|
1995
|
-
for (let i = 0; i < data.UserAttributes.length; i++) {
|
|
1996
|
-
const attribute = {
|
|
1997
|
-
Name: data.UserAttributes[i].Name,
|
|
1998
|
-
Value: data.UserAttributes[i].Value,
|
|
1999
|
-
};
|
|
2000
|
-
const userAttribute = new CognitoUserAttribute(attribute);
|
|
2001
|
-
attributeList.push(userAttribute);
|
|
2002
|
-
}
|
|
2003
|
-
|
|
2004
|
-
const attributes = this.attributesToObject(attributeList);
|
|
2005
|
-
Object.assign(internalUser, { attributes, preferredMFA });
|
|
2006
|
-
return res(internalUser);
|
|
2007
|
-
},
|
|
2008
|
-
{ bypassCache, clientMetadata },
|
|
2009
|
-
userAgentValue
|
|
2010
|
-
);
|
|
2011
|
-
} else {
|
|
2012
|
-
logger.debug(
|
|
2013
|
-
`Unable to get the user data because the ${USER_ADMIN_SCOPE} ` +
|
|
2014
|
-
`is not in the scopes of the access token`
|
|
2015
|
-
);
|
|
2016
|
-
return res(internalUser);
|
|
2017
|
-
}
|
|
2018
|
-
} catch (err) {
|
|
2019
|
-
rej(err);
|
|
2020
|
-
}
|
|
2021
|
-
})
|
|
2022
|
-
.catch(e => {
|
|
2023
|
-
logger.debug('Failed to sync cache info into memory', e);
|
|
2024
|
-
return rej(e);
|
|
2025
|
-
});
|
|
2026
|
-
});
|
|
2027
|
-
}
|
|
2028
|
-
|
|
2029
|
-
private isOAuthInProgress(): boolean {
|
|
2030
|
-
return this.oAuthFlowInProgress;
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
/**
|
|
2034
|
-
* Get current authenticated user
|
|
2035
|
-
* @param {CurrentUserOpts} - options for getting the current user
|
|
2036
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2037
|
-
* @return - A promise resolves to current authenticated CognitoUser if success
|
|
2038
|
-
*/
|
|
2039
|
-
public currentAuthenticatedUser(
|
|
2040
|
-
params?: CurrentUserOpts,
|
|
2041
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2042
|
-
): Promise<CognitoUser | any> {
|
|
2043
|
-
return this._currentAuthenticatedUser(params, customUserAgentDetails);
|
|
2044
|
-
}
|
|
2045
|
-
|
|
2046
|
-
private async _currentAuthenticatedUser(
|
|
2047
|
-
params?: CurrentUserOpts,
|
|
2048
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2049
|
-
): Promise<CognitoUser | any> {
|
|
2050
|
-
logger.debug('getting current authenticated user');
|
|
2051
|
-
let federatedUser = null;
|
|
2052
|
-
try {
|
|
2053
|
-
await this._storageSync;
|
|
2054
|
-
} catch (e) {
|
|
2055
|
-
logger.debug('Failed to sync cache info into memory', e);
|
|
2056
|
-
throw e;
|
|
2057
|
-
}
|
|
2058
|
-
|
|
2059
|
-
try {
|
|
2060
|
-
const federatedInfo = JSON.parse(
|
|
2061
|
-
this._storage.getItem('aws-amplify-federatedInfo')
|
|
2062
|
-
);
|
|
2063
|
-
if (federatedInfo) {
|
|
2064
|
-
federatedUser = {
|
|
2065
|
-
...federatedInfo.user,
|
|
2066
|
-
token: federatedInfo.token,
|
|
2067
|
-
};
|
|
2068
|
-
}
|
|
2069
|
-
} catch (e) {
|
|
2070
|
-
logger.debug('cannot load federated user from auth storage');
|
|
2071
|
-
}
|
|
2072
|
-
|
|
2073
|
-
if (federatedUser) {
|
|
2074
|
-
this.user = federatedUser;
|
|
2075
|
-
logger.debug('get current authenticated federated user', this.user);
|
|
2076
|
-
return this.user;
|
|
2077
|
-
} else {
|
|
2078
|
-
logger.debug('get current authenticated userpool user');
|
|
2079
|
-
let user = null;
|
|
2080
|
-
try {
|
|
2081
|
-
user = await this._currentUserPoolUser(
|
|
2082
|
-
params,
|
|
2083
|
-
getAuthUserAgentDetails(
|
|
2084
|
-
AuthAction.CurrentAuthenticatedUser,
|
|
2085
|
-
customUserAgentDetails
|
|
2086
|
-
)
|
|
2087
|
-
);
|
|
2088
|
-
} catch (e) {
|
|
2089
|
-
if (e === 'No userPool') {
|
|
2090
|
-
logger.error(
|
|
2091
|
-
'Cannot get the current user because the user pool is missing. ' +
|
|
2092
|
-
'Please make sure the Auth module is configured with a valid Cognito User Pool ID'
|
|
2093
|
-
);
|
|
2094
|
-
}
|
|
2095
|
-
logger.debug('The user is not authenticated by the error', e);
|
|
2096
|
-
return Promise.reject('The user is not authenticated');
|
|
2097
|
-
}
|
|
2098
|
-
this.user = user;
|
|
2099
|
-
return this.user;
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
2102
|
-
|
|
2103
|
-
/**
|
|
2104
|
-
* Get current user's session
|
|
2105
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2106
|
-
* @return - A promise resolves to session object if success
|
|
2107
|
-
*/
|
|
2108
|
-
public currentSession(
|
|
2109
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2110
|
-
): Promise<CognitoUserSession> {
|
|
2111
|
-
return this._currentSession(customUserAgentDetails);
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
private _currentSession(
|
|
2115
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2116
|
-
): Promise<CognitoUserSession> {
|
|
2117
|
-
const that = this;
|
|
2118
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
2119
|
-
AuthAction.CurrentSession,
|
|
2120
|
-
customUserAgentDetails
|
|
2121
|
-
);
|
|
2122
|
-
logger.debug('Getting current session');
|
|
2123
|
-
// Purposely not calling the reject method here because we don't need a console error
|
|
2124
|
-
if (!this.userPool) {
|
|
2125
|
-
return Promise.reject(new Error('No User Pool in the configuration.'));
|
|
2126
|
-
}
|
|
2127
|
-
|
|
2128
|
-
return new Promise((res, rej) => {
|
|
2129
|
-
that
|
|
2130
|
-
._currentUserPoolUser(undefined, userAgentDetails)
|
|
2131
|
-
.then(user => {
|
|
2132
|
-
that
|
|
2133
|
-
._userSession(getAmplifyUserAgent(userAgentDetails), user)
|
|
2134
|
-
.then(session => {
|
|
2135
|
-
res(session);
|
|
2136
|
-
return;
|
|
2137
|
-
})
|
|
2138
|
-
.catch(e => {
|
|
2139
|
-
logger.debug('Failed to get the current session', e);
|
|
2140
|
-
rej(e);
|
|
2141
|
-
return;
|
|
2142
|
-
});
|
|
2143
|
-
})
|
|
2144
|
-
.catch(e => {
|
|
2145
|
-
logger.debug('Failed to get the current user', e);
|
|
2146
|
-
rej(e);
|
|
2147
|
-
return;
|
|
2148
|
-
});
|
|
2149
|
-
});
|
|
2150
|
-
}
|
|
2151
|
-
|
|
2152
|
-
private async _userSession(
|
|
2153
|
-
userAgentValue: string,
|
|
2154
|
-
internalUser?: InternalCognitoUser
|
|
2155
|
-
): Promise<CognitoUserSession> {
|
|
2156
|
-
if (!internalUser) {
|
|
2157
|
-
logger.debug('the user is null');
|
|
2158
|
-
return this.rejectAuthError(AuthErrorTypes.NoUserSession);
|
|
2159
|
-
}
|
|
2160
|
-
const clientMetadata = this._config.clientMetadata;
|
|
2161
|
-
// Debouncing the concurrent userSession calls by caching the promise.
|
|
2162
|
-
// This solution assumes users will always call this function with the same CognitoUser instance.
|
|
2163
|
-
if (this.inflightSessionPromiseCounter === 0) {
|
|
2164
|
-
this.inflightSessionPromise = new Promise<CognitoUserSession>(
|
|
2165
|
-
(res, rej) => {
|
|
2166
|
-
internalUser.getSession(
|
|
2167
|
-
async (err, session) => {
|
|
2168
|
-
if (err) {
|
|
2169
|
-
logger.debug(
|
|
2170
|
-
'Failed to get the session from user',
|
|
2171
|
-
internalUser
|
|
2172
|
-
);
|
|
2173
|
-
if (this.isSessionInvalid(err)) {
|
|
2174
|
-
try {
|
|
2175
|
-
await this.cleanUpInvalidSession(
|
|
2176
|
-
internalUser,
|
|
2177
|
-
userAgentValue
|
|
2178
|
-
);
|
|
2179
|
-
} catch (cleanUpError) {
|
|
2180
|
-
rej(
|
|
2181
|
-
new Error(
|
|
2182
|
-
`Session is invalid due to: ${err.message} and failed to clean up invalid session: ${cleanUpError.message}`
|
|
2183
|
-
)
|
|
2184
|
-
);
|
|
2185
|
-
return;
|
|
2186
|
-
}
|
|
2187
|
-
}
|
|
2188
|
-
rej(err);
|
|
2189
|
-
return;
|
|
2190
|
-
} else {
|
|
2191
|
-
logger.debug('Succeed to get the user session', session);
|
|
2192
|
-
res(session);
|
|
2193
|
-
return;
|
|
2194
|
-
}
|
|
2195
|
-
},
|
|
2196
|
-
{ clientMetadata },
|
|
2197
|
-
userAgentValue
|
|
2198
|
-
);
|
|
2199
|
-
}
|
|
2200
|
-
);
|
|
2201
|
-
}
|
|
2202
|
-
this.inflightSessionPromiseCounter++;
|
|
2203
|
-
|
|
2204
|
-
try {
|
|
2205
|
-
const userSession = await this.inflightSessionPromise;
|
|
2206
|
-
// Set private member. Avoid user.setSignInUserSession() to prevent excessive localstorage refresh.
|
|
2207
|
-
// @ts-ignore
|
|
2208
|
-
internalUser.signInUserSession = userSession;
|
|
2209
|
-
return userSession!;
|
|
2210
|
-
} finally {
|
|
2211
|
-
this.inflightSessionPromiseCounter--;
|
|
2212
|
-
}
|
|
2213
|
-
}
|
|
2214
|
-
|
|
2215
|
-
/**
|
|
2216
|
-
* Get the corresponding user session
|
|
2217
|
-
* @param {Object} user - The CognitoUser object
|
|
2218
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2219
|
-
* @return - A promise resolves to the session
|
|
2220
|
-
*/
|
|
2221
|
-
public userSession(
|
|
2222
|
-
user,
|
|
2223
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2224
|
-
): Promise<CognitoUserSession> {
|
|
2225
|
-
return this._userSession(
|
|
2226
|
-
getAuthUserAgentValue(AuthAction.UserSession, customUserAgentDetails),
|
|
2227
|
-
user
|
|
2228
|
-
);
|
|
2229
|
-
}
|
|
2230
|
-
|
|
2231
|
-
/**
|
|
2232
|
-
* Get authenticated credentials of current user.
|
|
2233
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2234
|
-
* @return - A promise resolves to be current user's credentials
|
|
2235
|
-
*/
|
|
2236
|
-
public async currentUserCredentials(
|
|
2237
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2238
|
-
): Promise<ICredentials> {
|
|
2239
|
-
logger.debug('Getting current user credentials');
|
|
2240
|
-
|
|
2241
|
-
try {
|
|
2242
|
-
await this._storageSync;
|
|
2243
|
-
} catch (e) {
|
|
2244
|
-
logger.debug('Failed to sync cache info into memory', e);
|
|
2245
|
-
throw e;
|
|
2246
|
-
}
|
|
2247
|
-
|
|
2248
|
-
// first to check whether there is federation info in the auth storage
|
|
2249
|
-
let federatedInfo = null;
|
|
2250
|
-
try {
|
|
2251
|
-
federatedInfo = JSON.parse(
|
|
2252
|
-
this._storage.getItem('aws-amplify-federatedInfo')
|
|
2253
|
-
);
|
|
2254
|
-
} catch (e) {
|
|
2255
|
-
logger.debug('failed to get or parse item aws-amplify-federatedInfo', e);
|
|
2256
|
-
}
|
|
2257
|
-
|
|
2258
|
-
if (federatedInfo) {
|
|
2259
|
-
// refresh the jwt token here if necessary
|
|
2260
|
-
return this.Credentials.refreshFederatedToken(federatedInfo);
|
|
2261
|
-
} else {
|
|
2262
|
-
return this._currentSession(
|
|
2263
|
-
getAuthUserAgentDetails(
|
|
2264
|
-
AuthAction.CurrentUserCredentials,
|
|
2265
|
-
customUserAgentDetails
|
|
2266
|
-
)
|
|
2267
|
-
)
|
|
2268
|
-
.then(session => {
|
|
2269
|
-
logger.debug('getting session success', session);
|
|
2270
|
-
return this.Credentials.set(session, 'session');
|
|
2271
|
-
})
|
|
2272
|
-
.catch(() => {
|
|
2273
|
-
logger.debug('getting guest credentials');
|
|
2274
|
-
return this.Credentials.set(null, 'guest');
|
|
2275
|
-
});
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
|
|
2279
|
-
public currentCredentials(
|
|
2280
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2281
|
-
): Promise<ICredentials> {
|
|
2282
|
-
logger.debug('getting current credentials');
|
|
2283
|
-
return this.Credentials.get();
|
|
2284
|
-
}
|
|
2285
|
-
|
|
2286
|
-
/**
|
|
2287
|
-
* Initiate an attribute confirmation request
|
|
2288
|
-
* @param {Object} user - The CognitoUser
|
|
2289
|
-
* @param {Object} attr - The attributes to be verified
|
|
2290
|
-
* @param {ClientMetaData} clientMetadata - optional client metadata, defaults to config
|
|
2291
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2292
|
-
* @return - A promise resolves to callback data if success
|
|
2293
|
-
*/
|
|
2294
|
-
public verifyUserAttribute(
|
|
2295
|
-
user: CognitoUser | any,
|
|
2296
|
-
attr: string,
|
|
2297
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
2298
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2299
|
-
): Promise<void> {
|
|
2300
|
-
return this._verifyUserAttribute(
|
|
2301
|
-
user,
|
|
2302
|
-
attr,
|
|
2303
|
-
clientMetadata,
|
|
2304
|
-
customUserAgentDetails
|
|
2305
|
-
);
|
|
2306
|
-
}
|
|
2307
|
-
|
|
2308
|
-
private _verifyUserAttribute(
|
|
2309
|
-
user: CognitoUser | any,
|
|
2310
|
-
attr: string,
|
|
2311
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
2312
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2313
|
-
): Promise<void> {
|
|
2314
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
2315
|
-
|
|
2316
|
-
return new Promise((resolve, reject) => {
|
|
2317
|
-
internalUser.getAttributeVerificationCode(
|
|
2318
|
-
attr,
|
|
2319
|
-
{
|
|
2320
|
-
onSuccess(success) {
|
|
2321
|
-
return resolve(success);
|
|
2322
|
-
},
|
|
2323
|
-
onFailure(err) {
|
|
2324
|
-
return reject(err);
|
|
2325
|
-
},
|
|
2326
|
-
},
|
|
2327
|
-
clientMetadata,
|
|
2328
|
-
getAuthUserAgentValue(
|
|
2329
|
-
AuthAction.VerifyUserAttribute,
|
|
2330
|
-
customUserAgentDetails
|
|
2331
|
-
)
|
|
2332
|
-
);
|
|
2333
|
-
});
|
|
2334
|
-
}
|
|
2335
|
-
|
|
2336
|
-
/**
|
|
2337
|
-
* Confirm an attribute using a confirmation code
|
|
2338
|
-
* @param {Object} user - The CognitoUser
|
|
2339
|
-
* @param {Object} attr - The attribute to be verified
|
|
2340
|
-
* @param {String} code - The confirmation code
|
|
2341
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2342
|
-
* @return - A promise resolves to callback data if success
|
|
2343
|
-
*/
|
|
2344
|
-
public verifyUserAttributeSubmit(
|
|
2345
|
-
user: CognitoUser | any,
|
|
2346
|
-
attr: string,
|
|
2347
|
-
code: string,
|
|
2348
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2349
|
-
): Promise<string> {
|
|
2350
|
-
return this._verifyUserAttributeSubmit(
|
|
2351
|
-
user,
|
|
2352
|
-
attr,
|
|
2353
|
-
code,
|
|
2354
|
-
customUserAgentDetails
|
|
2355
|
-
);
|
|
2356
|
-
}
|
|
2357
|
-
|
|
2358
|
-
private _verifyUserAttributeSubmit(
|
|
2359
|
-
user: CognitoUser | any,
|
|
2360
|
-
attr: string,
|
|
2361
|
-
code: string,
|
|
2362
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2363
|
-
): Promise<string> {
|
|
2364
|
-
if (!code) {
|
|
2365
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyCode);
|
|
2366
|
-
}
|
|
2367
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
2368
|
-
|
|
2369
|
-
return new Promise((resolve, reject) => {
|
|
2370
|
-
internalUser.verifyAttribute(
|
|
2371
|
-
attr,
|
|
2372
|
-
code,
|
|
2373
|
-
{
|
|
2374
|
-
onSuccess(data) {
|
|
2375
|
-
resolve(data);
|
|
2376
|
-
return;
|
|
2377
|
-
},
|
|
2378
|
-
onFailure(err) {
|
|
2379
|
-
reject(err);
|
|
2380
|
-
return;
|
|
2381
|
-
},
|
|
2382
|
-
},
|
|
2383
|
-
getAuthUserAgentValue(
|
|
2384
|
-
AuthAction.VerifyUserAttributeSubmit,
|
|
2385
|
-
customUserAgentDetails
|
|
2386
|
-
)
|
|
2387
|
-
);
|
|
2388
|
-
});
|
|
2389
|
-
}
|
|
2390
|
-
|
|
2391
|
-
public verifyCurrentUserAttribute(
|
|
2392
|
-
attr: string,
|
|
2393
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2394
|
-
): Promise<void> {
|
|
2395
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
2396
|
-
AuthAction.VerifyCurrentUserAttribute,
|
|
2397
|
-
customUserAgentDetails
|
|
2398
|
-
);
|
|
2399
|
-
const that = this;
|
|
2400
|
-
return that
|
|
2401
|
-
._currentUserPoolUser(undefined, userAgentDetails)
|
|
2402
|
-
.then(user =>
|
|
2403
|
-
that._verifyUserAttribute(user, attr, undefined, userAgentDetails)
|
|
2404
|
-
);
|
|
2405
|
-
}
|
|
2406
|
-
|
|
2407
|
-
/**
|
|
2408
|
-
* Confirm current user's attribute using a confirmation code
|
|
2409
|
-
* @param {Object} attr - The attribute to be verified
|
|
2410
|
-
* @param {String} code - The confirmation code
|
|
2411
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2412
|
-
* @return - A promise resolves to callback data if success
|
|
2413
|
-
*/
|
|
2414
|
-
verifyCurrentUserAttributeSubmit(
|
|
2415
|
-
attr: string,
|
|
2416
|
-
code: string,
|
|
2417
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2418
|
-
): Promise<string> {
|
|
2419
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
2420
|
-
AuthAction.VerifyCurrentUserAttributeSubmit,
|
|
2421
|
-
customUserAgentDetails
|
|
2422
|
-
);
|
|
2423
|
-
const that = this;
|
|
2424
|
-
return that
|
|
2425
|
-
._currentUserPoolUser(undefined, userAgentDetails)
|
|
2426
|
-
.then(user =>
|
|
2427
|
-
that._verifyUserAttributeSubmit(user, attr, code, userAgentDetails)
|
|
2428
|
-
);
|
|
2429
|
-
}
|
|
2430
|
-
|
|
2431
|
-
private async cognitoIdentitySignOut(
|
|
2432
|
-
opts: SignOutOpts,
|
|
2433
|
-
internalUser: InternalCognitoUser | any,
|
|
2434
|
-
userAgentValue: string
|
|
2435
|
-
) {
|
|
2436
|
-
try {
|
|
2437
|
-
await this._storageSync;
|
|
2438
|
-
} catch (e) {
|
|
2439
|
-
logger.debug('Failed to sync cache info into memory', e);
|
|
2440
|
-
throw e;
|
|
2441
|
-
}
|
|
2442
|
-
|
|
2443
|
-
const isSignedInHostedUI =
|
|
2444
|
-
this._oAuthHandler &&
|
|
2445
|
-
this._storage.getItem('amplify-signin-with-hostedUI') === 'true';
|
|
2446
|
-
|
|
2447
|
-
return new Promise((res, rej) => {
|
|
2448
|
-
if (opts && opts.global) {
|
|
2449
|
-
logger.debug('user global sign out', internalUser);
|
|
2450
|
-
// in order to use global signout
|
|
2451
|
-
// we must validate the user as an authenticated user by using getSession
|
|
2452
|
-
const clientMetadata = this._config.clientMetadata; // TODO: verify behavior if this is override during signIn
|
|
2453
|
-
|
|
2454
|
-
internalUser.getSession(
|
|
2455
|
-
async (err, result) => {
|
|
2456
|
-
if (err) {
|
|
2457
|
-
logger.debug('failed to get the user session', err);
|
|
2458
|
-
if (this.isSessionInvalid(err)) {
|
|
2459
|
-
try {
|
|
2460
|
-
await this.cleanUpInvalidSession(
|
|
2461
|
-
internalUser,
|
|
2462
|
-
userAgentValue
|
|
2463
|
-
);
|
|
2464
|
-
} catch (cleanUpError) {
|
|
2465
|
-
rej(
|
|
2466
|
-
new Error(
|
|
2467
|
-
`Session is invalid due to: ${err.message} and failed to clean up invalid session: ${cleanUpError.message}`
|
|
2468
|
-
)
|
|
2469
|
-
);
|
|
2470
|
-
return;
|
|
2471
|
-
}
|
|
2472
|
-
}
|
|
2473
|
-
return rej(err);
|
|
2474
|
-
}
|
|
2475
|
-
internalUser.globalSignOut(
|
|
2476
|
-
{
|
|
2477
|
-
onSuccess: data => {
|
|
2478
|
-
logger.debug('global sign out success');
|
|
2479
|
-
if (isSignedInHostedUI) {
|
|
2480
|
-
this.oAuthSignOutRedirect(res, rej);
|
|
2481
|
-
} else {
|
|
2482
|
-
return res();
|
|
2483
|
-
}
|
|
2484
|
-
},
|
|
2485
|
-
onFailure: err => {
|
|
2486
|
-
logger.debug('global sign out failed', err);
|
|
2487
|
-
return rej(err);
|
|
2488
|
-
},
|
|
2489
|
-
},
|
|
2490
|
-
userAgentValue
|
|
2491
|
-
);
|
|
2492
|
-
},
|
|
2493
|
-
{ clientMetadata },
|
|
2494
|
-
userAgentValue
|
|
2495
|
-
);
|
|
2496
|
-
} else {
|
|
2497
|
-
logger.debug('user sign out', internalUser);
|
|
2498
|
-
internalUser.signOut(() => {
|
|
2499
|
-
if (isSignedInHostedUI) {
|
|
2500
|
-
this.oAuthSignOutRedirect(res, rej);
|
|
2501
|
-
} else {
|
|
2502
|
-
return res();
|
|
2503
|
-
}
|
|
2504
|
-
}, userAgentValue);
|
|
2505
|
-
}
|
|
2506
|
-
});
|
|
2507
|
-
}
|
|
2508
|
-
|
|
2509
|
-
private oAuthSignOutRedirect(
|
|
2510
|
-
resolve: () => void,
|
|
2511
|
-
reject: (reason?: any) => void
|
|
2512
|
-
) {
|
|
2513
|
-
const { isBrowser } = browserOrNode();
|
|
2514
|
-
|
|
2515
|
-
if (isBrowser) {
|
|
2516
|
-
this.oAuthSignOutRedirectOrReject(reject);
|
|
2517
|
-
} else {
|
|
2518
|
-
this.oAuthSignOutAndResolve(resolve);
|
|
2519
|
-
}
|
|
2520
|
-
}
|
|
2521
|
-
|
|
2522
|
-
private oAuthSignOutAndResolve(resolve: () => void) {
|
|
2523
|
-
this._oAuthHandler.signOut();
|
|
2524
|
-
resolve();
|
|
2525
|
-
}
|
|
2526
|
-
|
|
2527
|
-
private oAuthSignOutRedirectOrReject(reject: (reason?: any) => void) {
|
|
2528
|
-
this._oAuthHandler.signOut(); // this method redirects url
|
|
2529
|
-
|
|
2530
|
-
// App should be redirected to another url otherwise it will reject
|
|
2531
|
-
setTimeout(() => reject(Error('Signout timeout fail')), 3000);
|
|
2532
|
-
}
|
|
2533
|
-
|
|
2534
|
-
/**
|
|
2535
|
-
* Sign out method
|
|
2536
|
-
* @param {SignOutOpts} opts - options for sign out
|
|
2537
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2538
|
-
* @return - A promise resolved if success
|
|
2539
|
-
*/
|
|
2540
|
-
public async signOut(
|
|
2541
|
-
opts?: SignOutOpts,
|
|
2542
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2543
|
-
): Promise<any> {
|
|
2544
|
-
try {
|
|
2545
|
-
await this.cleanCachedItems();
|
|
2546
|
-
} catch (e) {
|
|
2547
|
-
logger.debug('failed to clear cached items');
|
|
2548
|
-
}
|
|
2549
|
-
|
|
2550
|
-
if (this.userPool) {
|
|
2551
|
-
const internalUser =
|
|
2552
|
-
this.userPool.getCurrentUser() as InternalCognitoUser;
|
|
2553
|
-
if (internalUser) {
|
|
2554
|
-
await this.cognitoIdentitySignOut(
|
|
2555
|
-
opts,
|
|
2556
|
-
internalUser,
|
|
2557
|
-
getAuthUserAgentValue(AuthAction.SignOut, customUserAgentDetails)
|
|
2558
|
-
);
|
|
2559
|
-
} else {
|
|
2560
|
-
logger.debug('no current Cognito user');
|
|
2561
|
-
}
|
|
2562
|
-
} else {
|
|
2563
|
-
logger.debug('no Cognito User pool');
|
|
2564
|
-
}
|
|
2565
|
-
|
|
2566
|
-
/**
|
|
2567
|
-
* Note for future refactor - no reliable way to get username with
|
|
2568
|
-
* Cognito User Pools vs Identity when federating with Social Providers
|
|
2569
|
-
* This is why we need a well structured session object that can be inspected
|
|
2570
|
-
* and information passed back in the message below for Hub dispatch
|
|
2571
|
-
*/
|
|
2572
|
-
dispatchAuthEvent('signOut', this.user, `A user has been signed out`);
|
|
2573
|
-
this.user = null;
|
|
2574
|
-
}
|
|
2575
|
-
|
|
2576
|
-
private async cleanCachedItems() {
|
|
2577
|
-
// clear cognito cached item
|
|
2578
|
-
await this.Credentials.clear();
|
|
2579
|
-
}
|
|
2580
|
-
|
|
2581
|
-
/**
|
|
2582
|
-
* Change a password for an authenticated user
|
|
2583
|
-
* @param {Object} user - The CognitoUser object
|
|
2584
|
-
* @param {String} oldPassword - the current password
|
|
2585
|
-
* @param {String} newPassword - the requested new password
|
|
2586
|
-
* @param {ClientMetaData} clientMetadata - optional client metadata, defaults to config
|
|
2587
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2588
|
-
* @return - A promise resolves if success
|
|
2589
|
-
*/
|
|
2590
|
-
public changePassword(
|
|
2591
|
-
user: CognitoUser | any,
|
|
2592
|
-
oldPassword: string,
|
|
2593
|
-
newPassword: string,
|
|
2594
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
2595
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2596
|
-
): Promise<'SUCCESS'> {
|
|
2597
|
-
const internalUser: InternalCognitoUser | any = user;
|
|
2598
|
-
const userAgentValue = getAuthUserAgentValue(
|
|
2599
|
-
AuthAction.ChangePassword,
|
|
2600
|
-
customUserAgentDetails
|
|
2601
|
-
);
|
|
2602
|
-
|
|
2603
|
-
return new Promise((resolve, reject) => {
|
|
2604
|
-
this._userSession(userAgentValue, internalUser).then(session => {
|
|
2605
|
-
internalUser.changePassword(
|
|
2606
|
-
oldPassword,
|
|
2607
|
-
newPassword,
|
|
2608
|
-
(err, data) => {
|
|
2609
|
-
if (err) {
|
|
2610
|
-
logger.debug('change password failure', err);
|
|
2611
|
-
return reject(err);
|
|
2612
|
-
} else {
|
|
2613
|
-
return resolve(data);
|
|
2614
|
-
}
|
|
2615
|
-
},
|
|
2616
|
-
clientMetadata,
|
|
2617
|
-
userAgentValue
|
|
2618
|
-
);
|
|
2619
|
-
});
|
|
2620
|
-
});
|
|
2621
|
-
}
|
|
2622
|
-
|
|
2623
|
-
/**
|
|
2624
|
-
* Initiate a forgot password request
|
|
2625
|
-
* @param {String} username - the username to change password
|
|
2626
|
-
* @param {ClientMetaData} clientMetadata - optional client metadata, defaults to config
|
|
2627
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2628
|
-
* @return - A promise resolves if success
|
|
2629
|
-
*/
|
|
2630
|
-
public forgotPassword(
|
|
2631
|
-
username: string,
|
|
2632
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
2633
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2634
|
-
): Promise<any> {
|
|
2635
|
-
if (!this.userPool) {
|
|
2636
|
-
return this.rejectNoUserPool();
|
|
2637
|
-
}
|
|
2638
|
-
if (!username) {
|
|
2639
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyUsername);
|
|
2640
|
-
}
|
|
2641
|
-
|
|
2642
|
-
const internalUser = this.createCognitoUser(username);
|
|
2643
|
-
return new Promise((resolve, reject) => {
|
|
2644
|
-
internalUser.forgotPassword(
|
|
2645
|
-
{
|
|
2646
|
-
onSuccess: () => {
|
|
2647
|
-
resolve();
|
|
2648
|
-
return;
|
|
2649
|
-
},
|
|
2650
|
-
onFailure: err => {
|
|
2651
|
-
logger.debug('forgot password failure', err);
|
|
2652
|
-
dispatchAuthEvent(
|
|
2653
|
-
'forgotPassword_failure',
|
|
2654
|
-
err,
|
|
2655
|
-
`${username} forgotPassword failed`
|
|
2656
|
-
);
|
|
2657
|
-
reject(err);
|
|
2658
|
-
return;
|
|
2659
|
-
},
|
|
2660
|
-
inputVerificationCode: data => {
|
|
2661
|
-
dispatchAuthEvent(
|
|
2662
|
-
'forgotPassword',
|
|
2663
|
-
internalUser,
|
|
2664
|
-
`${username} has initiated forgot password flow`
|
|
2665
|
-
);
|
|
2666
|
-
resolve(data);
|
|
2667
|
-
return;
|
|
2668
|
-
},
|
|
2669
|
-
},
|
|
2670
|
-
clientMetadata,
|
|
2671
|
-
getAuthUserAgentValue(AuthAction.ForgotPassword, customUserAgentDetails)
|
|
2672
|
-
);
|
|
2673
|
-
});
|
|
2674
|
-
}
|
|
2675
|
-
|
|
2676
|
-
/**
|
|
2677
|
-
* Confirm a new password using a confirmation Code
|
|
2678
|
-
* @param {String} username - The username
|
|
2679
|
-
* @param {String} code - The confirmation code
|
|
2680
|
-
* @param {String} password - The new password
|
|
2681
|
-
* @param {ClientMetaData} clientMetadata - optional client metadata, defaults to config
|
|
2682
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2683
|
-
* @return - A promise that resolves if success
|
|
2684
|
-
*/
|
|
2685
|
-
public forgotPasswordSubmit(
|
|
2686
|
-
username: string,
|
|
2687
|
-
code: string,
|
|
2688
|
-
password: string,
|
|
2689
|
-
clientMetadata: ClientMetaData = this._config.clientMetadata,
|
|
2690
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2691
|
-
): Promise<string> {
|
|
2692
|
-
if (!this.userPool) {
|
|
2693
|
-
return this.rejectNoUserPool();
|
|
2694
|
-
}
|
|
2695
|
-
if (!username) {
|
|
2696
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyUsername);
|
|
2697
|
-
}
|
|
2698
|
-
if (!code) {
|
|
2699
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyCode);
|
|
2700
|
-
}
|
|
2701
|
-
if (!password) {
|
|
2702
|
-
return this.rejectAuthError(AuthErrorTypes.EmptyPassword);
|
|
2703
|
-
}
|
|
2704
|
-
|
|
2705
|
-
const internalUser = this.createCognitoUser(username);
|
|
2706
|
-
return new Promise((resolve, reject) => {
|
|
2707
|
-
internalUser.confirmPassword(
|
|
2708
|
-
code,
|
|
2709
|
-
password,
|
|
2710
|
-
{
|
|
2711
|
-
onSuccess: success => {
|
|
2712
|
-
dispatchAuthEvent(
|
|
2713
|
-
'forgotPasswordSubmit',
|
|
2714
|
-
internalUser,
|
|
2715
|
-
`${username} forgotPasswordSubmit successful`
|
|
2716
|
-
);
|
|
2717
|
-
resolve(success);
|
|
2718
|
-
return;
|
|
2719
|
-
},
|
|
2720
|
-
onFailure: err => {
|
|
2721
|
-
dispatchAuthEvent(
|
|
2722
|
-
'forgotPasswordSubmit_failure',
|
|
2723
|
-
err,
|
|
2724
|
-
`${username} forgotPasswordSubmit failed`
|
|
2725
|
-
);
|
|
2726
|
-
reject(err);
|
|
2727
|
-
return;
|
|
2728
|
-
},
|
|
2729
|
-
},
|
|
2730
|
-
clientMetadata,
|
|
2731
|
-
getAuthUserAgentValue(
|
|
2732
|
-
AuthAction.ForgotPasswordSubmit,
|
|
2733
|
-
customUserAgentDetails
|
|
2734
|
-
)
|
|
2735
|
-
);
|
|
2736
|
-
});
|
|
2737
|
-
}
|
|
2738
|
-
|
|
2739
|
-
/**
|
|
2740
|
-
* Get user information
|
|
2741
|
-
* @async
|
|
2742
|
-
* @param {CustomUserAgentDetails} customUserAgentDetails - Optional parameter to send user agent details
|
|
2743
|
-
* @return {Object }- current User's information
|
|
2744
|
-
*/
|
|
2745
|
-
public async currentUserInfo(
|
|
2746
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2747
|
-
) {
|
|
2748
|
-
const source = this.Credentials.getCredSource();
|
|
2749
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
2750
|
-
AuthAction.CurrentUserInfo,
|
|
2751
|
-
customUserAgentDetails
|
|
2752
|
-
);
|
|
2753
|
-
|
|
2754
|
-
if (!source || source === 'aws' || source === 'userPool') {
|
|
2755
|
-
const internalUser: InternalCognitoUser = await this._currentUserPoolUser(
|
|
2756
|
-
undefined,
|
|
2757
|
-
userAgentDetails
|
|
2758
|
-
).catch(err => logger.error(err));
|
|
2759
|
-
if (!internalUser) {
|
|
2760
|
-
return null;
|
|
2761
|
-
}
|
|
2762
|
-
|
|
2763
|
-
try {
|
|
2764
|
-
const attributes = await this._userAttributes(
|
|
2765
|
-
internalUser,
|
|
2766
|
-
userAgentDetails
|
|
2767
|
-
);
|
|
2768
|
-
const userAttrs: object = this.attributesToObject(attributes);
|
|
2769
|
-
let credentials = null;
|
|
2770
|
-
try {
|
|
2771
|
-
credentials = await this.currentCredentials();
|
|
2772
|
-
} catch (e) {
|
|
2773
|
-
logger.debug(
|
|
2774
|
-
'Failed to retrieve credentials while getting current user info',
|
|
2775
|
-
e
|
|
2776
|
-
);
|
|
2777
|
-
}
|
|
2778
|
-
|
|
2779
|
-
const info = {
|
|
2780
|
-
id: credentials ? credentials.identityId : undefined,
|
|
2781
|
-
username: internalUser.getUsername(),
|
|
2782
|
-
attributes: userAttrs,
|
|
2783
|
-
};
|
|
2784
|
-
return info;
|
|
2785
|
-
} catch (err) {
|
|
2786
|
-
logger.error('currentUserInfo error', err);
|
|
2787
|
-
return {};
|
|
2788
|
-
}
|
|
2789
|
-
}
|
|
2790
|
-
|
|
2791
|
-
if (source === 'federated') {
|
|
2792
|
-
const user = this.user;
|
|
2793
|
-
return user ? user : {};
|
|
2794
|
-
}
|
|
2795
|
-
}
|
|
2796
|
-
|
|
2797
|
-
public async federatedSignIn(
|
|
2798
|
-
providerOrOptions:
|
|
2799
|
-
| LegacyProvider
|
|
2800
|
-
| FederatedSignInOptions
|
|
2801
|
-
| FederatedSignInOptionsCustom,
|
|
2802
|
-
response?: FederatedResponse,
|
|
2803
|
-
user?: FederatedUser,
|
|
2804
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
2805
|
-
): Promise<ICredentials> {
|
|
2806
|
-
if (!this._config.identityPoolId && !this._config.userPoolId) {
|
|
2807
|
-
throw new Error(
|
|
2808
|
-
`Federation requires either a User Pool or Identity Pool in config`
|
|
2809
|
-
);
|
|
2810
|
-
}
|
|
2811
|
-
|
|
2812
|
-
// Ensure backwards compatability
|
|
2813
|
-
if (typeof providerOrOptions === 'undefined') {
|
|
2814
|
-
if (this._config.identityPoolId && !this._config.userPoolId) {
|
|
2815
|
-
throw new Error(
|
|
2816
|
-
`Federation with Identity Pools requires tokens passed as arguments`
|
|
2817
|
-
);
|
|
2818
|
-
}
|
|
2819
|
-
}
|
|
2820
|
-
|
|
2821
|
-
if (
|
|
2822
|
-
isFederatedSignInOptions(providerOrOptions) ||
|
|
2823
|
-
isFederatedSignInOptionsCustom(providerOrOptions) ||
|
|
2824
|
-
hasCustomState(providerOrOptions) ||
|
|
2825
|
-
typeof providerOrOptions === 'undefined'
|
|
2826
|
-
) {
|
|
2827
|
-
const options = providerOrOptions || {
|
|
2828
|
-
provider: CognitoHostedUIIdentityProvider.Cognito,
|
|
2829
|
-
};
|
|
2830
|
-
const provider = isFederatedSignInOptions(options)
|
|
2831
|
-
? options.provider
|
|
2832
|
-
: (options as FederatedSignInOptionsCustom).customProvider;
|
|
2833
|
-
|
|
2834
|
-
const customState = isFederatedSignInOptions(options)
|
|
2835
|
-
? options.customState
|
|
2836
|
-
: (options as FederatedSignInOptionsCustom).customState;
|
|
2837
|
-
|
|
2838
|
-
if (this._config.userPoolId) {
|
|
2839
|
-
const client_id = isCognitoHostedOpts(this._config.oauth)
|
|
2840
|
-
? this._config.userPoolWebClientId
|
|
2841
|
-
: this._config.oauth.clientID;
|
|
2842
|
-
/*Note: Invenstigate automatically adding trailing slash */
|
|
2843
|
-
const redirect_uri = isCognitoHostedOpts(this._config.oauth)
|
|
2844
|
-
? this._config.oauth.redirectSignIn
|
|
2845
|
-
: this._config.oauth.redirectUri;
|
|
2846
|
-
|
|
2847
|
-
this._storage.setItem(
|
|
2848
|
-
'aws-amplify-federatedUserAgent',
|
|
2849
|
-
getAuthUserAgentValue(
|
|
2850
|
-
AuthAction.FederatedSignIn,
|
|
2851
|
-
customUserAgentDetails
|
|
2852
|
-
)
|
|
2853
|
-
);
|
|
2854
|
-
|
|
2855
|
-
this._oAuthHandler.oauthSignIn(
|
|
2856
|
-
this._config.oauth.responseType,
|
|
2857
|
-
this._config.oauth.domain,
|
|
2858
|
-
redirect_uri,
|
|
2859
|
-
client_id,
|
|
2860
|
-
provider,
|
|
2861
|
-
customState
|
|
2862
|
-
);
|
|
2863
|
-
}
|
|
2864
|
-
} else {
|
|
2865
|
-
const provider = providerOrOptions;
|
|
2866
|
-
// To check if the user is already logged in
|
|
2867
|
-
try {
|
|
2868
|
-
const loggedInUser = JSON.stringify(
|
|
2869
|
-
JSON.parse(this._storage.getItem('aws-amplify-federatedInfo')).user
|
|
2870
|
-
);
|
|
2871
|
-
if (loggedInUser) {
|
|
2872
|
-
logger.warn(`There is already a signed in user: ${loggedInUser} in your app.
|
|
2873
|
-
You should not call Auth.federatedSignIn method again as it may cause unexpected behavior.`);
|
|
2874
|
-
}
|
|
2875
|
-
} catch (e) {}
|
|
2876
|
-
|
|
2877
|
-
const { token, identity_id, expires_at } = response;
|
|
2878
|
-
// Because this.Credentials.set would update the user info with identity id
|
|
2879
|
-
// So we need to retrieve the user again.
|
|
2880
|
-
const credentials = await this.Credentials.set(
|
|
2881
|
-
{ provider, token, identity_id, user, expires_at },
|
|
2882
|
-
'federation'
|
|
2883
|
-
);
|
|
2884
|
-
const currentUser = await this._currentAuthenticatedUser();
|
|
2885
|
-
dispatchAuthEvent(
|
|
2886
|
-
'signIn',
|
|
2887
|
-
currentUser,
|
|
2888
|
-
`A user ${currentUser.username} has been signed in`
|
|
2889
|
-
);
|
|
2890
|
-
logger.debug('federated sign in credentials', credentials);
|
|
2891
|
-
return credentials;
|
|
2892
|
-
}
|
|
2893
|
-
}
|
|
2894
|
-
|
|
2895
|
-
/**
|
|
2896
|
-
* Used to complete the OAuth flow with or without the Cognito Hosted UI
|
|
2897
|
-
* @param {String} URL - optional parameter for customers to pass in the response URL
|
|
2898
|
-
*/
|
|
2899
|
-
private async _handleAuthResponse(URL?: string) {
|
|
2900
|
-
if (this.oAuthFlowInProgress) {
|
|
2901
|
-
logger.debug(`Skipping URL ${URL} current flow in progress`);
|
|
2902
|
-
return;
|
|
2903
|
-
}
|
|
2904
|
-
|
|
2905
|
-
try {
|
|
2906
|
-
this.oAuthFlowInProgress = true;
|
|
2907
|
-
if (!this._config.userPoolId) {
|
|
2908
|
-
throw new Error(
|
|
2909
|
-
`OAuth responses require a User Pool defined in config`
|
|
2910
|
-
);
|
|
2911
|
-
}
|
|
2912
|
-
|
|
2913
|
-
dispatchAuthEvent(
|
|
2914
|
-
'parsingCallbackUrl',
|
|
2915
|
-
{ url: URL },
|
|
2916
|
-
`The callback url is being parsed`
|
|
2917
|
-
);
|
|
2918
|
-
|
|
2919
|
-
const currentUrl =
|
|
2920
|
-
URL || (browserOrNode().isBrowser ? window.location.href : '');
|
|
2921
|
-
|
|
2922
|
-
const hasCodeOrError = !!(parse(currentUrl).query || '')
|
|
2923
|
-
.split('&')
|
|
2924
|
-
.map(entry => entry.split('='))
|
|
2925
|
-
.find(([k]) => k === 'code' || k === 'error');
|
|
2926
|
-
|
|
2927
|
-
const hasTokenOrError = !!(parse(currentUrl).hash || '#')
|
|
2928
|
-
.substr(1)
|
|
2929
|
-
.split('&')
|
|
2930
|
-
.map(entry => entry.split('='))
|
|
2931
|
-
.find(([k]) => k === 'access_token' || k === 'error');
|
|
2932
|
-
|
|
2933
|
-
if (hasCodeOrError || hasTokenOrError) {
|
|
2934
|
-
this._storage.setItem('amplify-redirected-from-hosted-ui', 'true');
|
|
2935
|
-
const userAgentValue =
|
|
2936
|
-
this._storage.getItem('aws-amplify-federatedUserAgent') || undefined;
|
|
2937
|
-
this._storage.removeItem('aws-amplify-federatedUserAgent');
|
|
2938
|
-
try {
|
|
2939
|
-
const { accessToken, idToken, refreshToken, state } =
|
|
2940
|
-
await this._oAuthHandler.handleAuthResponse(
|
|
2941
|
-
currentUrl,
|
|
2942
|
-
userAgentValue
|
|
2943
|
-
);
|
|
2944
|
-
const session = new CognitoUserSession({
|
|
2945
|
-
IdToken: new CognitoIdToken({ IdToken: idToken }),
|
|
2946
|
-
RefreshToken: new CognitoRefreshToken({
|
|
2947
|
-
RefreshToken: refreshToken,
|
|
2948
|
-
}),
|
|
2949
|
-
AccessToken: new CognitoAccessToken({
|
|
2950
|
-
AccessToken: accessToken,
|
|
2951
|
-
}),
|
|
2952
|
-
});
|
|
2953
|
-
|
|
2954
|
-
let credentials;
|
|
2955
|
-
// Get AWS Credentials & store if Identity Pool is defined
|
|
2956
|
-
if (this._config.identityPoolId) {
|
|
2957
|
-
credentials = await this.Credentials.set(session, 'session');
|
|
2958
|
-
logger.debug('AWS credentials', credentials);
|
|
2959
|
-
}
|
|
2960
|
-
|
|
2961
|
-
/*
|
|
2962
|
-
Prior to the request we do sign the custom state along with the state we set. This check will verify
|
|
2963
|
-
if there is a dash indicated when setting custom state from the request. If a dash is contained
|
|
2964
|
-
then there is custom state present on the state string.
|
|
2965
|
-
*/
|
|
2966
|
-
const isCustomStateIncluded = /-/.test(state);
|
|
2967
|
-
|
|
2968
|
-
/*
|
|
2969
|
-
The following is to create a user for the Cognito Identity SDK to store the tokens
|
|
2970
|
-
When we remove this SDK later that logic will have to be centralized in our new version
|
|
2971
|
-
*/
|
|
2972
|
-
//#region
|
|
2973
|
-
const currentUser = this.createCognitoUser(
|
|
2974
|
-
session.getIdToken().decodePayload()['cognito:username']
|
|
2975
|
-
);
|
|
2976
|
-
|
|
2977
|
-
// This calls cacheTokens() in Cognito SDK
|
|
2978
|
-
currentUser.setSignInUserSession(session);
|
|
2979
|
-
|
|
2980
|
-
if (window && typeof window.history !== 'undefined') {
|
|
2981
|
-
window.history.replaceState(
|
|
2982
|
-
{},
|
|
2983
|
-
null,
|
|
2984
|
-
(this._config.oauth as AwsCognitoOAuthOpts).redirectSignIn
|
|
2985
|
-
);
|
|
2986
|
-
}
|
|
2987
|
-
|
|
2988
|
-
dispatchAuthEvent(
|
|
2989
|
-
'signIn',
|
|
2990
|
-
currentUser,
|
|
2991
|
-
`A user ${currentUser.getUsername()} has been signed in`
|
|
2992
|
-
);
|
|
2993
|
-
dispatchAuthEvent(
|
|
2994
|
-
'cognitoHostedUI',
|
|
2995
|
-
currentUser,
|
|
2996
|
-
`A user ${currentUser.getUsername()} has been signed in via Cognito Hosted UI`
|
|
2997
|
-
);
|
|
2998
|
-
|
|
2999
|
-
if (isCustomStateIncluded) {
|
|
3000
|
-
const customState = state.split('-').splice(1).join('-');
|
|
3001
|
-
|
|
3002
|
-
dispatchAuthEvent(
|
|
3003
|
-
'customOAuthState',
|
|
3004
|
-
urlSafeDecode(customState),
|
|
3005
|
-
`State for user ${currentUser.getUsername()}`
|
|
3006
|
-
);
|
|
3007
|
-
}
|
|
3008
|
-
//#endregion
|
|
3009
|
-
|
|
3010
|
-
return credentials;
|
|
3011
|
-
} catch (err) {
|
|
3012
|
-
logger.debug('Error in cognito hosted auth response', err);
|
|
3013
|
-
|
|
3014
|
-
// Just like a successful handling of `?code`, replace the window history to "dispose" of the `code`.
|
|
3015
|
-
// Otherwise, reloading the page will throw errors as the `code` has already been spent.
|
|
3016
|
-
if (window && typeof window.history !== 'undefined') {
|
|
3017
|
-
window.history.replaceState(
|
|
3018
|
-
{},
|
|
3019
|
-
null,
|
|
3020
|
-
(this._config.oauth as AwsCognitoOAuthOpts).redirectSignIn
|
|
3021
|
-
);
|
|
3022
|
-
}
|
|
3023
|
-
|
|
3024
|
-
dispatchAuthEvent(
|
|
3025
|
-
'signIn_failure',
|
|
3026
|
-
err,
|
|
3027
|
-
`The OAuth response flow failed`
|
|
3028
|
-
);
|
|
3029
|
-
dispatchAuthEvent(
|
|
3030
|
-
'cognitoHostedUI_failure',
|
|
3031
|
-
err,
|
|
3032
|
-
`A failure occurred when returning to the Cognito Hosted UI`
|
|
3033
|
-
);
|
|
3034
|
-
dispatchAuthEvent(
|
|
3035
|
-
'customState_failure',
|
|
3036
|
-
err,
|
|
3037
|
-
`A failure occurred when returning state`
|
|
3038
|
-
);
|
|
3039
|
-
}
|
|
3040
|
-
}
|
|
3041
|
-
} finally {
|
|
3042
|
-
this.oAuthFlowInProgress = false;
|
|
3043
|
-
}
|
|
3044
|
-
}
|
|
3045
|
-
|
|
3046
|
-
/**
|
|
3047
|
-
* Compact version of credentials
|
|
3048
|
-
* @param {Object} credentials
|
|
3049
|
-
* @return {Object} - Credentials
|
|
3050
|
-
*/
|
|
3051
|
-
public essentialCredentials(credentials): ICredentials {
|
|
3052
|
-
return {
|
|
3053
|
-
accessKeyId: credentials.accessKeyId,
|
|
3054
|
-
sessionToken: credentials.sessionToken,
|
|
3055
|
-
secretAccessKey: credentials.secretAccessKey,
|
|
3056
|
-
identityId: credentials.identityId,
|
|
3057
|
-
authenticated: credentials.authenticated,
|
|
3058
|
-
};
|
|
3059
|
-
}
|
|
3060
|
-
|
|
3061
|
-
private attributesToObject(attributes) {
|
|
3062
|
-
const obj = {};
|
|
3063
|
-
if (attributes) {
|
|
3064
|
-
attributes.map(attribute => {
|
|
3065
|
-
if (
|
|
3066
|
-
attribute.Name === 'email_verified' ||
|
|
3067
|
-
attribute.Name === 'phone_number_verified'
|
|
3068
|
-
) {
|
|
3069
|
-
obj[attribute.Name] =
|
|
3070
|
-
this.isTruthyString(attribute.Value) || attribute.Value === true;
|
|
3071
|
-
} else {
|
|
3072
|
-
obj[attribute.Name] = attribute.Value;
|
|
3073
|
-
}
|
|
3074
|
-
});
|
|
3075
|
-
}
|
|
3076
|
-
return obj;
|
|
3077
|
-
}
|
|
3078
|
-
|
|
3079
|
-
private isTruthyString(value: any): boolean {
|
|
3080
|
-
return (
|
|
3081
|
-
typeof value.toLowerCase === 'function' && value.toLowerCase() === 'true'
|
|
3082
|
-
);
|
|
3083
|
-
}
|
|
3084
|
-
|
|
3085
|
-
private createCognitoUser(username: string): InternalCognitoUser {
|
|
3086
|
-
const userData: ICognitoUserData = {
|
|
3087
|
-
Username: username,
|
|
3088
|
-
Pool: this.userPool,
|
|
3089
|
-
};
|
|
3090
|
-
userData.Storage = this._storage;
|
|
3091
|
-
|
|
3092
|
-
const { authenticationFlowType } = this._config;
|
|
3093
|
-
|
|
3094
|
-
const internalUser = new InternalCognitoUser(userData);
|
|
3095
|
-
if (authenticationFlowType) {
|
|
3096
|
-
internalUser.setAuthenticationFlowType(authenticationFlowType);
|
|
3097
|
-
}
|
|
3098
|
-
return internalUser;
|
|
3099
|
-
}
|
|
3100
|
-
|
|
3101
|
-
private _isValidAuthStorage(obj) {
|
|
3102
|
-
// We need to check if the obj has the functions of Storage
|
|
3103
|
-
return (
|
|
3104
|
-
!!obj &&
|
|
3105
|
-
typeof obj.getItem === 'function' &&
|
|
3106
|
-
typeof obj.setItem === 'function' &&
|
|
3107
|
-
typeof obj.removeItem === 'function' &&
|
|
3108
|
-
typeof obj.clear === 'function'
|
|
3109
|
-
);
|
|
3110
|
-
}
|
|
3111
|
-
|
|
3112
|
-
private noUserPoolErrorHandler(config: AuthOptions): AuthErrorTypes {
|
|
3113
|
-
if (config) {
|
|
3114
|
-
if (!config.userPoolId || !config.identityPoolId) {
|
|
3115
|
-
return AuthErrorTypes.MissingAuthConfig;
|
|
3116
|
-
}
|
|
3117
|
-
}
|
|
3118
|
-
return AuthErrorTypes.NoConfig;
|
|
3119
|
-
}
|
|
3120
|
-
|
|
3121
|
-
private rejectAuthError(type: AuthErrorTypes): Promise<never> {
|
|
3122
|
-
return Promise.reject(new AuthError(type));
|
|
3123
|
-
}
|
|
3124
|
-
|
|
3125
|
-
private rejectNoUserPool(): Promise<never> {
|
|
3126
|
-
const type = this.noUserPoolErrorHandler(this._config);
|
|
3127
|
-
return Promise.reject(new NoUserPoolError(type));
|
|
3128
|
-
}
|
|
3129
|
-
|
|
3130
|
-
public async rememberDevice(
|
|
3131
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
3132
|
-
): Promise<string | AuthError> {
|
|
3133
|
-
let internalUser: InternalCognitoUser | any;
|
|
3134
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
3135
|
-
AuthAction.RememberDevice,
|
|
3136
|
-
customUserAgentDetails
|
|
3137
|
-
);
|
|
3138
|
-
|
|
3139
|
-
try {
|
|
3140
|
-
internalUser = await this._currentUserPoolUser(
|
|
3141
|
-
undefined,
|
|
3142
|
-
userAgentDetails
|
|
3143
|
-
);
|
|
3144
|
-
} catch (error) {
|
|
3145
|
-
logger.debug('The user is not authenticated by the error', error);
|
|
3146
|
-
return Promise.reject('The user is not authenticated');
|
|
3147
|
-
}
|
|
3148
|
-
|
|
3149
|
-
internalUser.getCachedDeviceKeyAndPassword();
|
|
3150
|
-
return new Promise((res, rej) => {
|
|
3151
|
-
internalUser.setDeviceStatusRemembered(
|
|
3152
|
-
{
|
|
3153
|
-
onSuccess: data => {
|
|
3154
|
-
res(data);
|
|
3155
|
-
},
|
|
3156
|
-
onFailure: err => {
|
|
3157
|
-
if (err.code === 'InvalidParameterException') {
|
|
3158
|
-
rej(new AuthError(AuthErrorTypes.DeviceConfig));
|
|
3159
|
-
} else if (err.code === 'NetworkError') {
|
|
3160
|
-
rej(new AuthError(AuthErrorTypes.NetworkError));
|
|
3161
|
-
} else {
|
|
3162
|
-
rej(err);
|
|
3163
|
-
}
|
|
3164
|
-
},
|
|
3165
|
-
},
|
|
3166
|
-
getAmplifyUserAgent(userAgentDetails)
|
|
3167
|
-
);
|
|
3168
|
-
});
|
|
3169
|
-
}
|
|
3170
|
-
|
|
3171
|
-
public async forgetDevice(
|
|
3172
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
3173
|
-
): Promise<void> {
|
|
3174
|
-
let internalUser: InternalCognitoUser | any;
|
|
3175
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
3176
|
-
AuthAction.ForgetDevice,
|
|
3177
|
-
customUserAgentDetails
|
|
3178
|
-
);
|
|
3179
|
-
|
|
3180
|
-
try {
|
|
3181
|
-
internalUser = await this._currentUserPoolUser(
|
|
3182
|
-
undefined,
|
|
3183
|
-
userAgentDetails
|
|
3184
|
-
);
|
|
3185
|
-
} catch (error) {
|
|
3186
|
-
logger.debug('The user is not authenticated by the error', error);
|
|
3187
|
-
return Promise.reject('The user is not authenticated');
|
|
3188
|
-
}
|
|
3189
|
-
|
|
3190
|
-
internalUser.getCachedDeviceKeyAndPassword();
|
|
3191
|
-
return new Promise((res, rej) => {
|
|
3192
|
-
internalUser.forgetDevice(
|
|
3193
|
-
{
|
|
3194
|
-
onSuccess: data => {
|
|
3195
|
-
res(data);
|
|
3196
|
-
},
|
|
3197
|
-
onFailure: err => {
|
|
3198
|
-
if (err.code === 'InvalidParameterException') {
|
|
3199
|
-
rej(new AuthError(AuthErrorTypes.DeviceConfig));
|
|
3200
|
-
} else if (err.code === 'NetworkError') {
|
|
3201
|
-
rej(new AuthError(AuthErrorTypes.NetworkError));
|
|
3202
|
-
} else {
|
|
3203
|
-
rej(err);
|
|
3204
|
-
}
|
|
3205
|
-
},
|
|
3206
|
-
},
|
|
3207
|
-
getAmplifyUserAgent(userAgentDetails)
|
|
3208
|
-
);
|
|
3209
|
-
});
|
|
3210
|
-
}
|
|
3211
|
-
|
|
3212
|
-
public async fetchDevices(
|
|
3213
|
-
customUserAgentDetails?: CustomUserAgentDetails
|
|
3214
|
-
): Promise<IAuthDevice[]> {
|
|
3215
|
-
let internalUser: InternalCognitoUser | any;
|
|
3216
|
-
const userAgentDetails = getAuthUserAgentDetails(
|
|
3217
|
-
AuthAction.FetchDevices,
|
|
3218
|
-
customUserAgentDetails
|
|
3219
|
-
);
|
|
3220
|
-
|
|
3221
|
-
try {
|
|
3222
|
-
internalUser = await this._currentUserPoolUser(
|
|
3223
|
-
undefined,
|
|
3224
|
-
userAgentDetails
|
|
3225
|
-
);
|
|
3226
|
-
} catch (error) {
|
|
3227
|
-
logger.debug('The user is not authenticated by the error', error);
|
|
3228
|
-
throw new Error('The user is not authenticated');
|
|
3229
|
-
}
|
|
3230
|
-
|
|
3231
|
-
internalUser.getCachedDeviceKeyAndPassword();
|
|
3232
|
-
return new Promise((res, rej) => {
|
|
3233
|
-
const cb = {
|
|
3234
|
-
onSuccess(data) {
|
|
3235
|
-
const deviceList: IAuthDevice[] = data.Devices.map(device => {
|
|
3236
|
-
const deviceName =
|
|
3237
|
-
device.DeviceAttributes.find(
|
|
3238
|
-
({ Name }) => Name === 'device_name'
|
|
3239
|
-
) || {};
|
|
3240
|
-
|
|
3241
|
-
const deviceInfo: IAuthDevice = {
|
|
3242
|
-
id: device.DeviceKey,
|
|
3243
|
-
name: deviceName.Value,
|
|
3244
|
-
};
|
|
3245
|
-
return deviceInfo;
|
|
3246
|
-
});
|
|
3247
|
-
res(deviceList);
|
|
3248
|
-
},
|
|
3249
|
-
onFailure: err => {
|
|
3250
|
-
if (err.code === 'InvalidParameterException') {
|
|
3251
|
-
rej(new AuthError(AuthErrorTypes.DeviceConfig));
|
|
3252
|
-
} else if (err.code === 'NetworkError') {
|
|
3253
|
-
rej(new AuthError(AuthErrorTypes.NetworkError));
|
|
3254
|
-
} else {
|
|
3255
|
-
rej(err);
|
|
3256
|
-
}
|
|
3257
|
-
},
|
|
3258
|
-
};
|
|
3259
|
-
internalUser.listDevices(
|
|
3260
|
-
MAX_DEVICES,
|
|
3261
|
-
null,
|
|
3262
|
-
cb,
|
|
3263
|
-
getAmplifyUserAgent(userAgentDetails)
|
|
3264
|
-
);
|
|
3265
|
-
});
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
|
|
3269
|
-
export const InternalAuth = new InternalAuthClass(null);
|
|
3270
|
-
Amplify.register(InternalAuth);
|