EC2 and RDS Authentication? - amazon-web-services

I have an EC2 instance running a Node.js Express backend that controls CRUD operations to an RDS instance. I am doing a mobile application client (which I am authenticating users through cognito with the client sdk). What would be the best way to authenticate my mobile app users so that only authenticated users can access my Node.js Express functions running in EC2? Basically looking for something like IAM Lambda authentication (but for this server application, rather than a serverless architecture).

What would be the best way to authenticate my mobile app users so that only authenticated users can access my Node.js Express functions running in EC2
Authenticating with Cognito you shoud be able to get an access token (id token and access token) once the user is authenticated.
The token is to be fetched by the mobile client after the user is authenticated, see https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdToken.html . This token can be sent along every request to the nodejs services. Please note the token has an expiration time and the client needs to get another one when the token is expired.
The token contains user identity, issuer, expiration time and (Cognito) user groups
The services must validate the token (issuer, expiration, signature) and trust the token (or not) based on the validation.
Validation example: https://github.com/kjur/jsrsasign/wiki/Tutorial-for-JWT-verification) in this example the public key is read from a certificate. Amazon provides only the public key properties (e,n) https://aws.amazon.com/premiumsupport/knowledge-center/decode-verify-cognito-json-token/, so you will have to complete the public key yourself, example https://github.com/rzcoder/node-rsa
Edit: more detailed clarifications

Related

What is the best way to authorize an AWS API call for a logged in user?

I have a spring boot based web application which already authenticates the user. I would like to create some AWS APIs using AWS api gateway and a springboot rest app deployed on EC2. The user will log into the existing application and call the new AWS APIs from the browser ajax calls (like an SPA I guess but I have a server and can use client credentials/secrets if needed). What is the best way to handle security for the APIs. My first thought was to generate a JWT using a shared server side secret for hash and verify it with an AWS lambda. But this seems a bit non standard. Oauth2 might be better but might also be over kill. Not sure the performance would be good. Few requirements
token passed to the API should be a user specific token and have an expiration (and hence a refresh token)
The user is already logged into my web app and calling the api should not issue a login challenge.
AWS API Gateway should be able to verify the token before passing it to the application
Any token passed to the API should probably be generated on the logged in web application. Server knows the user is authenticated and should generate the user access token on behalf of the user. The AWS api should be able to figure out what privileges the user has based on the user principle or scopes in the token
I've thought about using Cognito AWS but I dont want to require the users to preexist in a user pool. Cognito seems geared more for the authentication rather than authorization and I would not be using the cognito login functionality. I dont know if its possible to use the oauth2/token endpoint alone with cognito.

AWS API Gateway authorizer google sign in

I have an API Gateway/lambda REST API that is being accessed from a react web app. I need to add authentication using google as an identity provider. The app should also keep the user signed in.
I understand when the user first grants access to the (react) client app, it should send the ID token to my backend, which should then verify the token.
Since my architecture is serverless, I assume the verifying should be done in the API Gateway authorizer function, which then grants access to the API on successful verification of the token.
My question is, how do I then create a persistent session? Should I be saving anything to my database about the user? Does the token need to be verified on every API call?
Should the authorizer be checking if the user is already registered or if it's a new user?
It would be easiest to use AWS Cognito for this. Configure a user pool as an authorizer for your API gateway and then configure Google as an identity provider for that user pool. This link might be helpful: https://docs.aws.amazon.com/cognito/latest/developerguide/google.html. Cognito even has a hosted UI if you want to use it for signing users in.
As for your question about persisting user sessions, they usually get persisted in local storage in the browser or in a cookie or some similar mechanism. You can also persist them on the server-side in a database like you were mentioning but that isn't really for authentication purposes.
The user session will contain an access token. The access token is short-lived, meaning you can only use them for an hour usually. After that you have to use a separate refresh token to generate a new access token. And to be extra safe the refresh token itself will expires after a few days (and you have to sign back in).

AWS Cognito federated identities + permanent access key for programmatic API

