aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.44k stars 2.13k forks source link

How to integrate Amplify and ALB security #3894

Open GuidoBeutlerHRS opened 5 years ago

GuidoBeutlerHRS commented 5 years ago

Which Category is your question related to?

Issue: I configured an ALB with the same Cognito Pool I use for my React Web app, which uses amplify. After login to the pool the session in the web app is not valid. I would have expected, that if a user authorized on the same pool and has been forwarded to the web application by the ALB that the session in my web app is valid.

description

In my web App I read the session state

//load current session state  
loadSessionState () {  
  Auth.currentSession()
    .then(data => {
          console.log("loadSessionState", data);
          this.setState( {sessionIsValid: data.isValid()});
      })
      .catch(err => {
          console.log(err);
          this.setState({sessionIsValid: false});
      });
};

sessionIsValid is false afterwards, although the session passed the ALB, which is configured to use the same user pool.

Probably it has to do with that the ALB and the Web app uses different application clients of the same pool? Amplify always creates two app clients, one has a client key, the other doesn't have one. The java script code, which has been generated by amplify, uses the app client which doesn't have a client key. The ALB can b configured ONLY with the app client, which has the client key.

How to setup ALB security with a amplify app properly?

Thanks in advance and best regards,

Guido

What AWS Services are you utilizing?

Cognito and ALB (application load balancer

undefobj commented 5 years ago

We currently do not have documentation for this, however could I ask is there a reason why you're using ALB rather than API Gateway or AppSync as your API endpoint? Are there specific ALB features which you need to leverage for your use case? This would help us look into it in the future.

GuidoBeutlerHRS commented 5 years ago

Hi @undefobj , it's more a POC. I am aware of that you could use S3 for the React pages and serverless development in general. We just have some applications, where we can not do so for technical reasons and I wonder, how Amplify and ALB security can be integrated with each other. I am new to Amplify and thought, that it would work out of the box and was a bit surprised, that it didn't. I also could let Amplify do the Authentication but in this case the session at least hit the web server. With regards to security I thought, that ALB Security is most secure solution since there is no room for programming errors of any kind. I am searching for a solution to add a managed authentication provider to an existing application without having to rewrite it entirely.

undefobj commented 5 years ago

I think some clarification is needed. ALB doesn't do anything related to Authentication, you need an Identity Provider for this which Amplify supports using Amazon Cognito. This will return OIDC compliant JWT tokens. These tokens can be passed to your backend API for performing Authorization checks. The two most common ways of doing this are using API Gateway or AWS AppSync, which is what Amplify supports out of the box.

ALB is an alternative to running your own API backend if you don't want one of the managed options I mentioned above, however you take on more responsibilities such as connecting it to a compute instance and other concerns. You could do this today but we don't have documentation on it as most customers go the route of API Gateway or AppSync.

I think the question is what are you building and what are the requirements why you would need ALB as opposed to one of the above options?

kenta-polyglot commented 5 years ago

@undefobj

Hi, Sorry to interrupt.

ALB doesn't do anything related to Authentication

ALB now supports authentication. Document is below.

Authenticate Users Using an Application Load Balancer

I think @GuidoBeutlerHRS knows this and I'm very interested in this issue. (Because I'm going to use Amplify and ALB + Cognito authentication)

undefobj commented 5 years ago

@kenta-polyglot Thanks I'm aware of the functionality. To be completely accurate, unless I'm missing something, ALB is not actually doing Authentication but rather interacting with the IdP which is doing Authentication using OAuth and doing signing validation on the returned JWT. This is why it needs the .well-known/openid-configuration URL to perform Authorization against the public key which the IdP publishes.

What ALB is actually doing is Authorization flows as documented here on that page: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html#authentication-flow I can see why there might be confusion though as they've titled this "Authentication Flow" but as the details explain it's "OIDC authorization code flow".

All these things aside, if we go back to the issue at hand I'll repeat my original question: What are you building and what are the requirements why you would need ALB as opposed to one of the above options?

kenta-polyglot commented 5 years ago

@undefobj Thank you for your reply.

What are you building and what are the requirements why you would need ALB as opposed to one of the above options?

I don't know the situation of @GuidoBeutlerHRS , But in my case, API Gateway and AppSync are too heavy.

I used API Gateway a year ago, I had to write many settings for API Gateway in my CloudFormation template. I don't want to do that again and my APIs are very simple and I don't need 'logging' or 'monitoring' so API Gateway is too heavy. (I plan to write access log on server side (EKS))

I don't know AppSync a lot but I'm not going to use GraphQL and I have to use RDS(Aurora) and Amazon personalize in my API so AppSync is not suitable.

So 'ALB authentication for Cognito' is very suitable for my situation.

undefobj commented 5 years ago

I'm still not sure what the ask here is? My suggestion is if you're really set on using ALB with Cognito see what does & doesn't work with Amplify that way you can crisply give us your requirements for future improvements or asks around what we could change in the current implementation to support your use case.

kenta-polyglot commented 5 years ago

@undefobj Sorry for my poor reply.

My situation is:

I will examine the combination soon. I'm very sorry for taking your time.

GuidoBeutlerHRS commented 5 years ago

