How to Prevent identity provider attributes to be updated with UpdateUserAttributes - amazon-web-services

I am using AWS Cognito with Federated identities to manage access to my app.
The custom social identity provider that I use returns me some custom user attributes.
The attributes are correctly mapped as user attributes in my user pool.
I recently realized that my users could change their own attributes using their accessToken. (using aws cognito-idp update-user-attribute for example). Is there a way to forbid this? I basically always want to keep the value returned by the provider.
I originally thought I could mark the attributes as non-writable, but this does not work as I need the social provider to be able to write it.
Also, the doc mentions that I should keep it mutable.
Would using DeveloperOnlyAttribute work ? I did not try it so far as the doc basically says it is deprecated.

Related

AWS DynamoDB with Cognito user-scoped access?

I am using AWS Cognito for user management. I want users of my application to store their data in DynamoDB. So I need user-scoped access (User A can write data and only read data added by User A, User B being able to only read data added by User B).
Docs suggest the ability to have row-level and column-level fine grain access: (https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/specifying-conditions.html).
BUT I am not using IAM, I am using Congito users (want it scoped to each user, not a Role/Group). This doc suggests you can use Cognito ID: (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_dynamodb_items.html).
However, according to this StackOverflow question (How to use DynamoDB fine grained access control with Cognito User Pools?), it's not what I am expecting?
Does AWS support my use-case? Lot of docs but its not clear if my use-case is supported.
You need to use Cognito identity pool. Cognito identity pool acts as an identity broker. When a Cognito user authenticates using the user pool, then Cognito provides JWT tokens. User can use ID token provided by Cognito user pool and Cognito identity pool can take the token and provide temporary IAM credentials.
I am familiar with a similar use case as of yours. In that use case, user who has written data to S3 can only modify/delete that data. In this case, you can create new S3 folders (prefixes) for each user's Identity ID (provided by Cognito identity pool) and that particular user can access data under that S3 folder only.
I am not much familiar with DynamoDB access control, hence not able provide the exact solution now. You can try a similar approach as the above one.
https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-identity-pool.html

Which parameter can be used as primary key from AWS Cognito?

I read some questions and answers about my issue, but I still don't know the answer.
Can I use the userSub in AWS Cognito as primary key?
AWS Cognito: Difference between Cognito ID and sub, what should I use as primary key?
First, I will try to describe my case.
I want to create an application with spring boot as a resource server that uses oauth2. Then to save me some time with user management, I was hoping to use AWS Cognito since it allows me to create users as admin. I can set it up that it won't let other people sign up for themselves, which is crucial for me since my app will have restricted access; the admin will manage that.
Now to my question, which field of AWS Cognito can I use as the primary key for keeping user-specific data in my DB? I read that neither usernamenor sub is correct.
username can be changed, for example, and sub is globally unique, so it can't be restored. Is there any way to create a custom field where AWS Cognito will autogenerate UUID that I can use, and if I had to restore the user pool, I would have an option to set this field?
You can still go with username. If it is ever changed, just update your database to reflect this change.
You can also create a custom attributes in user pool. You can use that to store a self generated id. As for automatically generating this, you can have a post confirmation lambda trigger that will use adminUpdateUserAttributes to assign a unique id.

AWS Amplify Graph API that can be accessed without authorization (login)

