Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: 0095 cognito construct library #91

Merged
merged 18 commits into from
Feb 17, 2020
Merged

Conversation

nija-at
Copy link
Contributor

@nija-at nija-at commented Jan 26, 2020

#95


Ready for feedback.

Rendered version


By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache-2.0 license

@nija-at nija-at self-assigned this Jan 26, 2020
@eladb eladb changed the title rfc: cognito construct library RFC: cognito construct library Jan 26, 2020
Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial comments

text/cognito-construct-library.md Outdated Show resolved Hide resolved
text/cognito-construct-library.md Outdated Show resolved Hide resolved
text/cognito-construct-library/working-backwards-readme.md Outdated Show resolved Hide resolved
text/cognito-construct-library/working-backwards-readme.md Outdated Show resolved Hide resolved
text/cognito-construct-library/working-backwards-readme.md Outdated Show resolved Hide resolved
text/cognito-construct-library/working-backwards-readme.md Outdated Show resolved Hide resolved
text/cognito-construct-library/working-backwards-readme.md Outdated Show resolved Hide resolved
text/cognito-construct-library/working-backwards-readme.md Outdated Show resolved Hide resolved
text/cognito-construct-library/working-backwards-readme.md Outdated Show resolved Hide resolved
text/cognito-construct-library/working-backwards-readme.md Outdated Show resolved Hide resolved
@eladb
Copy link
Contributor

eladb commented Jan 26, 2020

Please follow the RFC README, create a tracking issues, reference it here in the title, etc.

@nija-at nija-at changed the title RFC: cognito construct library RFC: 0095 cognito construct library Jan 27, 2020
Copy link

@duarten duarten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! :)

text/0095-cognito-construct-library.md Show resolved Hide resolved
custom: {
'myappid': new StringAttr({ minLen: 5, maxLen: 15 }),
'callingcode': new NumberAttr({ min: 1, max: 3 }),
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not an array for custom attributes too?

custom: [new StringAttr('myappid', {minLen: 5, maxLen: 15 })]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't see from this example code how you make a custom attribute required or a standard attribute optional. The sample seems to conflate required == standard, custom == optional (although that might be a Cognito limitation that I'm unaware of).

Would expect to see this though:

new UserPool(this, 'myuserpool', {
  // ...
  requiredAttributes: [
    Attribute.NAME,
    Attribute.customString('myappid', { minLen: 5, maxLen: 15 })
  ],
  optionalAttributes: [
    Attribute.ADDRESS,
    Attribute.customNumber('callingcode', { min: 1, max: 3 })
  ]
});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rix0rrr -

The sample seems to conflate required == standard, custom == optional (although that might be a Cognito limitation that I'm unaware of).

That is exactly Cognito's modeling.

Quoting from the documentation for standard attributes -- "These attributes are available as optional attributes for all users. To make an attribute required, select the check box next to the attribute. ".

Quoting from the documentation for custom attributes -- "cannot be required"

Given this information, is my modeling ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@duarten - switched this from an array to map based on another comment. I believe the map-style is a bit more ergonomic and human friendly.

on the user pool via the `from` property, and the `replyTo` property to configure the email where replies are sent.

User pools can also be configured to send emails through Amazon SES, however, that is not yet supported via the CDK. Use
the cfn layer to configure this - https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't this going to be supported? Seems like it could be a simple switch.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes if CFN can do it there shouldn't really be a blocker.

Or is it because SES doesn't have appropriate L2s yet?

Copy link
Contributor Author

@nija-at nija-at Feb 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is it because SES doesn't have appropriate L2s yet?

Correct!

Seems like it could be a simple switch.

It's not a simple switch. A bunch of configurability comes along with it and without proper class modeling in SES, this will look weird.

At the same time, given the extended nature of Cognito's features, something had to be cut for the first round of implementation and this got cut. This is not saying we will not support it but just not yet. Users can always avail this configuration via escape hatches, albeit it won't be clean.

});
```

At least one of `welcomeEmail` or `welcomeSms` is required if `selfSignUp` is set to `true`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be worth making a class with factory functions for this?

new UserPool(this, 'myuserpool', {
  signUp: SignUp.byEmail()  // Has some nice defaults that can be customized
});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've flattened this mapping out by one level. What do you think about this now? Do you think it still need factory functions?

custom: {
'myappid': new StringAttr({ minLen: 5, maxLen: 15 }),
'callingcode': new NumberAttr({ min: 1, max: 3 }),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't see from this example code how you make a custom attribute required or a standard attribute optional. The sample seems to conflate required == standard, custom == optional (although that might be a Cognito limitation that I'm unaware of).

Would expect to see this though:

new UserPool(this, 'myuserpool', {
  // ...
  requiredAttributes: [
    Attribute.NAME,
    Attribute.customString('myappid', { minLen: 5, maxLen: 15 })
  ],
  optionalAttributes: [
    Attribute.ADDRESS,
    Attribute.customNumber('callingcode', { min: 1, max: 3 })
  ]
});

});
```

