@aws-amplify/core 6.0.1-console-preview.3b09ef9.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.
- package/lib/Hub/types/AuthTypes.d.ts +13 -7
- package/lib/Platform/index.d.ts +2 -2
- package/lib/Platform/index.js +2 -5
- package/lib/Platform/types.d.ts +4 -55
- package/lib/Platform/types.js +36 -48
- package/lib/Platform/version.d.ts +1 -1
- package/lib/Platform/version.js +1 -1
- package/lib/index.d.ts +1 -7
- package/lib/index.js +2 -17
- package/lib/libraryUtils.d.ts +1 -1
- package/lib/parseAWSExports.d.ts +5 -4
- package/lib/parseAWSExports.js +37 -43
- package/lib/singleton/Auth/index.js +1 -1
- package/lib/singleton/Auth/types.d.ts +2 -2
- package/lib/singleton/types.d.ts +2 -2
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/core.d.ts +0 -8
- package/lib-esm/Hub/types/AuthTypes.d.ts +13 -7
- package/lib-esm/Platform/index.d.ts +2 -2
- package/lib-esm/Platform/index.js +2 -5
- package/lib-esm/Platform/types.d.ts +4 -55
- package/lib-esm/Platform/types.js +36 -48
- package/lib-esm/Platform/version.d.ts +1 -1
- package/lib-esm/Platform/version.js +1 -1
- package/lib-esm/index.d.ts +1 -7
- package/lib-esm/index.js +1 -6
- package/lib-esm/libraryUtils.d.ts +1 -1
- package/lib-esm/parseAWSExports.d.ts +5 -4
- package/lib-esm/parseAWSExports.js +37 -43
- package/lib-esm/singleton/Auth/index.js +1 -1
- package/lib-esm/singleton/Auth/types.d.ts +2 -2
- package/lib-esm/singleton/types.d.ts +2 -2
- package/lib-esm/tsconfig.tsbuildinfo +1 -1
- package/lib-esm/types/core.d.ts +0 -8
- package/package.json +2 -26
- package/src/Cache/CHANGELOG.md +12 -0
- package/src/Hub/types/AuthTypes.ts +8 -6
- package/src/Platform/index.ts +3 -8
- package/src/Platform/types.ts +34 -56
- package/src/Platform/version.ts +1 -1
- package/src/index.ts +3 -9
- package/src/libraryUtils.ts +5 -1
- package/src/parseAWSExports.ts +69 -63
- package/src/singleton/Auth/index.ts +1 -1
- package/src/singleton/Auth/types.ts +2 -2
- package/src/singleton/types.ts +5 -4
- package/src/types/core.ts +0 -10
- package/lib/Credentials.d.ts +0 -47
- package/lib/Credentials.js +0 -676
- package/lib-esm/Credentials.d.ts +0 -47
- package/lib-esm/Credentials.js +0 -673
- package/src/Credentials.ts +0 -630
package/src/Credentials.ts
DELETED
|
@@ -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);
|