@aws-amplify/core 6.0.1-console-preview.2f5ba46.0 → 6.0.1-console-preview.9e7dd78.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.
Files changed (43) hide show
  1. package/lib/Hub/types/AuthTypes.d.ts +13 -7
  2. package/lib/Platform/index.d.ts +2 -2
  3. package/lib/Platform/index.js +2 -5
  4. package/lib/Platform/types.d.ts +4 -55
  5. package/lib/Platform/types.js +36 -48
  6. package/lib/Platform/version.d.ts +1 -1
  7. package/lib/Platform/version.js +1 -1
  8. package/lib/index.d.ts +0 -6
  9. package/lib/index.js +2 -17
  10. package/lib/parseAWSExports.d.ts +5 -4
  11. package/lib/parseAWSExports.js +37 -43
  12. package/lib/singleton/Auth/types.d.ts +1 -1
  13. package/lib/tsconfig.tsbuildinfo +1 -1
  14. package/lib/types/core.d.ts +0 -8
  15. package/lib-esm/Hub/types/AuthTypes.d.ts +13 -7
  16. package/lib-esm/Platform/index.d.ts +2 -2
  17. package/lib-esm/Platform/index.js +2 -5
  18. package/lib-esm/Platform/types.d.ts +4 -55
  19. package/lib-esm/Platform/types.js +36 -48
  20. package/lib-esm/Platform/version.d.ts +1 -1
  21. package/lib-esm/Platform/version.js +1 -1
  22. package/lib-esm/index.d.ts +0 -6
  23. package/lib-esm/index.js +1 -6
  24. package/lib-esm/parseAWSExports.d.ts +5 -4
  25. package/lib-esm/parseAWSExports.js +37 -43
  26. package/lib-esm/singleton/Auth/types.d.ts +1 -1
  27. package/lib-esm/tsconfig.tsbuildinfo +1 -1
  28. package/lib-esm/types/core.d.ts +0 -8
  29. package/package.json +2 -26
  30. package/src/Cache/CHANGELOG.md +12 -0
  31. package/src/Hub/types/AuthTypes.ts +8 -6
  32. package/src/Platform/index.ts +3 -8
  33. package/src/Platform/types.ts +34 -56
  34. package/src/Platform/version.ts +1 -1
  35. package/src/index.ts +1 -7
  36. package/src/parseAWSExports.ts +69 -63
  37. package/src/singleton/Auth/types.ts +1 -1
  38. package/src/types/core.ts +0 -10
  39. package/lib/Credentials.d.ts +0 -47
  40. package/lib/Credentials.js +0 -676
  41. package/lib-esm/Credentials.d.ts +0 -47
  42. package/lib-esm/Credentials.js +0 -673
  43. package/src/Credentials.ts +0 -630