I have an API service, which I'm going to deploy using AWS API Gateway with Cognito authorizer + Lambda as backend. This service will be used by our javascript client. Also, it should be exposed to end users as raw endpoints for programmatic access.
While it was quite easy to enable signup/login in js client using federated identities, I can't figure out the way to provide users with private access token to include directly in http headers.
Here are two authentication flows, I'd like to get in the end:
The flow for js client user:
User signs up with Facebook or Google.
User verifies his identity.
After login, user goes to the Profile/API Keys section in the interface.
User copies access token and can include it in http request header in any http client (httpie, curl, language libraries whatever)
The flow for admin created user:
Admin creates user.
Access token is generated for that user.
Admin passes generated access token the user.
User can include it in http headers to make request, as in previous flow.
An access token should be permanent, and can be regenerated by user at any time (think of Stripe API access keys).
The point here is to eliminate additional steps for the user to start using service programmatically. The closest thing in AWS docs so far is developer-authenticated-identities, but user should utilize AWS sdk anyway.
One possible way to accomplish this task is to use Custom authorizer instead of Cognito authorizer in API Gateway. Custom authorizer could implement logic based on e.g. auth header name and decide to either authorize in Cognito or to user API access token in database. I'm not sure, if it is possible, and if it is the major drawback is to reimplement Cognito authentication flow in lambda function.
The question is how can I accomplish such API access token (re)generation using Cognito or API Gateway?
The first flow should be possible with User Pools. Cognito User Pools now has a federation feature where you can federate using Facebook/Google and receive access token/refresh token depending on the flow used.
For admin created user, the user would need to authenticate before tokens are issued but this can be achieved by creating the user with a temporary password and signing the user in with that password, after which it can be changed and logged in again to receive access/refresh token.
The refresh token use case is that it can be used against the Cognito APIs to receive a new access token. When the refresh token expires (default is 30 days but it is configurable), the user would have to authenticate again.

User authentication in microservice application hosted on Amazon WS

I am building web application based on microservice architecture. At this moment I am considering few ways of user authentication flow. I predict following, example user roles:
admin - is able to create content, upload files etc (admin account can be created only by another admin)
unauthorized user - can view content
authorized user - can comment content
Here is, how I was thinking about authentication flow so far:
authentication service - have access to DB with users credentials and permissions
api gateway - retrieve requests from user, check if user is logged in (ie verifies OAuth2 access token with auth service) and transfer flow to other services based on user request (attaching JWT token with some basic user info)
another service - accept only requests from api gateway, and trusts user data from JWT token (does not need to connect with auth service to get information about user).
After deploying some stuff on AWS infrastructure my way of thinking have changed a little bit. As far as I understand AWS products (Lambda - serverless applications and API gateway), I should implement authentication flow as follows:
authentication service - gets request from user, retrieve data from dynamoDB and provide user cookie with JWT signed by private key
any other service - retrieves request with JWT token, verifies signature using public key, and perform some action.
And now the question comes:
How deos AWS Cognito fits here? Is it something useful for me? As far as I understand, Cognito simplifies flow of authenticating users via 3rd parties (facebook, twitter etc. etc.). Does AWS Cognito serves login page, separated from my application, or it is only background/webservices impelementation?
So far I am thinking about Cognito as a replacement for my authentication service - any of my services, should impelemnt Cognito authentication flow provided by SDK from amazon, and my static website would implement JavaScript SDK for user login/register. Am I right?
First of all AWS Cognito consists of two services.
AWS Cognito UserPools (Which is the Identity Provider) - This is the service where you can create the users and manage their credentials with other policies. It can also provide the login screen where we can customize the logo and look and feel so that it can become a plug and play Login service. Then it is also possible to configure the authentication flow (For example to make the service as an OpenIDConnect authentication provider so that it will return a JWT token once user logs in). It is also possible to connect Social Identities (Facebook, Google & etc.) and SAML.
AWS Cognito Federated Identities (Identity Federation to grant users access AWS Services) - This service is capable of accepting AWS Cognito UserPool Token or direct access from other providers where we can federate the access to AWS resources. For example, AWS Cognito Federated Identities can grant temporal access to a User, Authenticated from another provider (e.g; AWS Cognito UserPools) to upload files to S3.
For more details refer the article The Difference Between AWS Cognito UserPools and Federated Identities?.
So coming back to your questions,
So far I am thinking about Cognito as a replacement for my
authentication service?
you can use AWS Cognito UserPools authentication service to issue JWT tokens and validate the token in AWS Lambda Custom Authorizer at your other service endpoints. This is also the place where you can do Authorization.
My static website would implement JavaScript SDK for user
login/register. Am I right?
Not necessarily. If you use AWS Cognito UserPools Hosted UI, you will get Login, Signup, Password Change, Confirmation pages, by default along with auto redirection for Federated Identities (Based on the configurations) such as Facebook, Google or Corporate Credentials like Office365. Although the customization is limited, you should be able to add your own logo and change the background color of these screens. If you plan to implement this by your self, then you can use AWS SDKs to implement these screens.
For more details on the serverless architecture refer Full Stack Serverless Web Apps with AWS.