*Note* that, custom attributes cannot be marked as required.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha. Well I'd still expect to see the previous code with a runtime check or something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow this comment. Can you re-state?

// ...
// ...
security: {
mfa: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd like to encourage a factory function here again, and same for passwordPolicy. Or flatten out the properties into the top-level props object.

We have a construct library design guideline to flatten out the properties namespace.

on the user pool via the `from` property, and the `replyTo` property to configure the email where replies are sent.

User pools can also be configured to send emails through Amazon SES, however, that is not yet supported via the CDK. Use
the cfn layer to configure this - https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes if CFN can do it there shouldn't really be a blocker.

Or is it because SES doesn't have appropriate L2s yet?

documentation of the `identityProviders` property has more details on how to configure an identity pool with each of
these external providers.

> Internal Note: IdentityPool-SupportedLoginProviders takes a JSON with all of the providers configured.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will provide factory functions for the common use cases, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The subsequent paragraphs and code snippet is how I propose to model this JSON. This should be sufficient, no?

new IdentityPool(this, 'my-awesome-id-pool', {
// ...
// ...
authenticatedRole: authenRole,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to autocreate these?

const pool = new IdentityPool(this, 'my-awesome-id-pool');

bucket.grantRead(pool.unauthenticatedRole);
bucket.grantReadWrite(pool.authenticatedRole);

Especially since I believe the assumedBy parameter for the roles is going to be quite tricky in practice, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to autocreate these?

Yes, there should be a default role created for these with the authenticatedRole property to specify an existing role. I seem to have missed this and will add that in.

Especially since I believe the assumedBy parameter for the roles is going to be quite tricky in practice, no?

The doc states -- "The CDK, by default, adds a trust policy with these configured to all roles used by the IdentityPool. To disable this, set the configureRoleTrust to false."

Essentially I'm hoping to call role.assumeRolePolicy.addStatements(...) and add the correct trust parameters.

Does this satisfy?

// ...
// ...
roleMappings: {
'facebook': new FacebookRoleMapping({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't the key be implicit in the mapping class?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, doesn't it make sense to push these mappings into the Facebook provider?

new IdentityPool(this, 'myidentitypool', {
  // ...
  identityProviders: [
    IdentityProvider.Facebook('7346241598935555' , {
      roleMappingRules: [
        {
          // if the identifier of the user as returned by facebook is 'boris'
          claim: FacebookRoleMappingClaim.SUB,
          matchType: MatchType.EQUALS,
          value: 'boris',
          role: adminRole
        }
      ],
    })
 ]
});

Copy link
Contributor Author

@nija-at nija-at Feb 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I like the idea of merging identityProviders and roleMappingRules.

text/0095-cognito-construct-library.md Outdated Show resolved Hide resolved
new UserPool(this, 'myuserpool', {
// ...
// ...
signInType: [ SignInType.USERNAME, SignInType.EMAIL ],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would we have convenience methods to add/remove sign-in types?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you elaborate?

Copy link
Contributor

@shivlaks shivlaks Feb 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so the constructor is one way to initialize with supported sign-in types. would UserPool have methods to the UserPool class -> addSignInType

use case I'm thinking of is conditionally allowing different sign-in types based on stage in a CI/CD pipeline

I'm not sure how it's currently handled, does it replace the UserPool altogether or is this an attribute that can be updated?

eladb
eladb previously approved these changes Feb 11, 2020
@nija-at nija-at merged commit 1f92050 into master Feb 17, 2020
@nija-at nija-at deleted the nija-at/cognito-l2constructs branch February 17, 2020 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants