Dev Proxy for Easy Auth on Container Apps
Posted 11 Feb 2024
Like many Azure services, Container Apps support Easy Auth. It's not a very well known feature and that's a bit of a shame because Easy Auth helps to neatly separate the setup and code required for authentication from the implementation of application logic.
Unfortunately, it's not easy (yet) to test apps with Easy Auth enabled in development because it requires HTTP headers from the side car to figure out if a user is logged in.
So, I scratched my own itch, and setup a quick dev proxy using YARP. The code is up on GitHub.
What is Easy Auth?
Easy Auth is, in essence, a sidecar configured to handle authentication on your behalf. It proxies requests to your container app and verifies the authentication headers. It also provides endpoints to login your user to one of the providers you configure.
The sidecar provides information about the logged in user in a set of headers:
Header | Description |
X-MS-CLIENT-PRINCIPAL | Base64 encoded JSON object containing all user claims |
X-MS-CLIENT-PRINCIPAL-IDP | The name of the identity provider used to login the user. For example 'aad' |
X-MS-CLIENT-PRINCIPAL-ID | The user ID. For Azure Entra (AAD) this is the object id for the user. |
X-MS-CLIENT-PRINCIPAL-NAME | The user name. For example the e-mail address used to login. |
The JSON object looks like this:
{
"auth_typ": "aad",
"claims": [
{
"typ": "aud",
"val": "e44d07cd-7aae-4cd2-aa0e-1bbd9a3865d2"
},
// .... many more claims here ...
{
"typ": "http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/emailaddress",
"val": "marnix@example.org"
},
{
"typ": "name",
"val": "Marnix van Valen"
},
{
"typ": "preferred_username",
"val": "marnixn@example.org"
},
{
"typ": "roles",
"val": "editor"
},
{
"typ": "roles",
"val": "admin"
}
],
"name_typ": "http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/emailaddress",
"role_typ": "http:\/\/schemas.microsoft.com\/ws\/2008\/06\/identity\/claims\/role"
}
In the example above, I logged in through Azure Entra and all the claims, including roles are passed to container app in a header.
Dev tooling for Easy Auth
Azure App Services and Azure Static Web Apps have similar (but different) implementations. For Azure Static Web Apps there's a handy CLI that launches a dev proxy with a proper local authentication scenario. Microsoft doesn't provide any tooling like this for Azure Container Apps.
Fortunately, creating a dev proxy is easy these days in dotnet, with YARP to handle proxying requests, an API endpoint to handle logout and a of Razor page to fake a user login.
Running the dev proxy
To run the dev proxy, checkout the repo and run the application. You'll need to provide a front-end and back-end url for the proxy:
dotnet run --urls=https://localhost:8888 --backend=http://localhost:5191
It really doesn't matter if you run your back-end in a container or not. You can launch it from visual studio with a debugger attached or from the command line. Just be sure to open the front-end url of the proxy to access your application.
Faking a login
It's easy for the dev proxy to fake a login because it is in control of the headers provided to your application. The Dev Proxy provides hosts a login page at the default url ./auth/login/<idp>
, for example: ./auth/login/aad
.
On login the dev proxy sets a cookie to remember your login settings. You can either logout at ./auth/logout
or revisit the login page to change the logged in user.
Summary
This solution is nowhere near complete but works well for APIs and server rendered sites. Please check the project on GitHub for more details. It has both the proxy and a demo application.
If you find this useful, please let me know and star the GitHub repo.
Leave a comment