I have done following configurations
Created loadbalancer
Created user pool
created client with secret and enabled authorization code grant and openid scope
Configured authentication in loadbalancer with above created resource details
Created a listener rule with cognito authentication
Added needed configuration including scope as openid
Configured deny for unauthenticated requests
Problem is when I call the loadbalancer url with the id token or access token(as cookies) that is retrieved from another app client configured to application, The loadbalancer is returning 401
When I try the the configuration authenticate for unauthenticated request. I was able to successfully call the loadbalancer url where I am getting success response(loadbalancer will redirect to cognito login and after successfull login, loadbalancer will set the cookies).
The cookie that being set in the success scenario is being sharded
The cookie entry were like cookie_name-0 and cookie_name-1 (Which I do not know how to reproduce/recreate manually)
The below excerpt from aws docs confirms above sharding behaviour
The load balancer creates the authentication session cookie and sends it to the client so that the client's user agent can send the cookie to the load balancer when making requests. Because most browsers limit a cookie to 4K in size, the load balancer shards a cookie that is greater than 4K in size into multiple cookies. If the total size of the user claims and access token received from the IdP is greater than 11K bytes in size, the load balancer returns an HTTP 500 error to the client and increments the ELBAuthUserClaimsSizeExceeded metric.
How can I successfully call the loadbalancer url with the configuration for unauthenticated request as deny where I need to set the cookie manually?
Manually generated id token/ access token length are around 1k in size, why the loadbalancer retrieved token exceeds 4k in size?
Reference - https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html#authentication-flow
https://aws.amazon.com/premiumsupport/knowledge-center/elb-configure-authentication-alb/
I think what you're trying to do is this: you're getting JWT tokens from cognito, and you want to use them to authenticate a web request through ALB that is using cognito authentication checks. Which is to say you're trying to find some way to generate the AWSELBAuthSessionCookie cookies yourself, or craft a call to /oauth2/idpresponse so that the ALB sets these cookies.
Short answer: You can't as of June 2021.
Here's the answer I got from AWS support on this issue, where I'm trying to get a python client to call through ALB with cognito JWT tokens:
As per the design, automated clients ( such as your python script ) will not be in position to utilize this ALB functionality. Further ALB will not accept any JWT tokens passed by clients in the request. This is to prevent any kind of replay attacks while communicating with load balancer. ALB will only initiate the authentication process if client request triggers authentication rule.
Seems the only way to get those ALB cookies set is by having a web browser open the auth page. Sorry. Cognito sucks. Open standards my ____.
Related
I have a project where I am hosting an ASP.NET MVC site on an AWS EC2 instance behind an AWS application load balancer (ALB).
I have an ALB listener "Authenticate" rule that takes any traffic that does not have a valid cookie and forwards it to the Azure AD OAuth prvoider (aka OIDC Autentication). The authentication works well, and goes as follows:
HTTPS traffic hits my ALB and since there was not a previous OIDC authentication it forwards the user to Microsoft's Azure AD authentication page for my Azure AD tenant.
On successful authentication, Azure AD forward the response to my ALBs response URL. This is where the Azure AD OAuth flow terminates.
The AWS ALB generates it's own OAuth token, which includes my original Azure AD username and claims, signs the JWT with it's own key, and forwards the request to my EC2 instance via a target group, with additional HTTP headers (X-Amzn-*) which include the AWS token info
However, I cannot figure out how to sign the authenticated user out. I have tried
Using Azure ADs own "outh2/v2.0/logout" URL with information about my tenant and client ID (application ID) and then specifying a logout page I have hosted behind my AWS ALB, This only logs out the Azure AD user, but when I return to my site home page the AWS ALB has persisted info via it's own cookie and forwards the traffic without redirecting to Azuure AD with the old AWS JWT (event if the "Exp" timestamp in the JWT has passed). These subsequent requests contain a cookie named "AWSELBAuthSessionCookie-0" whose value is the entire JWT encoded in Base64, but with a cookie expiration of 1 week in the future.
I have tried clearing the "AWSELBAuthSessionCookie-0" cookie both on the server side of my application and also in the client code (by setting expiration to some time in the past) prior to hitting my website home page again, but the "AWSELBAuthSessionCookie-0" is somehow magically restored containing the old, expired JWT
Is there a prescribed way to logout of an AWS ALB-authenticated session that used Azure AD (with a custom tenant, not the public 'common' tenant) as the OIDC provider?
I configured a Session timeout to be as short as 1 second to prevent users from reusing the old cookie.
The AWSELBAuthSessionCookie-0 is a session cookie containing the secure and httponly attributes issued by the load balancer. As this post points out, the cookie must be changed only on the issuing server.
I am using AWS ALB for OIDC authentication, and once authenticated it lands to my backend application where i create a session save it in redis and return the session cookie back to front end.
The front end uses the cookie to commuicate with my backend.
After 10 minutes if the session is expired. Then i want to redirect the page login page.
My question is should i handle the session expiry in my code or does AWS ALB has some intelligence in it to know that my sesion is expired and redirect to logic page.
If i have to explicitly redirect form my code. DO i need to get location header and statu code as 302 as below.
/login is listener in ALB which will authenicate to OIDC
response.getHeaders().setLocation(URI.create("/login"));
response.setStatusCode(HttpStatus.FOUND);
However, when i redirect to /login. which is path route configred in ALB to authenticate via OIDC. I get 404 0r 400 not found from Oauth provider . Is it because of setting location header am not sure
Your session is handled by your backend services and ALB has no knowledge nor access to it. So, you should also handle session expiration in your code.
I have a AWS Cloudfront hosted webpage which takes static pages from S3 and makes calls to custom origin (ALB) for dynamic data. There is OIDC authentication enabled on ALB, so calls to custom origin (my API) passes via rules set at ALB.
In a particular case when my request to custom origin is unauthenticated I am redirected to IdP for login and after successful login I get the cookie in the response header, as this request was sent to IdP from ALB - the issued cookie has domain as ALB DNS. In order for my webpage to use this cookie I have to redirect the call to Cloudfront URL. Now the cookie was issued to ALB which has a different DNS and my Cloudfront URL has a different DNS therefore I am unable to use the cookie.
I tried to catch the cookie value but because it is issued for a different domain i am unable to catch hold, also as a part of design I feel that is wrong. Has some one faced similar type of issue.
AWS ALB OIDC sets session cookie for the same request host domain for which you configure the authentication action in the listener rules.
Also, they set a http only secure cookie, meaning you cannot access it via client side Javascript at all.
Considering this along with your setup, it seems you actually need a (tiny) backend for your web page, so that you can access the response cookie when you make the API call to the mentioned custom origin internally from this backend.
Architecture : Strictly Serverless
Cloud - AWS
I've an application load balancer (internal) in front of a private api gateway and the requirement is to protect the load balancer endpoint with the enterprise SAML IdP.
Lambdas, S3 are allowed, but Route 53, EC2 are not whitelisted to use on this account.
Problem here is what would be the relay state (final target) here after SAML authentication ? As the internal ALB and the private api gateway endpoints arent visible outside the AWS landscape, I dont understand how to land on the alb endpoint once the user is authenticated with the enterprise IdP ?
Many thannks !
To use the on-premise enterprise IdP with your ALB, the IdP and ALB must be able to talk to each other (via VPN or Direct Connect). you would then establish a trust relationship between your AWS account and the IdP and define an authentication action in a listener rule on your ALB.
Elastic Load Balancing uses the OIDC authorization code flow:
When users direct requests to your ALB, the ALB authentication
action will check if the session cookie exists on the incoming
requests and check its validity. If the session cookie is set and
valid then the ALB will route the request to the proper target group
containing identity information (JWT token via X-AMZN-OIDC-*
headers) that backend instances can use to identify the user. If the
cookie is not present, the load balancer redirects the user to the
IdP authorization endpoint so that the IdP can authenticate the
user.
The IdP then authenticates the user and redirects the user back to
the load balancer with an authorization code. The ALB presents the
code to the IdP token endpoint to get the ID token and access token.
After the load balancer validates the ID token, it exchanges the
access token with the IdP user info endpoint to get the user claims.
The load balancer creates the authentication session cookie and
sends it to the client so that the client can use it on subsequent
requests.
Source:
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html
https://aws.amazon.com/blogs/aws/built-in-authentication-in-alb/
I am trying to set Listener rules on an ALB. I want to add Google Oauth support to one of my servers.
Here are the Google endpoints I am using
I see google auth page alright, but on the callback url I'm seeing 500 Internal Server Error. I've also set the callback URL. Am at a loss as to what's wrong here. Any help is most appreciated!
After authentication, I'm not redirecting to my application, instead I've set ALP to show a text based simple response.
I struggled with the same problem for hours, and in the end it turned out to be the user info endpoint that was wrong. I was using the same one as you, but it should be https://openidconnect.googleapis.com/v1/userinfo.
I haven’t found any Google documentation saying what the value should be, but found this excellent blog post that contained a working example: https://cloudonaut.io/how-to-secure-your-devops-tools-with-alb-authentication/ (the first example uses Cognito, but the second uses OIDC and Google directly).
From AWS documentation
HTTP 500: Internal Server Error
Possible causes:
You configured an AWS WAF web access control list (web ACL) and there was an error executing the web ACL rules.
You configured a listener rule to authenticate users, but one of the following is true:
The load balancer is unable to communicate with the IdP token endpoint or the IdP user info endpoint. Verify that the security groups for your load balancer and the network ACLs for your VPC allow outbound access to these endpoints. Verify that your VPC has internet access. If you have an internal-facing load balancer, use a NAT gateway to enable internet access.
The size of the claims returned by the IdP exceeded the maximum size supported by the load balancer.
A client submitted an HTTP/1.0 request without a host header, and the load balancer was unable to generate a redirect URL.
A client submitted a request without an HTTP protocol, and the load balancer was unable to generate a redirect URL.
The requested scope doesn't return an ID token.