Securing AWS JS SDK Api Calls

I have a website where I use AWS S3 JS sdk to upload/delete images from S3 server buckets.
Currently I am passing the credentials in raw format in JS file only, which is not secured. And AWS suggests to use web identity federation technique to make it secured.
I read about them, and have some query.
Does this technique means, each user of my website who is going to use it to upload image, needs to verify their logins ?
There is something called, pre-signed in URLs too. Which let us hide the credentials too.
But I am confused on what exactly to be followed to achieve my goal that is,
I do not want to show my credentials to end user in js file. ALSO I don't want my end users to authenticate themselves of any kind.
Is it possible and how?
You should indeed use some Identity Federation to let somehow authenticate your users and to get temporary access key / secret key for your user.
AWS has a service to help you to implement this : AWS Cognito (http://aws.amazon.com/cognito/)
Cognito Identity is an identity federation service that let authenticate your users on well known web identity services such as Facebook, Google, Amazon, any OpenID Connect service (SalesForce...) or your own authentication backend. Once a user is authenticated in one of these services, Cognito will trade the federation token for an AWS Access Key and Secret Key. These Access Keys will be limited in scope to whatever permission you have defined in your Cognito Role and limited in time (15 min by default)
This blog post describes how to use AWS Cognito Identity with your own backend authentication service. It provided server side sample code for Java and .Net : http://mobile.awsblog.com/post/TxBVEDL5Z8JKAC/Use-Amazon-Cognito-in-your-website-for-simple-AWS-authentication
AWS Cognito Identity also allows you to work with unauthenticated users, i.e. to receive an Access Key / Secret Key for users before they are authenticated.
AWS Cognito will maintain an unique identity ID for your users, whatever authentication method they will use (i.e. the same person authenticates once with Google, once with Facebook and will have the same identity ID)
https://identity-demo.aws-emea.info is a web site that demonstrates user authentication and identity federation. This web site implements several federation techniques : Server Side Web Identity Federation (tab #1), Client Side (JavaScript) Web Identity Federation (tab #2) and Client Side (JavaSCript) AWS Cognito Authentication (tab #3)
To answer your second question : S3 Signed URL : these are URL allowing to download / upload content from / to S3. They are typically generated by an App Server and embedded in web pages. S3 Signed URL does not required to have your user authenticated nor to have one key per user. It is your implementation choice to decide between using a user specific key or an app generic key to generate your S3 signed URL. All AWS SDK have methods to help you to generate the pre-signed URL.
Giving your requirement of not authenticating your users, you have two choices. Either use unauthenticated users w/ AWS Cognito or to use S3 pre-signed URLs. Signature must be then generated on the server side, using a servers side key (or a EC2 Role if your app server runs on Amazon EC2)