I'm developing a mobile app that must access some AWS resources, so it needs authentication to AWS endpoint. The app doesn't manage users (sign-in, sign-out, register and so on).
My first solution was to create a IAM user dedicated to the mobile app and embed its credentials in the mobile app code. The app authenticate itself to AWS using the embedded credentials. It works, however AWS suggests to avoid embedding credentials directly in the app.
I think a better solution is Cognito. Because I don't need users management, I should use unauthenticated (guest) identity to request temporary AWS credentials.
However I don't understand why a guest Cognito identity is more secure than an embedded credentials. The mobile app receive a temporary AWS credentials by sending a Cognito Identity Pool ID, that is a long-term "number" embedded in the mobile app. If someone is able to find this Identity Pool ID, she can receive AWS credentials and access AWS resources as my official mobile app. It seems there's no difference between embedded AWS long-term credentials and huest Cognito access.
Why Cognito solution is better than embedded AWS credentials?
If you are creating unauthenticated access using identity pool, you are allowing public to access your AWS resources. Make sure you write your policy carefully and it won't matter if you use a single IAM user or cognito unauthenticated access as far as security is concerned.
Using federated identity will provide you benefits like getting statistics on usage and adding triggers to events. Also keep in mind that creating a single IAM user and then allowing multiple people to use these credentials is a "hack" way of doing what cognito federated unauthenticated idenity was designed to do. You might run into unexpected complications later if AWS decides to throttle this behavior of IAM.
Related
I have an application (node.js) that need an Authentication and authorization.
My app need access to postgres database and also need a Inheritances (roles etc.)
One option to implement that is using the cognito service of aws (the app will host on aws properly - not sure about that)
so the questions is
Is cognito service support the authorization for node.js with database that is not services on aws? (I read that "identity pool" is for aws services like mariaDB)
If my app will be on heroku (not on aws), I will also be able to use with cognito services (for authorization)?
Is cognito support roles/users inheritances ?
Tnx
Cognito identity pool is used for granting access to aws services. User pool is used to exchange user credentials for tokens which can contain additional information about the user once decoded. So yes, you can use user pool just for authentication. Your user attributes can contain information related to the services this user needs to access.
However, if you plan on storing database credentials, I suggest you use AWS secrets manager to store your DB credentials and grant the cognito user access to this secret. You'll need to use both user pool and identity pool in this case.
Not directly, but you can use it to access secrets manager where you db credentials are stored.
Yes you can use cognito anywhere. It will be connecting to AWS to grant you tokens however. And these tokens are only recognized on AWS. Which is why you need to use them to access other secrets that can be used to access whatever other services you want.
Cognito supports groups. I'm not sure if that's what you mean by inheritences. You can have token based roles with groups.
I am managing multiple accounts in AWS: each company we have as client has its own organization and they have some aws resources attached to it.
At the moment, users login with user and email using Cognito (there is a pool on our root account) and get a JWT token. One of the information in this token is the aws_access_id and AWS_SECRET_ACCESS_KEY of a user in the client account. Then, when they make a request in our api, they use this token and i can make request to the aws api.
This is a poor design since the token can be decoded easily and anyone can then get the aws credentials for their account (they are not encoded).
Now, I don't know how I could improve the flow though... Keeping Cognito would be good but protecting my tokens would be really important. What would you suggest?
EDIT: I tried using identity pools. With identity pools, you can connect with email/password with cognito and receive aws credentials that give access to a specific role. This role can then access the resources of another account. You "just" need to create one role per account. The problem I see with that is providing directly the access,secret,session to my client. Any alternative?
I am currently investigating the use of Federated Identities and from the many examples I have read, it seems to be a way to grant users temporary credentials to various AWS services. For my case, the API Gateway is all that the user will interact with, since the API server is the one making calls to other services like S3 and DynamoDB. I like how permissions are controlled using IAM, but I'm failing to see any other appeals of Federated Identities. User Pools itself already supports password/fb/google/etc sign in, the only downside I see with user pools is that I'll need to do the authorization manually in the API layer. Is there something else I am missing with Federated Identities? Is it worth it given my use of only API Gateways (externally).
It all depends on the way that you will secure your API Gateway endpoint.
If you secure your API using AWS IAM, you'll need a way to convert your authentication tokens in AWS IAM Roles. For that scenario you can use AWS Cognito Idp (not the User Pool) or AWS Federated Identities. The difference is: using AWS IAM Federated Identities you will need to call AWS STS AssumeRoleWithWebIdentity in your frontend code. If you use AWS Cognito Idp this is done for you. . (AWS strongly suggest that you use the Cognito Idp in that scenario)
If you secure your API using AWS Cognito User Pools you don't need to use AWS Federated Identities. You can connect API Gateway directly to AWS Cognito and the service will enforce the controls for you. In that case you'll need to have a Cognito User Pool.
You also have a choice to use Custom Authorizers. In that scenario you will implement a lambda function that will evaluate your request and decide if it is authorized or not. In the same way, you won't need federated identities.
And finally you have the API Key authorization, that you already mentioned that is not applicable to your use case.
We're building an application using AWS App Sync, we're still in a very early stage.
Our application has a restricted area, through user sign-in, which is being managed via aws cognito users pool. And this is fine.
We're having issues on the public area which doesn't require any authentication.
How can we protect these public endpoints?
We're having some doubts about hard coding the api key (that we know can be rotated), is it a good practice (documentation page says that it isn't ideal for production)?
Is there any way to authorise the origin? (aka, any request coming from www.foobar.baz is ok)
I would suggest using Amazon Cognito Federated Identity to control authenticated and unauthenticated access to the api. In order to do use Amazon Cognito Federated Identity with AWS AppSync, you need to use AWS IAM based authorization.
For the authenticated access you can use Amazon Cognito User Pools and federated to Amazon Cognito Federated Identity and since the federated identity can also allow for unauthenticated users it will allow you to control some api's which can be made public via an IAM policy.
For more information please read the AWS IAM Section of our security guide here
Under your AppSync app's Settings menu, where you set the User Pool Configuration, there is an option to set a default action. You can change this to DENY and all unauthenticated requests will be rejected. The alternative approach is to ALLOW everything, and manually add #aws_auth directives to every query/mutation/subscription field that you care about restricting.
In the AWS Xamarin SDK docs, the Amazon Cognito Identity API documentation for GetOpenIdTokenForDeveloperIdentity() says in its second paragraph that "You must use AWS Developer credentials to call this API."
Now, the general idea is to try to never expose API secrets & keys in the source code especially if there are other mechanisms available. AWS provides the IAM mechanism so that we can assume a role and then we can define which privileges can be assumed by that role.
But this text mentioned in bold above, does it mean i cannot use IAM roles and/or policies to call those APIs? Does it mean i HAVE TO include my accessKey and secretKey in my application source code?
Edit:
AWS provides the Cognito mechanism through which we can requested temporary credentials via
`credentials = new CognitoAWSCredentials ("IDENTITY_POOL_ID", "REGION_NAME");`
without directly using Developer credentials like the accesskey and secretkey etc.
But this text mentioned in bold above, does it mean i cannot use the credentials obtained via cognito because these credentials were not produced with Developer credentials?
Trying to figure out this new cognito thing.
You can use IAM roles to call this API, same way you would call any other AWS sigv4 API. Purpose of the text is to emphasize that unlike other Cognito unauth APIs (getId, getOpenIdToken, getCredetialsForIdentity) you will need to call GetOpenIdTokenForDeveloperIdentity from your server and with AWS credentials. These credentials can be obtained with IAM user or IAM roles.
Edit:
Cognito is meant for vending credentials on the client side applications, for eg: Mobile apps. Typically credentials are vended after federating with social identity providers, eg: Facebook, google, Amazon etc.
The API 'GetOpenIdTokenForDeveloperIdentity' was introduced to allow you to federate with Cognito with your own authentication system. If you don't have your own authentication system, you should not be using this API. This API is meant to be called from your server side application. Of course you can use Cognito to get the credentials on server side and call GetOpenIdTokenForDeveloperIdentity, but that's not what Cognito is meant for. Simpler will be to just use credentials with help of IAM on server side.