I am using AWS Cognito. I have a pretty common scenario: users can register in different roles. Depending on the role different user attributes are required, so I need to use different user pools.
Now a user wants to upgrade from role A to role B - thus I would have to move his account from one pool to another. Is this possible with AWS? The response in Can you export/migrate users out of AWS cognito, does it cause vendor lock-in? seems to indicate the opposite.
If not possible this way, what would be a viable solution to achieve requiring different user attributes depending on different user roles with AWS Cognito. (NOTE: requiring / verifying them only on the front end is not a viable solution)
I know this question is a bit dated, but it is possible that this scenario is best solved by using Groups instead of a separate user pool for each role. See here
If you reach this link to find out how to transfer users to a new pool (for instance, you needed to create a new user pool in order to change how your users log in), then there isn't a built in way to do this. However, there are solutions that you could build in order to migrate users, which is referenced here:
Create your new user pool.
Modify your client to do the following:
On failed sign in with new user pool, attempt sign in with old user pool.
If existing user pool sign in is successful, use the username and password that was submitted to the existing sign in to create a user on the new user pool.
Possibly do something to remove the user from the old user pool or mark as migrated.
You can export users and import them to a new user pool with a CSV file, but your users will have to change their password.
Related
Why when creating a new AWS account via the AWS Control Tower Account Factory does an SSO user also need to be created? There is already an email for the root user can through AWS SSO you can assign users/groups anyway, so what purpose does it serve to make an SSO user as well? You may not want a new user, or should I simply put the email of an existing SSO user?
This is something that is not that intuitive, indeed. Feels like a wrong UX.
However, there is a reason behind that. Let's check the docs first:
The SSOUserEmail can be a new email address, or the email address
associated with an existing IAM Identity Center user. Whichever you
choose, this user will have administrative access to the account
you're provisioning.
The AccountEmail must be an email address that isn't already
associated with an AWS account. If you used a new email address in
SSOUserEmail, you can use that email address here.
As we see, the general approach is something like that we could not create a state, where we cannot access the new account by default.
So either it will create a new user, or will understand that it is an existing user, and using that.
So you can type your SSO email, and will sort out the PermissionSets later, or you could use a default controltower admin user for just this reason.
You could create a new SSO user for every account too, but to be honest it just sounds wrong. (maybe with email aliases could work, but still unnecessary, redundant)
You could use the same address for root and the correspondent SSO, but it feels counterproductive too.
TL;DR:
For me the less painful approach is using my own SSO account, and later tuning the permissionsets.
The general approach is perhaps to have a ControlTower shared user, for kind of an account owner and backup user.
The doc: https://docs.aws.amazon.com/controltower/latest/userguide/provision-as-end-user.html
Help is required in the following problem we're facing 😔
Any tip would be much appreciated!
Details and environment:
A multi-tenant application that aims to provide a dedicated tenant per customer (organization), in order to achieve full separation.
AWS Cognito user pool as my users' datastore and authentication provider.
an "AWS Cognito user pool" per customer (org).
Role management - based on the built-in user pool groups. Group per role and the server-side verifies that a user's access token includes a group name in it's embedded group's list.
So far so good and everything is working as expected, using AWS Amplify's SDK, for the client side's implementation. Amplify performs well and allows me to do whatever I want. The server verifies group belonging etc.
The problem:
I want to restrict non-admin users (that doesn't belong to the "admin" group) from performing certain Cognito actions via Amplify.
2 Examples:
I want to disable non-admin users' ability to modify a specific attribute's value, via Amplify.
I want to disable non-admin users' ability to modify MFA settings for themselves, via Amplify.
The actual problem started when I wanted administrators to be able to set MFA (enable/disable) for other users, but in Cognito (as I understand it) only a user can set his own MFA settings.
What I saw and already tried:
Set read/write permissions for user attributes. So the specific attribute I want to protect is modifiable only via API calls with developer credentials. That way, admins can call my server to ask for attribute modification. The server verifies the role by a group belonging according to the access token and calls Cognito API. The problem with that solution is that it covers only the attribute modification scenario.
Create an AWS Cognito identity pool for each of the user pools. For every group in every user pool, create an AWS IAM role with a policy that would restrict or allow the wanted behavior. The could actually work. The problem with that solution is that it feels like a super-duper overkill, plus it requires me to create an extra identity pool and an IAM role for each user pool. It means that every new customer that joins the service, would require (1) user pool, (2) Cognito client application, (3) identity pool and (4) IAM Role (instead of just a user pool and Cognito client app). Essentially, implementing this solution.
The real question:
Can I restrict users in a certain group from performing actions on themselves, such as disabling the MFA (even that the user-pool's MFA is set to "Optional")?
Thank you all so much! any help would be appreciated!
Well... After long research, we have come to the understanding that there is no proper right way. Every possible solution has its own pros and cons. A consultant meeting with AWS's experts taught us that:
Options Overview:
[Server Side Only] - Solution #1 that I proposed is exactly as described. Drawbacks are the same. It could work, and access to user-attributes will be restricted. Any other action that another client would make will not be blocked.
[Identity Pools] - Solution #2 that I proposed is the most accurate one. Yet I described it with one big mistake: one identity-pool can serve multiple user-pools! So essentially, we could create only one IAM role and one identity-pool per app's role. Then we match every user-pool we want to that same identity-pool and when introducing a new role to the app - just create a new group in the user-pool and match it to the IAM role. This solution is not as complicated as thought, and it would definitely do the trick. As a bonus, you'll get the ability to control and allow access to different AWS services. That being said, it still requires management and effort.
[Post-Auth Lambda] - Solution #3 that was not mentioned here, and I started to work on a day after posting this post. I blocked the write permissions of a new boolean custom attribute called "MFA". It indicates the desired MFA configuration for the user. Only a server could edit its value (and users with the admin role will have access to the server's API endpoint that can modify it). We've deployed a lambda function that would be triggered after successful authentication (post auth trigger in Cognito user-pool). It would verify a match between the desired and current MFA configurations for the authenticated user. If there is a mismatch, throw the user out because he did something that is not allowed.
*To be exact, we created one more custom attribute called "mfa_status" and it is set to true after the user has set it's MFA configurations. The lambda checks if both MFA and mfa_status are true and the real current MFA Configurations are false. if this is the case - the user is thrown out.
The Chosen One:
The solution we picked eventually is #3 (Post-Auth lambda) as it is the most detached solution. It does not require any mix with our server or client's code, any special configurations that are specific to a user pool and it still allows us to keep working with the Cognito's Amplify SDK as a client.
Thank you all for your time, I hope this post would help someone in the future.
I'm a bit confused on which ID to use for the following purpose:
There is an online book store with books and users. Each user can have many books. Books are stored in a DynamoDB table alongside with their user IDs associated to them.
Question is, which user ID to be used? Pool user ID or Identity user ID? Thanks.
If you want the users to be able to read and write directly to the table you need to use the identity pool ID, because that's what's in the authentication context when IAM evaluates the request.
If that's not the purpose and you just want to keep track of the users for internal purposes it might be easier to use the user pool ID. With the user pool ID you can look up user attributes etc., which is not the case with identity pool IDs.
Another way of saying this is that if you want to leverage IAM for authorization (granting access to things) you need to use identity pool IDs (federated identities), but if you are going to handle authorization yourself in your application code and never let users access AWS resources directly, and not let users log in through other authentication mechanisms, then using user pool IDs makes more sense.
You can think of it this way: User Pool provides a login method (i.e. an authentication method).
Whereas Identity Pool provides a way to create a user identity based on a single or multiple login methods (e.g. Facebook login, Google login, Cognito User Pool login), and in turn, create IAM permissions tied to that identity. It's more about Authorization - what a user with this identity can do.
That said, you can still perform Authorization using just User Pool User Ids. You just have to write the custom logic yourself based on the information about that user stored under User Pool Attributes (e.g. their email or name), to allow or deny them access to certain books.
If you eventually want to enable the user to use multiple sources of logins (e.g. Facebook login, Google login, AWS Cognito login), then consider using Identity Pool user id.
In most cases, if you make users login via an app and access the resources (books in this case) via the app, storing the User Pool User Id makes things easier. Cognito generates a secure User Pool User IdToken which contains the User Id on login. The app can just pass this token along with the request for your backend to allow/ deny the request.
User pools stores the user records while identity pool has the necessary permissions available for the user. So in this case you need to use user pool Id
We have implemented a Developer Identity Provider using our custom user auth service and we have an Identity Pool connected to it with many Identities saved. Right now, we're evaluating to move our user table to a User Pool connected to the same Identity Pool and use the mobile-hub library.
The question is: After the import, could Cognito detects if a user with a specific username already exists in the Identity Pool and doesn't create it again (with another Identity)? Self signup is activated.
UPDATE for clarification:
Our identity pool has near 1000 existing identities. All of them were created before the existence of User Pool feature. They were created using the "Developer Authenticated Identities Authflow" (check link), and the external "Developer Provider" is a simple user table. Each identityId in the Identity Pool is associated to an existing identity (record) in our external user table.
Now we want to use AWS Mobile-hub lib in our iOS app and a User Pool connected with the existing Identity Pool. We want to start adding new users to our User Pool but for existing users, they already have an identity created in the Identity Pool. What to do in that case?
Seems to be that, at the moment of first login, Cognito doesn't have a mechanism to detect if a user already has an IdentityId created by another auth flow (Facebook, Developer Provider).
You could do one of a few things, because as you noted, Cognito does not totally handle this for you.
If you're all in on user pools, you could use the import user feature to transfer your users.
Alternatively, on sign in, you could check if the username exists in your user table. If so, you could either sign them in by that, or you could transfer them over to user pools then and there with a lazy load.
I'm attempting to develop an application architecture almost exclusively on top of AWS services.
This application has both User and Organization "entities". As one might except, a User may be an admin, role-x or role-y of one or more organizations. (role-x and role-y are just placeholders for some role with some set of specific permissions. A User may also be standalone (that is, not have a role on any Organization).
Our current thinking is to use DynamoDB to store organization and user specific data. For users this may include some basic information (address, phone number, whatever), and for organizations it may include fields like "mission statement", "business address" and so on.
An admin of an organization would be able to edit all organization fields, whereas a role-x might only be able to update "mission statement" while reading all other fields.
Since I mentioned that a single user may have roles on many different organizations, that might look something like:
user1:
organizations:
123: 'admin'
456: 'role-x'
789: 'admin'
It's also worth noting that these role assignments are modifiable. New or existing users may be invited to take on a specific role for an organization, and an organization may remove a user from a role.
This is a fairly straightforward type of layout, but I wanted to be very clear about the many-to-many nature of the user, org and roles.
I've been reading IAM and Cognito documentation, as well as how it relates to fine-grained control over DynamoDB items or S3 buckets - but many of the examples focus on a single user accessing their own data rather than a many-to-many role style layout.
How might one go about implementing this type of permission system on AWS?
(If policy definitions need to be updated with specific Identities (say, for an Organization), can that reliably be done in a programatic way - or is it ill-advised to modify policies on the fly like that?)
The above answer is outdated.
AWS has added Cognito-Groups recently. That provides more flexibility
You can use technique described in the article to achieve that:
https://aws.amazon.com/blogs/aws/new-amazon-cognito-groups-and-fine-grained-role-based-access-control-2/
Unfortunately the kind of permission system you are trying to implement is not possible with Cognito at the moment. With Cognito you can currently create unique identities for your users in an identity pool. Users can authenticate using any external provider such as Facebook, Amazon, Google, Twitter/Digits or any OpenId Connect Provider. Users can also authenticate through your own backend authentication process. After the user authenticates, Cognito creates a unique identity for that user. There’s a concept of an identity, but there’s no concept of groups. All users/identities within a one identity pool can get credentials from roles associated with that identity pool. Currently you can specify two roles: One role for authenticated identity and one role for unauthenticated identity. There’s no such feature at the moment where you can specify multiple groups for each identity and specify role on that group.
For more information on Cognito, you can refer to
https://aws.amazon.com/cognito/faqs/
http://docs.aws.amazon.com/cognito/devguide/getting-started/