-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathIdentityIdProvider.ts
110 lines (97 loc) · 3.22 KB
/
IdentityIdProvider.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { AuthTokens, ConsoleLogger, Identity, getId } from '@aws-amplify/core';
import { CognitoIdentityPoolConfig } from '@aws-amplify/core/internals/utils';
import { AuthError } from '../../../errors/AuthError';
import { getRegionFromIdentityPoolId } from '../../../foundation/parsers';
import { GetIdException } from '../types/errors';
import { IdentityIdStore } from './types';
import { formLoginsMap } from './utils';
const logger = new ConsoleLogger('CognitoIdentityIdProvider');
/**
* Provides a Cognito identityId
*
* @param tokens - The AuthTokens received after SignIn
* @returns string
* @throws configuration exceptions: `InvalidIdentityPoolIdException`
* - Auth errors that may arise from misconfiguration.
* @throws service exceptions: {@link GetIdException }
*/
export async function cognitoIdentityIdProvider({
tokens,
authConfig,
identityIdStore,
}: {
tokens?: AuthTokens;
authConfig: CognitoIdentityPoolConfig;
identityIdStore: IdentityIdStore;
}): Promise<string> {
identityIdStore.setAuthConfig({ Cognito: authConfig });
// will return null only if there is no identityId cached or if there is an error retrieving it
let identityId: Identity | null = await identityIdStore.loadIdentityId();
// Tokens are available so return primary identityId
if (tokens) {
// If there is existing primary identityId in-memory return that
if (identityId && identityId.type === 'primary') {
return identityId.id;
} else {
const logins = tokens.idToken
? formLoginsMap(tokens.idToken.toString())
: {};
const generatedIdentityId = await generateIdentityId(logins, authConfig);
if (identityId && identityId.id === generatedIdentityId) {
logger.debug(
`The guest identity ${identityId.id} has become the primary identity.`,
);
}
identityId = {
id: generatedIdentityId,
type: 'primary',
};
}
} else {
// If there is existing guest identityId cached return that
if (identityId && identityId.type === 'guest') {
return identityId.id;
} else {
identityId = {
id: await generateIdentityId({}, authConfig),
type: 'guest',
};
}
}
// Store in-memory or local storage depending on guest or primary identityId
identityIdStore.storeIdentityId(identityId);
return identityId.id;
}
async function generateIdentityId(
logins: Record<string, string>,
authConfig: CognitoIdentityPoolConfig,
): Promise<string> {
const identityPoolId = authConfig?.identityPoolId;
const region = getRegionFromIdentityPoolId(identityPoolId);
// IdentityId is absent so get it using IdentityPoolId with Cognito's GetId API
const idResult =
// for a first-time user, this will return a brand new identity
// for a returning user, this will retrieve the previous identity assocaited with the logins
(
await getId(
{
region,
},
{
IdentityPoolId: identityPoolId,
Logins: logins,
},
)
).IdentityId;
if (!idResult) {
throw new AuthError({
name: 'GetIdResponseException',
message: 'Received undefined response from getId operation',
recoverySuggestion:
'Make sure to pass a valid identityPoolId in the configuration.',
});
}
return idResult;
}