amazon-archives / aws-serverless-auth-reference-app

Serverless reference app and backend API, showcasing authentication and authorization patterns using Amazon Cognito, Amazon API Gateway, AWS Lambda, and AWS IAM.
Other
754 stars 193 forks source link

how to secure api? #5

Closed davidxiao closed 7 years ago

davidxiao commented 7 years ago

Hi, Thanks for your great demo and video, while could I ask a question about how to secure API? As mentioned, API key is not used to secure API, then how to secure it without details exposed? The details i mean all service we are using from AWS, like I don't want the API consumers know our system is based on AWS API Gateway, so as the API generated SDK, aws, cognito lib, etc. My case is: i want to develop an API(mainly for server to server) for 3rd developers, i feel AWS API Gateway is great option to control the API calls. but don't know how to protect API, Thanks very much in advance.

Thanks

justonian commented 7 years ago

Hi David-

If you want to properly secure an API Gateway-hosted API, but don't want your customers to know that it is hosted by AWS or using API Gateway, then I would avoid the IAM-signing option as SigV4 signing is a standard developed by AWS and could be traced back to AWS. In this case, you'd likely want to use a custom authorizer via Lambda function, in which case Cognito is completely optional and you can use the identity provider of your choice (including Facebook, Google, or any provider that supports bearer tokens).

Additionally, I would setup a custom domain name for your API Gateway deployment so that your customers only reference "api.yourdomain.com" when connecting without needing to know anything else or seeing the long dynamically generated unique AWS URL of the API Gateway deployment.

If you wanted to still do throttling of users, it'd be best to use API Keys and usage plans, in conjunction with your own Authorization header for calls (which is used by the custom authorizer to generate an effective IAM policy for the use, though the user does not see this or know about it).

Please let us know if you have further questions. I hope this clarifies.

Justin

davidxiao commented 7 years ago

Hi, Justin Thanks very much for your information, great helpful! Yes, I am planning to use API keys, usage plan, with API-Gateway in our domain, custom authorizer.

While one question about the work flow from developers as API consumer, for example, with Cognito User Pool as provider(preferred way, or probably it'll be the only one provider), and how to upload files to S3(better to bypass api gateway if possible)

Is the above flow correct? Sorry, this is a little bit silly question, but I don't have experience before so it'd be great if could get best practice from you.

Thanks very much again

David

justonian commented 7 years ago

For uploading images or other binary content to S3, you have several options:

As you mentioned, you can use API Gateway with Lambda to upload binary content, though you'd have to ensure additional content types are included beyond the default, then could use Lambda to parse the base 64 encoded image and upload to S3.

However, the preferred way, in my opinion, is to let the user write to S3 directly using the AWS SDK to enable multi-part uploads. If you already have the AWS SDK integrated in your project, either the browser JS SDK or Android/iOS SDK will work, then you can use temporary IAM role credentials to initialize it via an AWS access key, secret access key, and session token. This is exactly how our sample project uploads an image to S3 from the "account" page in the app. The biggest benefit of this approach is that you can leverage the built-in S3 multi-part upload functionality and other enhancements AWS has already developed in the SDK.

The preferred way to get the temporary IAM credentials for a user is to first have them authenticate with whichever identity provider they have an account with (Cognito User Pools, Google, Facebook, SAML-based, etc.) then use the returned token with Cognito Federated Identities to assume a Cognito identity IAM role. Hence, this is an option whether or not you're using Cognito User Pools and does not require a custom authorizer for this particular use case.

Hope this helps.

Justin

davidxiao commented 7 years ago

Thanks very much, Justin I was thinking to hide internal info like what service we use from 3rd part developers, but seems it's not best practice, and not easy to achieve. Thanks again