I am new to Amplify and I am building a simple list of items (votes) with GraphQL. While the items visibility should be public (read access) without authentication, creating, updating and deleting should be done authenticated via Cognito user pool.
The model can be seen in following AWS Amplify Admin UI screenshot:
I am not able to set the read access to Anyone (since this option is greyed out). Furthermore following statement in the AWS docs puzzles me a bit:
While the API endpoints are publicly reachable, they never allow unauthorized access.
GraphQL API Security with AWS AppSync and mplify
Am I on the wrong track when I want to publish a Graph API with Amplify to the public without authentication? Did I misconfigure my API or is there a way to bypass authentication? Honestly I am not sure if I understand the concept behind this.
For me it is hardly imaginable that only authenticated users can access the API. Respectively I assume there are many other cases (beside my one) where accessing the API without authentication is a requirement.
Thanks in advance for your feedback.
PS: #52601860 seems to be a similar question.
For me, restricting the public access to read operations in the schema file (amplify/backend/api/<name>/schema.graphql) was sufficient:
type SomeModel #model #auth(rules: [{allow: public, operations: [read]}]) {
id: ID!
# ...
}
You can check those permissions via amplify status api -acm SomeModel.
Do not forget to provision those changes by running amplify push.
This is achievable in AppSync. I think what you are looking for is a way to use different authentication mode for different API. So some API like query can be done by any unauthenticated users(i.e open to public) while others ike mutation is guarded behind the authentication.
One simple approach would be to enable authentication via Cogntito Identity Pool
Identity pool can be configured with two roles, one authorized role and another unauthorized role. Unauthorized role policy can be updated to, default ALLOW permission on AppSync query endpoint.
Here is a sample guide by Daniel Bayerlein which you can follow to achieve this: https://dev.to/danielbayerlein/aws-appsync-without-authentication-3fnm
It has detailed step and configuration change that is needed.
One more references for your help, in case if you just want to manually update the Cognito identity pool permission manually from AWS console: https://dev.to/sedkis/setting-up-aws-appsync-for-unauthenticated-users-1879
I hope this would be useful. Please feel free to reach out in case if you get stuck. Would be more then happy to assist in your configuration.
When you evoke authentication I hope you are aware that users can register and be members of Aws Cognito user pools. In this case you can adjust the authentication within your own model the way it's specified in the first answer above or maybe give Groups within Cogito Userpool the right access
ex: { allow:groups , groups:["Admin"] , operations:[create,read, delete, update]}
You can let all other Queries accessible to AWS Congnito Users and Groups as well the way you plan you amplify App. Don't forget to check the
aws-export.js
"aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS"

Different access tokens for users using aws Cognito for authorisation

