Securing your applications with AWS ALB Built-in Authentication and Auth0
Built-in Authentication for the AWS Application Load Balancer was announced back in May. This new feature allows you to require users to be authenticated before the request is proxied to your application. This is extremely useful when you’re hosting your own applications like Shiny Server Open-Source, Kibana … which don’t always make it easy to require end-user authentication.
I have an application running on https://app.sandrino.run which requires authentication. The application runs in a VPC and is not directly exposed to the internet. An Application Load Balancer is setup which handles SSL offloading and proxies all requests to the EC2 instance hosting the application.
Only authenticated requests should be sent to the instance, which is where Built-in Authentication comes in. If the user is not authenticated they will be sent to Auth0 (the identity provider, IdP). This leverages the OIDC Authorization Code flow. After the user has logged in to the IdP, they will be redirected back to the ALB with the authorization code (https://app.sandrino.run/oauth2/idpresponse?code=…). The ALB will complete the transaction by executing the code exchange (by calling the token endpoint of the IdP).
If the transaction is successfully completed the ALB will create a session and further requests to https://app.sandrino.run will be authenticated, allowing them to be proxied to the EC2 instance.
Configuring Built-in Authentication
Once you have your EC2 instance running in a VPC you’ll want to create an ALB. Make sure it listens on HTTPS. If you also want it to listen on HTTP I would suggest forcing a redirect to HTTPS in your application first.
Since the ALB has an HTTPS listener you’ll also need to setup a certificate:
And after configuring the Security Group and the Routing you can select the instances to which the traffic should be sent. Make sure the Routing is setup in a way to route traffic to the correct port (in my case 8080).
Once the ALB has been setup I also create a CNAME for my domain pointing to the ALB. My application is now listening on https://app.sandrino.run
Setting up an Auth0 Client
The next step requires you to create an Auth0 account in which we’ll create a new Auth0 application (“Regular Web Application”).
The only change you’ll need to make here is to configure the “Allowed Callback URL” for your application. In our case this is the endpoint hosted by the ALB which is the final step in the transaction.
The format is always:
Setting up Built-in Authentication
As a final step we’ll add a rule for the HTTPS listener in the ALB.
In the rule you can add an “Authenticate” step before the “Forward to” step, requiring all requests to be authenticated first. Configuring it will require you to fill in the following settings:
- Issuer: https://your-domain/
- Authorization Endpoint: https://your-domain/authorize
- Token Endpoint: https://your-domain/oauth/token
- User Info Endpoint: https://your-domain/userinfo
- Client ID and Client Secret of your Auth0 Application
- Scope: the scopes you can use to request specific sets of information as described by the OIDC specification. The openid profile scope will give you the full user profile
Note that if you’re using Auth0’s Custom Domain feature you’ll want to use the Custom Domain everywhere as the hostname.
The session timeout option allows you to configure for how long the user’s session will be valid before redirecting them back to the IdP.
I have a simple application setup which will show me the contents of the request. When I navigate to the application for the first time I’ll be redirected to the IdP (Auth0 in this case) where I’ll be prompted to authenticate.
After entering my credentials I’m redirected back the my application as an authenticated user. This is where you can see a few interesting things:
- A cookie has now been set “AWSELBAuthSessionCookie-0” by the ALB which is tied to my session
- The ALB sends a few headers (x-amzn-oidc-) to my application which contains the user identifier, the access token provided by the IdP and a data object which is a JWT containing the full user profile. This JWT is issued by AWS and should be validated if you are planning to consume the information.
Now that you have authentication covered you might want restrict access to specific applications. If you’re using this to authenticate access to Kibana, you might want to restrict this to IT Operations only.
Auth0 provides very basic authorization capabilities through the Authorization Extension. This is where you could setup a group “IT Operations” in which your IT users are added to.
With this you can then write a Rule which restricts access to your application and only allows members of “IT Operations” to access the application:
This post covers the most basic use case provided by ALB’s Built-in Authentication which is useful for packaged software you hosting in AWS. If you’re building your own applications you can use more advanced features like mixing public vs private content, accessing the user claims, refresh token support …
All of this is covered in the ALB Built-in Authentication documentation.