@ttoss/cloud-auth 0.6.4 → 0.7.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/dist/index.js CHANGED
@@ -33,10 +33,16 @@ var PASSWORD_MINIMUM_LENGTH = 8;
33
33
  var CognitoUserPoolLogicalId = "CognitoUserPool";
34
34
  var CognitoUserPoolClientLogicalId = "CognitoUserPoolClient";
35
35
  var CognitoIdentityPoolLogicalId = "CognitoIdentityPool";
36
+ var IdentityPoolAuthenticatedIAMRoleLogicalId = "IdentityPoolAuthenticatedIAMRole";
37
+ var IdentityPoolUnauthenticatedIAMRoleLogicalId = "IdentityPoolUnauthenticatedIAMRole";
38
+ var DenyStatement = {
39
+ Effect: "Deny",
40
+ Action: ["*"],
41
+ Resource: ["*"]
42
+ };
36
43
  var createAuthTemplate = ({
37
44
  autoVerifiedAttributes = ["email"],
38
- identityPool = true,
39
- roles,
45
+ identityPool,
40
46
  schema,
41
47
  usernameAttributes = ["email"]
42
48
  } = {}) => {
@@ -58,7 +64,6 @@ var createAuthTemplate = ({
58
64
  TemporaryPasswordValidityDays: 30
59
65
  }
60
66
  },
61
- Schema: schema,
62
67
  UsernameAttributes: usernameAttributes,
63
68
  UsernameConfiguration: {
64
69
  CaseSensitive: false
@@ -114,7 +119,35 @@ var createAuthTemplate = ({
114
119
  }
115
120
  }
116
121
  };
117
- if (identityPool) {
122
+ if (schema) {
123
+ const Schema = schema.map((attribute) => {
124
+ let NumberAttributeConstraints = void 0;
125
+ if (attribute.numberAttributeConstraints) {
126
+ NumberAttributeConstraints = {
127
+ MaxValue: attribute.numberAttributeConstraints?.maxValue,
128
+ MinValue: attribute.numberAttributeConstraints?.minValue
129
+ };
130
+ }
131
+ let StringAttributeConstraints = void 0;
132
+ if (attribute.stringAttributeConstraints) {
133
+ StringAttributeConstraints = {
134
+ MaxLength: attribute.stringAttributeConstraints?.maxLength,
135
+ MinLength: attribute.stringAttributeConstraints?.minLength
136
+ };
137
+ }
138
+ return {
139
+ AttributeDataType: attribute.attributeDataType,
140
+ DeveloperOnlyAttribute: attribute.developerOnlyAttribute,
141
+ Mutable: attribute.mutable,
142
+ Name: attribute.name,
143
+ NumberAttributeConstraints,
144
+ Required: attribute.required,
145
+ StringAttributeConstraints
146
+ };
147
+ });
148
+ template.Resources[CognitoUserPoolLogicalId].Properties.Schema = Schema;
149
+ }
150
+ if (identityPool?.enabled) {
118
151
  template.Resources[CognitoIdentityPoolLogicalId] = {
119
152
  Type: "AWS::Cognito::IdentityPool",
120
153
  Properties: {
@@ -131,17 +164,94 @@ var createAuthTemplate = ({
131
164
  ]
132
165
  }
133
166
  };
134
- if (roles) {
135
- template.Resources.CognitoIdentityPoolRoleAttachment = {
136
- Type: "AWS::Cognito::IdentityPoolRoleAttachment",
137
- Properties: {
138
- IdentityPoolId: {
139
- Ref: CognitoIdentityPoolLogicalId
167
+ template.Resources[IdentityPoolAuthenticatedIAMRoleLogicalId] = {
168
+ Type: "AWS::IAM::Role",
169
+ Properties: {
170
+ AssumeRolePolicyDocument: {
171
+ Version: "2012-10-17",
172
+ Statement: [
173
+ {
174
+ Effect: "Allow",
175
+ Principal: {
176
+ Federated: "cognito-identity.amazonaws.com"
177
+ },
178
+ Action: ["sts:AssumeRoleWithWebIdentity", "sts:TagSession"],
179
+ Condition: {
180
+ StringEquals: {
181
+ "cognito-identity.amazonaws.com:aud": {
182
+ Ref: CognitoIdentityPoolLogicalId
183
+ }
184
+ },
185
+ "ForAnyValue:StringLike": {
186
+ "cognito-identity.amazonaws.com:amr": "authenticated"
187
+ }
188
+ }
189
+ }
190
+ ]
191
+ },
192
+ Policies: identityPool.authenticatedPolicies || [
193
+ {
194
+ PolicyName: "IdentityPoolAuthenticatedIAMRolePolicyName",
195
+ PolicyDocument: {
196
+ Version: "2012-10-17",
197
+ Statement: [DenyStatement]
198
+ }
199
+ }
200
+ ]
201
+ }
202
+ };
203
+ template.Resources[IdentityPoolUnauthenticatedIAMRoleLogicalId] = {
204
+ Type: "AWS::IAM::Role",
205
+ Properties: {
206
+ AssumeRolePolicyDocument: {
207
+ Version: "2012-10-17",
208
+ Statement: [
209
+ {
210
+ Effect: "Allow",
211
+ Principal: {
212
+ Federated: "cognito-identity.amazonaws.com"
213
+ },
214
+ Action: "sts:AssumeRoleWithWebIdentity",
215
+ Condition: {
216
+ StringEquals: {
217
+ "cognito-identity.amazonaws.com:aud": {
218
+ Ref: CognitoIdentityPoolLogicalId
219
+ }
220
+ },
221
+ "ForAnyValue:StringLike": {
222
+ "cognito-identity.amazonaws.com:amr": "unauthenticated"
223
+ }
224
+ }
225
+ }
226
+ ]
227
+ },
228
+ Policies: identityPool.authenticatedPolicies || [
229
+ {
230
+ PolicyName: "IdentityPoolUnauthenticatedIAMRolePolicyName",
231
+ PolicyDocument: {
232
+ Version: "2012-10-17",
233
+ Statement: [DenyStatement]
234
+ }
235
+ }
236
+ ]
237
+ }
238
+ };
239
+ template.Resources.CognitoIdentityPoolRoleAttachment = {
240
+ Type: "AWS::Cognito::IdentityPoolRoleAttachment",
241
+ Properties: {
242
+ IdentityPoolId: {
243
+ Ref: CognitoIdentityPoolLogicalId
244
+ },
245
+ Roles: {
246
+ authenticated: {
247
+ "Fn::GetAtt": [IdentityPoolAuthenticatedIAMRoleLogicalId, "Arn"]
140
248
  },
141
- Roles: roles
249
+ unauthenticated: {
250
+ "Fn::GetAtt": [IdentityPoolUnauthenticatedIAMRoleLogicalId, "Arn"]
251
+ }
142
252
  }
143
- };
144
- }
253
+ }
254
+ };
145
255
  if (!template.Outputs) {
146
256
  template.Outputs = {};
147
257
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/cloud-auth",
3
- "version": "0.6.4",
3
+ "version": "0.7.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/esm/index.js",
6
6
  "scripts": {
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "typings": "./dist/index.d.ts",
11
11
  "dependencies": {
12
- "@ttoss/cloudformation": "^0.5.4"
12
+ "@ttoss/cloudformation": "^0.6.0"
13
13
  },
14
14
  "devDependencies": {
15
15
  "@ttoss/config": "^1.28.2",
@@ -20,5 +20,5 @@
20
20
  "publishConfig": {
21
21
  "access": "public"
22
22
  },
23
- "gitHead": "7ce61c5deab1deb32f9f2b573fe2ae6cebb778cd"
23
+ "gitHead": "ff8bed71bb39e2e7d7385f8bb4a1bfda3553cb5c"
24
24
  }
package/src/template.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { CloudFormationTemplate } from '@ttoss/cloudformation';
2
1
  import { PASSWORD_MINIMUM_LENGTH } from './config';
2
+ import type { CloudFormationTemplate, Policy } from '@ttoss/cloudformation';
3
3
 
4
4
  const CognitoUserPoolLogicalId = 'CognitoUserPool';
5
5
 
@@ -7,41 +7,46 @@ const CognitoUserPoolClientLogicalId = 'CognitoUserPoolClient';
7
7
 
8
8
  const CognitoIdentityPoolLogicalId = 'CognitoIdentityPool';
9
9
 
10
- type Role =
11
- | string
12
- | {
13
- 'Fn::ImportValue': string;
14
- };
10
+ const IdentityPoolAuthenticatedIAMRoleLogicalId =
11
+ 'IdentityPoolAuthenticatedIAMRole';
12
+
13
+ const IdentityPoolUnauthenticatedIAMRoleLogicalId =
14
+ 'IdentityPoolUnauthenticatedIAMRole';
15
+
16
+ export const DenyStatement = {
17
+ Effect: 'Deny' as const,
18
+ Action: ['*'],
19
+ Resource: ['*'],
20
+ };
15
21
 
16
22
  export const createAuthTemplate = ({
17
23
  autoVerifiedAttributes = ['email'],
18
- identityPool = true,
19
- roles,
24
+ identityPool,
20
25
  schema,
21
26
  usernameAttributes = ['email'],
22
27
  }: {
23
28
  autoVerifiedAttributes?: Array<'email' | 'phone_number'> | null | false;
24
- identityPool?: boolean;
25
- roles?: {
26
- authenticated?: Role;
27
- unauthenticated?: Role;
29
+ identityPool?: {
30
+ enabled?: boolean;
31
+ authenticatedPolicies?: Policy[];
32
+ unauthenticatedPolicies?: Policy[];
28
33
  };
29
34
  /**
30
35
  * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-userpool-schemaattribute.html
31
36
  */
32
37
  schema?: {
33
- AttributeDataType?: 'Boolean' | 'DateTime' | 'Number' | 'String';
34
- DeveloperOnlyAttribute?: boolean;
35
- Mutable?: boolean;
36
- Name?: string;
37
- NumberAttributeConstraints?: {
38
- MaxValue?: string;
39
- MinValue?: string;
38
+ attributeDataType?: 'Boolean' | 'DateTime' | 'Number' | 'String';
39
+ developerOnlyAttribute?: boolean;
40
+ mutable?: boolean;
41
+ name?: string;
42
+ numberAttributeConstraints?: {
43
+ maxValue?: string;
44
+ minValue?: string;
40
45
  };
41
- Required?: boolean;
42
- StringAttributeConstraints?: {
43
- MaxLength: string;
44
- MinLength: string;
46
+ required?: boolean;
47
+ stringAttributeConstraints?: {
48
+ maxLength: string;
49
+ minLength: string;
45
50
  };
46
51
  }[];
47
52
  usernameAttributes?: Array<'email' | 'phone_number'> | null;
@@ -68,7 +73,6 @@ export const createAuthTemplate = ({
68
73
  TemporaryPasswordValidityDays: 30,
69
74
  },
70
75
  },
71
- Schema: schema,
72
76
  UsernameAttributes: usernameAttributes,
73
77
  UsernameConfiguration: {
74
78
  CaseSensitive: false,
@@ -126,7 +130,41 @@ export const createAuthTemplate = ({
126
130
  },
127
131
  };
128
132
 
129
- if (identityPool) {
133
+ if (schema) {
134
+ const Schema = schema.map((attribute) => {
135
+ let NumberAttributeConstraints = undefined;
136
+
137
+ if (attribute.numberAttributeConstraints) {
138
+ NumberAttributeConstraints = {
139
+ MaxValue: attribute.numberAttributeConstraints?.maxValue,
140
+ MinValue: attribute.numberAttributeConstraints?.minValue,
141
+ };
142
+ }
143
+
144
+ let StringAttributeConstraints = undefined;
145
+
146
+ if (attribute.stringAttributeConstraints) {
147
+ StringAttributeConstraints = {
148
+ MaxLength: attribute.stringAttributeConstraints?.maxLength,
149
+ MinLength: attribute.stringAttributeConstraints?.minLength,
150
+ };
151
+ }
152
+
153
+ return {
154
+ AttributeDataType: attribute.attributeDataType,
155
+ DeveloperOnlyAttribute: attribute.developerOnlyAttribute,
156
+ Mutable: attribute.mutable,
157
+ Name: attribute.name,
158
+ NumberAttributeConstraints,
159
+ Required: attribute.required,
160
+ StringAttributeConstraints,
161
+ };
162
+ });
163
+
164
+ template.Resources[CognitoUserPoolLogicalId].Properties.Schema = Schema;
165
+ }
166
+
167
+ if (identityPool?.enabled) {
130
168
  /**
131
169
  * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-identitypool.html
132
170
  */
@@ -147,20 +185,99 @@ export const createAuthTemplate = ({
147
185
  },
148
186
  };
149
187
 
150
- if (roles) {
151
- /**
152
- * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-identitypoolroleattachment.html
153
- */
154
- template.Resources.CognitoIdentityPoolRoleAttachment = {
155
- Type: 'AWS::Cognito::IdentityPoolRoleAttachment',
156
- Properties: {
157
- IdentityPoolId: {
158
- Ref: CognitoIdentityPoolLogicalId,
188
+ template.Resources[IdentityPoolAuthenticatedIAMRoleLogicalId] = {
189
+ Type: 'AWS::IAM::Role',
190
+ Properties: {
191
+ AssumeRolePolicyDocument: {
192
+ Version: '2012-10-17' as const,
193
+ Statement: [
194
+ {
195
+ Effect: 'Allow' as const,
196
+ Principal: {
197
+ Federated: 'cognito-identity.amazonaws.com',
198
+ },
199
+ Action: ['sts:AssumeRoleWithWebIdentity', 'sts:TagSession'],
200
+ Condition: {
201
+ StringEquals: {
202
+ 'cognito-identity.amazonaws.com:aud': {
203
+ Ref: CognitoIdentityPoolLogicalId,
204
+ },
205
+ },
206
+ 'ForAnyValue:StringLike': {
207
+ 'cognito-identity.amazonaws.com:amr': 'authenticated',
208
+ },
209
+ },
210
+ },
211
+ ],
212
+ },
213
+ Policies: identityPool.authenticatedPolicies || [
214
+ {
215
+ PolicyName: 'IdentityPoolAuthenticatedIAMRolePolicyName',
216
+ PolicyDocument: {
217
+ Version: '2012-10-17' as const,
218
+ Statement: [DenyStatement],
219
+ },
220
+ },
221
+ ],
222
+ },
223
+ };
224
+
225
+ template.Resources[IdentityPoolUnauthenticatedIAMRoleLogicalId] = {
226
+ Type: 'AWS::IAM::Role',
227
+ Properties: {
228
+ AssumeRolePolicyDocument: {
229
+ Version: '2012-10-17' as const,
230
+ Statement: [
231
+ {
232
+ Effect: 'Allow' as const,
233
+ Principal: {
234
+ Federated: 'cognito-identity.amazonaws.com',
235
+ },
236
+ Action: 'sts:AssumeRoleWithWebIdentity',
237
+ Condition: {
238
+ StringEquals: {
239
+ 'cognito-identity.amazonaws.com:aud': {
240
+ Ref: CognitoIdentityPoolLogicalId,
241
+ },
242
+ },
243
+ 'ForAnyValue:StringLike': {
244
+ 'cognito-identity.amazonaws.com:amr': 'unauthenticated',
245
+ },
246
+ },
247
+ },
248
+ ],
249
+ },
250
+ Policies: identityPool.authenticatedPolicies || [
251
+ {
252
+ PolicyName: 'IdentityPoolUnauthenticatedIAMRolePolicyName',
253
+ PolicyDocument: {
254
+ Version: '2012-10-17' as const,
255
+ Statement: [DenyStatement],
256
+ },
257
+ },
258
+ ],
259
+ },
260
+ };
261
+
262
+ /**
263
+ * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-identitypoolroleattachment.html
264
+ */
265
+ template.Resources.CognitoIdentityPoolRoleAttachment = {
266
+ Type: 'AWS::Cognito::IdentityPoolRoleAttachment',
267
+ Properties: {
268
+ IdentityPoolId: {
269
+ Ref: CognitoIdentityPoolLogicalId,
270
+ },
271
+ Roles: {
272
+ authenticated: {
273
+ 'Fn::GetAtt': [IdentityPoolAuthenticatedIAMRoleLogicalId, 'Arn'],
274
+ },
275
+ unauthenticated: {
276
+ 'Fn::GetAtt': [IdentityPoolUnauthenticatedIAMRoleLogicalId, 'Arn'],
159
277
  },
160
- Roles: roles,
161
278
  },
162
- };
163
- }
279
+ },
280
+ };
164
281
 
165
282
  if (!template.Outputs) {
166
283
  template.Outputs = {};
@@ -8,7 +8,22 @@ test('do not add schema if not provided', () => {
8
8
  test('add schema if provided', () => {
9
9
  const schema = [
10
10
  {
11
- AttributeDataType: 'String' as const,
11
+ attributeDataType: 'String' as const,
12
+ developerOnlyAttribute: false,
13
+ mutable: true,
14
+ name: 'email',
15
+ required: true,
16
+ stringAttributeConstraints: {
17
+ maxLength: '2048',
18
+ minLength: '0',
19
+ },
20
+ },
21
+ ];
22
+
23
+ const template = createAuthTemplate({ schema });
24
+ expect(template.Resources.CognitoUserPool.Properties.Schema).toEqual([
25
+ {
26
+ AttributeDataType: 'String',
12
27
  DeveloperOnlyAttribute: false,
13
28
  Mutable: true,
14
29
  Name: 'email',
@@ -18,10 +33,7 @@ test('add schema if provided', () => {
18
33
  MinLength: '0',
19
34
  },
20
35
  },
21
- ];
22
-
23
- const template = createAuthTemplate({ schema });
24
- expect(template.Resources.CognitoUserPool.Properties.Schema).toEqual(schema);
36
+ ]);
25
37
  });
26
38
 
27
39
  test('should have autoVerifiedAttributes equal email by default', () => {
@@ -31,6 +43,13 @@ test('should have autoVerifiedAttributes equal email by default', () => {
31
43
  ).toEqual(['email']);
32
44
  });
33
45
 
46
+ test('default usernameAttributes should be email', () => {
47
+ const template = createAuthTemplate();
48
+ expect(
49
+ template.Resources.CognitoUserPool.Properties.UsernameAttributes
50
+ ).toEqual(['email']);
51
+ });
52
+
34
53
  test.each([[], null, false])(
35
54
  'should have autoVerifiedAttributes undefined: %p',
36
55
  (autoVerifiedAttributes: any) => {
@@ -41,40 +60,32 @@ test.each([[], null, false])(
41
60
  }
42
61
  );
43
62
 
44
- test.each([true, undefined])(
45
- 'should have identity pool by default or true: %p',
46
- (identityPool) => {
47
- const template = createAuthTemplate({ identityPool });
63
+ describe('identity pool', () => {
64
+ test.each([false, undefined])(
65
+ 'should not have identity pool by default or false: %p',
66
+ (enabled) => {
67
+ const template = createAuthTemplate({ identityPool: { enabled } });
68
+ expect(template.Resources.CognitoIdentityPool).not.toBeDefined();
69
+ expect(template.Outputs?.IdentityPoolId).not.toBeDefined();
70
+ }
71
+ );
72
+
73
+ test('should have identity pool if false', () => {
74
+ const template = createAuthTemplate({
75
+ identityPool: {
76
+ enabled: true,
77
+ },
78
+ });
48
79
  expect(template.Resources.CognitoIdentityPool).toBeDefined();
49
80
  expect(template.Outputs?.IdentityPoolId).toBeDefined();
50
- }
51
- );
52
-
53
- test('should not have identity pool if false', () => {
54
- const template = createAuthTemplate({ identityPool: false });
55
- expect(template.Resources.CognitoIdentityPool).toBeUndefined();
56
- expect(template.Outputs?.IdentityPoolId).toBeUndefined();
57
- });
81
+ });
58
82
 
59
- test('should have identity pool role attachment with roles', () => {
60
- const roles = {
61
- authenticated: 'arn:aws:iam::123456789012:role/authenticated',
62
- unauthenticated: 'arn:aws:iam::123456789012:role/unauthenticated',
63
- };
64
- const template = createAuthTemplate({ roles });
65
- expect(
66
- template.Resources.CognitoIdentityPoolRoleAttachment.Properties.Roles
67
- ).toEqual(roles);
68
- });
69
-
70
- test('should not have identity pool role attachment without roles', () => {
71
- const template = createAuthTemplate();
72
- expect(template.Resources.CognitoIdentityPoolRoleAttachment).toBeUndefined();
73
- });
74
-
75
- test('default usernameAttributes should be email', () => {
76
- const template = createAuthTemplate();
77
- expect(
78
- template.Resources.CognitoUserPool.Properties.UsernameAttributes
79
- ).toEqual(['email']);
83
+ test('should have identity pool role attachment', () => {
84
+ const template = createAuthTemplate({
85
+ identityPool: {
86
+ enabled: true,
87
+ },
88
+ });
89
+ expect(template.Resources.CognitoIdentityPoolRoleAttachment).toBeDefined();
90
+ });
80
91
  });