@@ -1,630 +0,0 @@
1
- // @ts-nocheck
2
- // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
- // SPDX-License-Identifier: Apache-2.0
4
- import { ConsoleLogger as Logger } from './Logger';
5
- import { StorageHelper } from './StorageHelper';
6
- import { makeQuerablePromise } from './Util/JS';
7
- import { FacebookOAuth, GoogleOAuth } from './OAuthHelper';
8
- import { jitteredExponentialRetry } from './Util';
9
- import { ICredentials } from './types';
10
- import { Amplify } from './Amplify';
11
- import { getId, getCredentialsForIdentity } from './AwsClients/CognitoIdentity';
12
- import { parseAWSExports } from './parseAWSExports';
13
- import { Hub, AMPLIFY_SYMBOL } from './Hub';
14
-
15
- const logger = new Logger('Credentials');
16
-
17
- const CREDENTIALS_TTL = 50 * 60 * 1000; // 50 min, can be modified on config if required in the future
18
-
19
- const COGNITO_IDENTITY_KEY_PREFIX = 'CognitoIdentityId-';
20
-
21
- const dispatchCredentialsEvent = (
22
- event: string,
23
- data: any,
24
- message: string
25
- ) => {
26
- Hub.dispatch('core', { event, data, message }, 'Credentials', AMPLIFY_SYMBOL);
27
- };
28
-
29
- export class CredentialsClass {
30
- private _config;
31
- private _credentials;
32
- private _credentials_source;
33
- private _gettingCredPromise: any = null;
34
- private _refreshHandlers = {};
35
- private _storage;
36
- private _storageSync;
37
- private _identityId;
38
- // @ts-ignore
39
- private _nextCredentialsRefresh: number;
40
-
41
- // Allow `Auth` to be injected for SSR, but Auth isn't a required dependency for Credentials
42
- Auth = undefined;
43
-
44
- constructor(config) {
45
- this.configure(config);
46
- this._refreshHandlers['google'] = GoogleOAuth.refreshGoogleToken;
47
- this._refreshHandlers['facebook'] = FacebookOAuth.refreshFacebookToken;
48
- }
49
-
50
- public getModuleName() {
51
- return 'Credentials';
52
- }
53
-
54
- public getCredSource() {
55
- return this._credentials_source;
56
- }
57
-
58
- public configure(config) {
59
- if (!config) return this._config || {};
60
-
61
- this._config = Object.assign({}, this._config, config);
62
- const { refreshHandlers } = this._config;
63
- // If the developer has provided an object of refresh handlers,
64
- // then we can merge the provided handlers with the current handlers.
65
- if (refreshHandlers) {
66
- this._refreshHandlers = {
67
- ...this._refreshHandlers,
68
- ...refreshHandlers,
69
- };
70
- }
71
-
72
- this._storage = this._config.storage;
73
-
74
- if (!this._storage) {
75
- this._storage = new StorageHelper().getStorage();
76
- }
77
-
78
- this._storageSync = Promise.resolve();
79
- if (typeof this._storage['sync'] === 'function') {
80
- this._storageSync = this._storage['sync']();
81
- }
82
-
83
- dispatchCredentialsEvent(
84
- 'credentials_configured',
85
- null,
86
- `Credentials has been configured successfully`
87
- );
88
-
89
- return this._config;
90
- }
91
-
92
- public get() {
93
- logger.debug('getting credentials');
94
- return this._pickupCredentials();
95
- }
96
-
97
- // currently we only store the guest identity in local storage
98
- private _getCognitoIdentityIdStorageKey(identityPoolId: string) {
99
- return `${COGNITO_IDENTITY_KEY_PREFIX}${identityPoolId}`;
100
- }
101
-
102
- private _pickupCredentials() {
103
- logger.debug('picking up credentials');
104
- if (!this._gettingCredPromise || !this._gettingCredPromise.isPending()) {
105
- logger.debug('getting new cred promise');
106
- this._gettingCredPromise = makeQuerablePromise(this._keepAlive());
107
- } else {
108
- logger.debug('getting old cred promise');
109
- }
110
- return this._gettingCredPromise;
111
- }
112
-
113
- private async _keepAlive() {
114
- logger.debug('checking if credentials exists and not expired');
115
- const cred = this._credentials;
116
- if (cred && !this._isExpired(cred) && !this._isPastTTL()) {
117
- logger.debug('credentials not changed and not expired, directly return');
118
- return Promise.resolve(cred);
119
- }
120
-
121
- logger.debug('need to get a new credential or refresh the existing one');
122
-
123
- // Some use-cases don't require Auth for signing in, but use Credentials for guest users (e.g. Analytics)
124
- // Prefer locally scoped `Auth`, but fallback to registered `Amplify.Auth` global otherwise.
125
- const { Auth = Amplify.Auth } = this as any;
126
-
127
- if (!Auth || typeof Auth.currentUserCredentials !== 'function') {
128
- // If Auth module is not imported, do a best effort to get guest credentials
129
- return this._setCredentialsForGuest();
130
- }
131
-
132
- if (!this._isExpired(cred) && this._isPastTTL()) {
133
- logger.debug('ttl has passed but token is not yet expired');
134
- try {
135
- const user = await Auth.currentUserPoolUser();
136
- const session = await Auth.currentSession();
137
- const refreshToken = session.refreshToken;
138
- const refreshRequest = new Promise((res, rej) => {
139
- user.refreshSession(refreshToken, (err, data) => {
140
- return err ? rej(err) : res(data);
141
- });
142
- });
143
- await refreshRequest; // note that rejections will be caught and handled in the catch block.
144
- } catch (err) {
145
- // should not throw because user might just be on guest access or is authenticated through federation
146
- logger.debug('Error attempting to refreshing the session', err);
147
- }
148
- }
149
- return Auth.currentUserCredentials();
150
- }
151
-
152
- public refreshFederatedToken(federatedInfo) {
153
- logger.debug('Getting federated credentials');
154
- const { provider, user, token, identity_id } = federatedInfo;
155
- let { expires_at } = federatedInfo;
156
-
157
- // Make sure expires_at is in millis
158
- expires_at =
159
- new Date(expires_at).getFullYear() === 1970
160
- ? expires_at * 1000
161
- : expires_at;
162
-
163
- const that = this;
164
- logger.debug('checking if federated jwt token expired');
165
- if (expires_at > new Date().getTime()) {
166
- // if not expired
167
- logger.debug('token not expired');
168
- return this._setCredentialsFromFederation({
169
- provider,
170
- token,
171
- user,
172
- identity_id,
173
- expires_at,
174
- });
175
- } else {
176
- // if refresh handler exists
177
- if (
178
- that._refreshHandlers[provider] &&
179
- typeof that._refreshHandlers[provider] === 'function'
180
- ) {
181
- logger.debug('getting refreshed jwt token from federation provider');
182
- return this._providerRefreshWithRetry({
183
- refreshHandler: that._refreshHandlers[provider],
184
- provider,
185
- user,
186
- });
187
- } else {
188
- logger.debug('no refresh handler for provider:', provider);
189
- this.clear();
190
- return Promise.reject('no refresh handler for provider');
191
- }
192
- }
193
- }
194
-
195
- private _providerRefreshWithRetry({ refreshHandler, provider, user }) {
196
- const MAX_DELAY_MS = 10 * 1000;
197
- // refreshHandler will retry network errors, otherwise it will
198
- // return NonRetryableError to break out of jitteredExponentialRetry
199
- return jitteredExponentialRetry<any>(refreshHandler, [], MAX_DELAY_MS)
200
- .then(data => {
201
- logger.debug('refresh federated token sucessfully', data);
202
- return this._setCredentialsFromFederation({
203
- provider,
204
- token: data.token,
205
- user,
206
- identity_id: data.identity_id,
207
- expires_at: data.expires_at,
208
- });
209
- })
210
- .catch(e => {
211
- const isNetworkError =
212
- typeof e === 'string' &&
213
- e.toLowerCase().lastIndexOf('network error', e.length) === 0;
214
-
215
- if (!isNetworkError) {
216
- this.clear();
217
- }
218
-
219
- logger.debug('refresh federated token failed', e);
220
- return Promise.reject('refreshing federation token failed: ' + e);
221
- });
222
- }
223
-
224
- private _isExpired(credentials): boolean {
225
- if (!credentials) {
226
- logger.debug('no credentials for expiration check');
227
- return true;
228
- }
229
- logger.debug('are these credentials expired?', credentials);
230
- const ts = Date.now();
231
-
232
- /* returns date object.
233
- https://github.com/aws/aws-sdk-js-v3/blob/v1.0.0-beta.1/packages/types/src/credentials.ts#L26
234
- */
235
- const { expiration } = credentials;
236
- return expiration.getTime() <= ts;
237
- }
238
-
239
- private _isPastTTL(): boolean {
240
- return this._nextCredentialsRefresh <= Date.now();
241
- }
242
-
243
- private async _setCredentialsForGuest() {
244
- logger.debug('setting credentials for guest');
245
- if (!this._config?.identityPoolId) {
246
- // If Credentials are not configured thru Auth module,
247
- // doing best effort to check if the library was configured
248
- this._config = Object.assign(
249
- {},
250
- this._config,
251
- parseAWSExports(this._config || {}).Auth
252
- );
253
- }
254
- const { identityPoolId, region, mandatorySignIn, identityPoolRegion } =
255
- this._config;
256
-
257
- if (mandatorySignIn) {
258
- return Promise.reject(
259
- 'cannot get guest credentials when mandatory signin enabled'
260
- );
261
- }
262
-
263
- if (!identityPoolId) {
264
- logger.debug(
265
- 'No Cognito Identity pool provided for unauthenticated access'
266
- );
267
- return Promise.reject(
268
- 'No Cognito Identity pool provided for unauthenticated access'
269
- );
270
- }
271
-
272
- if (!identityPoolRegion && !region) {
273
- logger.debug('region is not configured for getting the credentials');
274
- return Promise.reject(
275
- 'region is not configured for getting the credentials'
276
- );
277
- }
278
-
279
- const identityId = (this._identityId = await this._getGuestIdentityId());
280
-
281
- const cognitoConfig = { region: identityPoolRegion ?? region };
282
-
283
- const guestCredentialsProvider = async () => {
284
- if (!identityId) {
285
- const { IdentityId } = await getId(cognitoConfig, {
286
- IdentityPoolId: identityPoolId,
287
- });
288
- this._identityId = IdentityId;
289
- }
290
- const { Credentials } = await getCredentialsForIdentity(cognitoConfig, {
291
- IdentityId: this._identityId,
292
- });
293
- return {
294
- identityId: this._identityId,
295
- accessKeyId: Credentials!.AccessKeyId,
296
- secretAccessKey: Credentials!.SecretKey,
297
- sessionToken: Credentials!.SessionToken,
298
- expiration: Credentials!.Expiration,
299
- };
300
- };
301
- let credentials = guestCredentialsProvider().catch(async err => {
302
- throw err;
303
- });
304
-
305
- return this._loadCredentials(credentials, 'guest', false, null)
306
- .then(res => {
307
- return res;
308
- })
309
- .catch(async e => {
310
- // If identity id is deleted in the console, we make one attempt to recreate it
311
- // and remove existing id from cache.
312
- if (
313
- e.name === 'ResourceNotFoundException' &&
314
- e.message === `Identity '${identityId}' not found.`
315
- ) {
316
- logger.debug('Failed to load guest credentials');
317
- await this._removeGuestIdentityId();
318
-
319
- const guestCredentialsProvider = async () => {
320
- const { IdentityId } = await getId(cognitoConfig, {
321
- IdentityPoolId: identityPoolId,
322
- });
323
- this._identityId = IdentityId;
324
- const { Credentials } = await getCredentialsForIdentity(
325
- cognitoConfig,
326
- {
327
- IdentityId,
328
- }
329
- );
330
-
331
- return {
332
- identityId: IdentityId,
333
- accessKeyId: Credentials!.AccessKeyId,
334
- secretAccessKey: Credentials!.SecretKey,
335
- sessionToken: Credentials!.SessionToken,
336
- expiration: Credentials!.Expiration,
337
- };
338
- };
339
-
340
- credentials = guestCredentialsProvider().catch(async err => {
341
- throw err;
342
- });
343
-
344
- return this._loadCredentials(credentials, 'guest', false, null);
345
- } else {
346
- return e;
347
- }
348
- });
349
- }
350
-
351
- private _setCredentialsFromFederation(params) {
352
- const { provider, token } = params;
353
- let { identity_id } = params;
354
- const domains = {
355
- google: 'accounts.google.com',
356
- facebook: 'graph.facebook.com',
357
- amazon: 'www.amazon.com',
358
- developer: 'cognito-identity.amazonaws.com',
359
- };
360
-
361
- // Use custom provider url instead of the predefined ones
362
- const domain = domains[provider] || provider;
363
- if (!domain) {
364
- return Promise.reject('You must specify a federated provider');
365
- }
366
-
367
- const logins = {};
368
- logins[domain] = token;
369
-
370
- const { identityPoolId, region, identityPoolRegion } = this._config;
371
- if (!identityPoolId) {
372
- logger.debug('No Cognito Federated Identity pool provided');
373
- return Promise.reject('No Cognito Federated Identity pool provided');
374
- }
375
- if (!identityPoolRegion && !region) {
376
- logger.debug('region is not configured for getting the credentials');
377
- return Promise.reject(
378
- 'region is not configured for getting the credentials'
379
- );
380
- }
381
-
382
- const cognitoConfig = { region: identityPoolRegion ?? region };
383
-
384
- const authenticatedCredentialsProvider = async () => {
385
- if (!identity_id) {
386
- const { IdentityId } = await getId(cognitoConfig, {
387
- IdentityPoolId: identityPoolId,
388
- Logins: logins,
389
- });
390
- identity_id = IdentityId;
391
- }
392
- const { Credentials } = await getCredentialsForIdentity(cognitoConfig, {
393
- IdentityId: identity_id,
394
- Logins: logins,
395
- });
396
- return {
397
- identityId: identity_id,
398
- accessKeyId: Credentials!.AccessKeyId,
399
- secretAccessKey: Credentials!.SecretKey,
400
- sessionToken: Credentials!.SessionToken,
401
- expiration: Credentials!.Expiration,
402
- };
403
- };
404
-
405
- const credentials = authenticatedCredentialsProvider().catch(async err => {
406
- throw err;
407
- });
408
-
409
- return this._loadCredentials(credentials, 'federated', true, params);
410
- }
411
-
412
- private _setCredentialsFromSession(session): Promise<ICredentials> {
413
- logger.debug('set credentials from session');
414
- const idToken = session.getIdToken().getJwtToken();
415
- const { region, userPoolId, identityPoolId, identityPoolRegion } =
416
- this._config;
417
- if (!identityPoolId) {
418
- logger.debug('No Cognito Federated Identity pool provided');
419
- return Promise.reject('No Cognito Federated Identity pool provided');
420
- }
421
- if (!identityPoolRegion && !region) {
422
- logger.debug('region is not configured for getting the credentials');
423
- return Promise.reject(
424
- 'region is not configured for getting the credentials'
425
- );
426
- }
427
- const key = 'cognito-idp.' + region + '.amazonaws.com/' + userPoolId;
428
- const logins = {};
429
- logins[key] = idToken;
430
-
431
- const cognitoConfig = { region: identityPoolRegion ?? region };
432
-
433
- /*
434
- Retreiving identityId with GetIdCommand to mimic the behavior in the following code in aws-sdk-v3:
435
- https://git.io/JeDxU
436
-
437
- Note: Retreive identityId from CredentialsProvider once aws-sdk-js v3 supports this.
438
- */
439
- const credentialsProvider = async () => {
440
- // try to fetch the local stored guest identity, if found, we will associate it with the logins
441
- const guestIdentityId = await this._getGuestIdentityId();
442
-
443
- let generatedOrRetrievedIdentityId;
444
- if (!guestIdentityId) {
445
- // for a first-time user, this will return a brand new identity
446
- // for a returning user, this will retrieve the previous identity assocaited with the logins
447
- const { IdentityId } = await getId(cognitoConfig, {
448
- IdentityPoolId: identityPoolId,
449
- Logins: logins,
450
- });
451
- generatedOrRetrievedIdentityId = IdentityId;
452
- }
453
-
454
- const {
455
- Credentials: { AccessKeyId, Expiration, SecretKey, SessionToken },
456
- // single source of truth for the primary identity associated with the logins
457
- // only if a guest identity is used for a first-time user, that guest identity will become its primary identity
458
- IdentityId: primaryIdentityId,
459
- } = (await getCredentialsForIdentity(cognitoConfig, {
460
- IdentityId: guestIdentityId || generatedOrRetrievedIdentityId,
461
- Logins: logins,
462
- })) as { Credentials: any; IdentityId: string };
463
-
464
- this._identityId = primaryIdentityId;
465
- if (guestIdentityId) {
466
- // if guestIdentity is found and used by GetCredentialsForIdentity
467
- // it will be linked to the logins provided, and disqualified as an unauth identity
468
- logger.debug(
469
- `The guest identity ${guestIdentityId} has been successfully linked to the logins`
470
- );
471
- if (guestIdentityId === primaryIdentityId) {
472
- logger.debug(
473
- `The guest identity ${guestIdentityId} has become the primary identity`
474
- );
475
- }
476
- // remove it from local storage to avoid being used as a guest Identity by _setCredentialsForGuest
477
- await this._removeGuestIdentityId();
478
- }
479
-
480
- // https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-provider-cognito-identity/src/fromCognitoIdentity.ts#L40
481
- return {
482
- accessKeyId: AccessKeyId,
483
- secretAccessKey: SecretKey,
484
- sessionToken: SessionToken,
485
- expiration: Expiration,
486
- identityId: primaryIdentityId,
487
- };
488
- };
489
-
490
- const credentials = credentialsProvider().catch(async err => {
491
- throw err;
492
- });
493
-
494
- return this._loadCredentials(credentials, 'userPool', true, null);
495
- }
496
-
497
- private _loadCredentials(
498
- credentials,
499
- source,
500
- authenticated,
501
- info
502
- ): Promise<ICredentials> {
503
- const that = this;
504
- return new Promise((res, rej) => {
505
- credentials
506
- .then(async credentials => {
507
- logger.debug('Load credentials successfully', credentials);
508
- if (this._identityId && !credentials.identityId) {
509
- credentials['identityId'] = this._identityId;
510
- }
511
-
512
- that._credentials = credentials;
513
- that._credentials.authenticated = authenticated;
514
- that._credentials_source = source;
515
- that._nextCredentialsRefresh = new Date().getTime() + CREDENTIALS_TTL;
516
- if (source === 'federated') {
517
- const user = Object.assign(
518
- { id: this._credentials.identityId },
519
- info.user
520
- );
521
- const { provider, token, expires_at, identity_id } = info;
522
- try {
523
- this._storage.setItem(
524
- 'aws-amplify-federatedInfo',
525
- JSON.stringify({
526
- provider,
527
- token,
528
- user,
529
- expires_at,
530
- identity_id,
531
- })
532
- );
533
- } catch (e) {
534
- logger.debug('Failed to put federated info into auth storage', e);
535
- }
536
- }
537
- if (source === 'guest') {
538
- await this._setGuestIdentityId(credentials.identityId);
539
- }
540
- res(that._credentials);
541
- return;
542
- })
543
- .catch(err => {
544
- if (err) {
545
- logger.debug('Failed to load credentials', credentials);
546
- logger.debug('Error loading credentials', err);
547
- rej(err);
548
- return;
549
- }
550
- });
551
- });
552
- }
553
-
554
- public set(params, source): Promise<ICredentials> {
555
- if (source === 'session') {
556
- return this._setCredentialsFromSession(params);
557
- } else if (source === 'federation') {
558
- return this._setCredentialsFromFederation(params);
559
- } else if (source === 'guest') {
560
- return this._setCredentialsForGuest();
561
- } else {
562
- logger.debug('no source specified for setting credentials');
563
- return Promise.reject('invalid source');
564
- }
565
- }
566
-
567
- public async clear() {
568
- this._credentials = null;
569
- this._credentials_source = null;
570
- logger.debug('removing aws-amplify-federatedInfo from storage');
571
- this._storage.removeItem('aws-amplify-federatedInfo');
572
- }
573
-
574
- /* operations on local stored guest identity */
575
- private async _getGuestIdentityId(): Promise<string | undefined> {
576
- const { identityPoolId } = this._config;
577
- try {
578
- await this._storageSync;
579
- return this._storage.getItem(
580
- this._getCognitoIdentityIdStorageKey(identityPoolId)
581
- );
582
- } catch (e) {
583
- logger.debug('Failed to get the cached guest identityId', e);
584
- }
585
- }
586
-
587
- private async _setGuestIdentityId(identityId: string) {
588
- const { identityPoolId } = this._config;
589
- try {
590
- await this._storageSync;
591
- this._storage.setItem(
592
- this._getCognitoIdentityIdStorageKey(identityPoolId),
593
- identityId
594
- );
595
- } catch (e) {
596
- logger.debug('Failed to cache guest identityId', e);
597
- }
598
- }
599
-
600
- private async _removeGuestIdentityId() {
601
- const { identityPoolId } = this._config;
602
- logger.debug(
603
- `removing ${this._getCognitoIdentityIdStorageKey(
604
- identityPoolId
605
- )} from storage`
606
- );
607
- this._storage.removeItem(
608
- this._getCognitoIdentityIdStorageKey(identityPoolId)
609
- );
610
- }
611
-
612
- /**
613
- * Compact version of credentials
614
- * @param {Object} credentials
615
- * @return {Object} - Credentials
616
- */
617
- public shear(credentials) {
618
- return {
619
- accessKeyId: credentials.accessKeyId,
620
- sessionToken: credentials.sessionToken,
621
- secretAccessKey: credentials.secretAccessKey,
622
- identityId: credentials.identityId,
623
- authenticated: credentials.authenticated,
624
- };
625
- }
626
- }
627
-
628
- export const Credentials = new CredentialsClass(null);
629
-
630
- Amplify.register(Credentials);