Hi All, ALB is a quite easy and lightweight way to integrate Cognito as identity provider with an web application. All you need to do is some configuration and it works well. Nevertheless the AWS documentation says, that the web application should verify the token. This I wanted to do by using Amplify by validating the session (please see code in my initial post) and using the same User Pool for Amplify and the ALB. Of course there are obvious workarounds:

If I do not manage to sort out, why ALB and Amplify use the same user pool but not the same session I probably have to go for one of the other options. With regards to API Gateway AppSync, I think there is a general difference in the architecture. The ALB protects everything in behind since no client can even load the web pages or anything else without passing the Cognito authentication since the ALB ensures that nothing is accessible by routing. If I rely on the certifications of ALB and Cognito this, I think, is the most secure solution. If I use Amplify, a client at least can access the instance and the code executed there is Amplify and the integration. At least the integration of Amplify is self written so, even if Amplify would have the same certifications as ALB it is less secure. Please be so kind and correct me if I am wrong. Like I said, I am new to Amplify.

@undefobj : summarized, could Amplify support session verification of ALB/Cognito authorized sessions?

I am not sure, if this is a feature request, probably it is possible and I just don't know how. If it is possible, and you help me to set it up, I am happy to write the required documentation.

GuidoBeutlerHRS commented 5 years ago

@undefobj not sure if you noticed my comment above. I would be curious, if you have different arguments. Beside of that, you shared the AWS docu on how to verify a ALB authenticated session above (copied from there) https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html#authentication-flow This page contains sample code in Python, which of course can be ported to JavaScript. I wonder, if the same can not be done by Amplify and probably is part of the library already. My basic understanding would be, that if we manage to turn a ALB session in a Amplify session the ALB could protect the entire application while Amplify is a comfortable way of working with identities after that. Or is it that you say, the tho architectures ALB+Cognito vs. Amplify+Cognito exclude each other.

GuidoBeutlerHRS commented 5 years ago

I've implemented ALB token verification and payload decryption based on: https://github.com/kjur/jsrsasign/wiki/Tutorial-for-JWT-verification

Now I have the user ID accessible, which is the same Amplify shows for the same account. Remains the question, how to tell Amplify, that this is a valid session. Like I wrote, I the problem could be:

Amplify always creates two app clients, one has a client key, the other doesn't have one. The java script code, which has been generated by amplify, uses the app client which doesn't have a client key. The ALB can b configured ONLY with the app client, which has the client key.

I have not been able to find some description, why Amplify needs two Clients and which of them is used for what. Is there any documentation, I could consult on how to connect the existing session with Amplify?

Thanks in advance and best regards,

Guido

stephankaag commented 4 years ago

@GuidoBeutlerHRS @kenta-polyglot Great, someone with the same issue that I ran in today. Did you find a solution? What I found so far is that ALB only returns an AccessToken (in the header) and not the ID & refresh tokens that Amplify needs to function. Do you agree?

BTW this is the same issue: https://github.com/aws-amplify/aws-sdk-ios/issues/1323

sbbailey commented 2 years ago

Hi, I know this thread is old, but the problem still exists. As @GuidoBeutlerHRS describes, the solution of an ALB that offsets authentication to Cognito for web traffic is a really good implementation for many reasons. The way AWS has set up Amplify is in a way that requires AppSync and API Gateway - for technical reasons, these may not be applicable, and it seems AWS have missed a beat here by not allowing the ALB to offset Auth as it does for web - in the same way API Gateway does. I've spent an extensive amount of time on this and gone around in circles to find that it's not possible (from what I can see) to integrate both web and mobile with ALB - in other words using the Amplify SDK (Javascript in my case). If it is possible, we could do it with some documentation. If not, then maybe AWS should consider it, it's an elegant solution and requires little coding overhead to offset the Auth to the ALB. If anyone has an update on this please post, thanks.

azpnellius commented 11 months ago

I also have a very similar use case and would like this to be addressed. Can someone please provide an update on whether or not you are considering a solution for this or if we need to go with a different solution?

chriswilty commented 7 months ago

Just adding my upvote as well.

One very good reason for wanting ALB to handle all auth is that our UI and server code then don't need to know anything about authentication - if I can define the auth layer entirely in cloud infra, then our application code is fully portable to any other hosting infrastructure. Our application is open source, so this is essential for us.

As it currently stands, I have the UI handling auth via Amplify, but there seems to be no way that the ALB can then verify the access token included in API calls from the UI, as APIGateway can do. I can of course use an edge function in CloudFront to do this, but that doesn't prevent someone accessing the API directly and bypassing auth.

Can I let ALB handle authentication instead of the UI, and if so, how do I hook it up to our styled authenticator? Our situation is also slightly complicated by wanting to host the application in eu-north-1 (for carbon-efficiency reasons) which means needing to use AuthenticateOIDC rather than AuthenticateCognito action, though presumably that's just a case of identifying the correct URLs to pass in the action config.

alpadotsh commented 6 months ago

I am also running into this issue. I want to have an API backend by a service running in an EKS cluster and I want to expose the service with an ALB and still use Cognito for the auth. Given that ALB seems to integrate with Cognito it's a shame that you cannot use it with Amplify. I am lucky to have stumbled upon this thread before wasting hours trying to implement that.