I am trying to provide differential access to services behind an aws api-gateway, lets say simplistically split into 2 user groups user-a and user-b that each can access /routeA or /routeB but not the other.
User Authentication is via Cognito User Pool with 2 user groups defined. Front End is React and Amplify.
I am going round in circles with this having tried a few approaches. Running this decision tree select-auth-method points to using Cognito AuthZ which is fine in itself as I am using Cognito for AuthN.
So far none of the examples/tutorials/articles/videos have demonstrated how to block some users while enabling others. I have tried:
Cognito User Pool Authorizer - identity token based but seems to just AuthZ any logged in user. I could possibly attach IAM Roles to the user groups ?
Custom Lambda Authorizer - Works well on checking for the valid user-group in the Access Token and dynamically creating the required permissions but, some additional latency from a λ and no check that the access token is current. Starts to feel like I am writing code for a system that exists somewhere else?
Cognito OAuth - Spent some time trying to understand this. So I create a Resource Server attached to the Cognito app client and create some custom scopes that I can then reference in the Api-g Authorizers. Fine, but how to I create two different access tokens for the users that have different scopes? So far my understanding seems to suggest that it is another binary AuthZ approach, but articles suggest (but don't demonstrate!) it is capable of granular permissions? I must be missing something.
I also saw this 2017 answer but things may have moved on with better approaches?
I am minded to go OAuth route as it seems more of an industry standard approach and promises much but need a bit of insight as to how to enable different access tokens for different users.
So the answer is that Cognito does not implement the OAuth2 functionality that I need but others do. Given the following excerpt from AuthO docs, this feels like a better solution path...
It would be very useful if we could just restrict endpoints on the cognito:groups that are in the tokens,but this functionality isn't there.
There are a few options that might suit you, one is just put the users in different user pools and create different authorizers for those pools and assign them the routes.
Another is OAuth scopes, you can create two app clients each with different scopes then configure the scopes in APIGW. Note that in this case you need to pass the access token to APIGW not the ID token.
In either case if you are using Hosted UI you will have a problem as you will now have two Hosted UIs and it may not be straightforward knowing which one to display to a user until they have entered their email address.
BTW if you are not using Hosted UI you will be unable to use OAuth scopes.
You can also assign IAM roles to the cognito:groups and allow these access to the APIGW resources you want. This is probably the easiest method although it is not as simple as you would probably like.
The final way I can think of is writing a custom authorizer, I would avoid this if you can, I have done it a few times now and it has never been enjoyable.
Your requirement seems to be to authorise users depending on their permissions, as opposed to needing different types of access token.
I would recommend sending the Cognito access token to the API and receiving it like this in the API:
Level 1: Validate the access token first to check it is not expired etc
Level 2: Consider checking a scope to ensure that the token is for your API
Level 3: Check finer grained claims such as group membership or anything else that makes sense for your scenario. Your API can get groups by sending the access token to the Cognito user info endpoint.
DESIGN PATTERN
This blog post of mine describes the pattern and use of claims caching.
Here is some lambda authorizer sample code, though the same behaviour can be implemented in your API directly and my blog has some examples of this:
Cognito Claims Based Authorization

AWS Cognito - createIdentityPool - Where to get ProviderName and ClientId?

I'm attempting to use AWS Cognito to aid support for multi tenancy within my application.
https://aws.amazon.com/blogs/apn/managing-saas-users-with-amazon-cognito/
Provisioning User Pools
Assuming you were to associate a single user pool with each tenant,
you would need to introduce provisioning automation that would create
a tenant’s user pool during the sign-up process. This would also
require automation that configures all the other moving parts of
Amazon Cognito to declare and associate the user pools with the other
Amazon Cognito constructs and security policies.
The basic steps here would be to first create a user pool for the
tenant and apply any tenant-specific customizations or policies (these
would typically be the same for all tenants). Then, you’d need your
automation to provision and configure an identity pool. Finally, you’d
have to associate the identity pool with your newly created user pool.
The process is a bit more involved than that, but these are the key
concepts you need to have in mind as you think about how to add this
automation to your tenant creation lifecycle.
AWS provides a series of APIs that you can use to implement your
provisioning automation model. These APIs are available for a number
of different languages and environments.
So far I've been able to use the SDK to create many of the bits and pieces but am struggling with createIdentityPool () specifically CognitoIdentityProviders
The documentation states that CognitoIdentityProviders should contain...
ProviderName — (String) The provider name for an Amazon Cognito
Identity User Pool. For example,
cognito-idp.us-east-1.amazonaws.com/us-east-1_123456789.
ClientId — (String) The client ID for the Amazon Cognito Identity User
Pool.
ServerSideTokenCheck — (Boolean) TRUE if server-side token validation
is enabled for the identity provider’s token.
Where should I be getting ProviderName and ClientId from?
I have vars holding the values returned from createUserPool() and createUserPoolClient() but can't see anything within them that fits.
Any help appreciated.
ClientId is just the unique identifier for your client.
ProviderName is a constant string of the above format, just plug in region and user pool id where appropriate.
The easiest way to do this is via the Cognito federated identities console. It just takes in a user pool id and client id, which you get upon creating them in the Cognito user pools console.
If creating the identity pool from the SDK is a must, you can just get these values from the Cognito user pools console. Just look for the pool and client in question.
If using the console is out of the question, you can call ListUserPools and ListUserPoolClients to get the right ids.
I searched and couldn't find a definitive way to find or format the ProviderName.
I eventually figured it out from the CloudFormation example here.
ProviderName in the case of Cognito has this simple structure:
cognito-idp.{region}.amazonaws.com/{user_pool_id}
I've also found cases where it's necessary to also append the user pool client id like so:
:{user_pool_client_id}