axelwittmann
axelwittmann

Reputation: 369

How do I use Cognito purely to authenticate users for S3 use

I have read this post and the AWS reply on How do I use a Cognito token with API? and this one how to use AWS cognito with custom authentication to create temporary s3 upload security token

I am not yet clear whether there is a simpler solution to securing S3 access.

I have a mobile client and a node.js backend. The client authenticates with the backend and receives a jwt accesstoken for further calls to my backend. In addition to communication with my own backend, users should be able to upload and download files to and from S3. I am looking for the simplest solution to make sure only users who have a valid accesstoken for my backend can upload to S3.

Can I do the following (this is based on this blog post http://blog.backspace.academy/2015/03/using-cognito-with-nodejs-part-2.html):

  1. Client authenticates with my custom node.js backend and receives custom accesstoken from my backend
  2. My node.js backend gets CognitoID AWS temp user credentials. However, the AWS documention says we also need a session token (presumably by calling CognitoSync), so I assume my backened needs to get the session token as well.
  3. My node.js backend passes those temp credentials plus session token to client
  4. Client uses them for calls to S3 with AWS SDK passing in the credentials + session token.

Am I missing something? Is there an easier way to do that? I assume there is no way to simply have the client pass my own custom node.js user accesstoken to AWS/S3/Cognito and have S3/Cognito authenticate the token by calling my own node.js API that could authenticate this token.

Upvotes: 12

Views: 6795

Answers (2)

pcoady
pcoady

Reputation: 21

I wrote the NodeJS and Cordova Cognito tutorials from BackSpace Academy you are referencing. The tutorials were designed at the time to give much needed guidance on implementing Cognito. Notwithstanding this, Cognito is not always the most suitable solution (KISS principle). I think you may be over complicating your solution:

  1. You don't need Cognito to securely access S3 from Browser or Server. A federated user (oauth/Facebook) can access S3 directly from browser or through your NodeJS app.
  2. If you don't need the Cognito key value data store then just use a federated user on the browser side. Is a NodeJS server actually required?
  3. If you can do everything from the client you don't need a NodeJs server.

I would suggest you consider doing everything on the client side with a federated user. This is detailed in the AWS browser SDK docs under "Configuring Web Identity Federation in the Browser".

CAUTION! NEVER PUT YOUR AWS CREDENTIALS IN YOUR CODE, INCLUDING SERVER SIDE. Always use a federated user (oauth) on the browser side and on server side create an IAM role for your EC2 instance to connect to an S3 endpoint at your VPC. For some stupid reason the AWS S3 browser example hard codes credentials.

Upvotes: 2

Scott Willeke
Scott Willeke

Reputation: 9335

You've pretty much got it. You can get credentials from your backend and deliver the AWS credentials to the client. You will need the session key when using temporary credentials that will expire - and you definitely should use temporary credentials with mobile app clients.

If you want to authenticate the user with your own backend (using username/password with your backend) you can use Amazon Cognito's Developer Authenticated Identities feature. If your users will be authenticating with Facebook, you can just pass the Facebook access token to Amazon Cognito as described in the Facebook Integration topic.

Either way, the "standard" flow you'll see in AWS documentation is that you let Amazon Cognito deliver the AWS session credentials directly to the mobile app (rather than via your backend). When using Developer Authenticated Identities, the mobile app exchanges the OpenID Connect Token (retrieved from Cognito's GetOpenIdTokenForDeveloperIdentity call by your backend and delivered to the mobile app in the response to the authentication request) to call Cognito's GetCredentialsForIdentity. When using Facebook, you can just pass in the Facebook access token instead of the OpenID Token. Either way, by using this flow, you'll be able to use the "standard" Cognito to get AWS credentials to the app as shown for iOS, Android, JavaScript, Unity, and Xamarin in the Getting Credentials topic.

With that said, you can indeed get the AWS Credentials on behalf of the user from your backend and push them down to the client, but just keep in mind that all of the AWS Mobile SDK examples will assume you're using Cognito as shown in the Getting Credentials topic above, so you'll have to take that into account. If you want to see an example of routing credentials through your own backend, see the API Gateway Secure Pet Store sample (backend code, client code)

Upvotes: 5

Related Questions