The year was 2023, and for Enterprise apps, Identity and Access Management are almost never built-in from the design level. They tend to be an afterthought that gets quickly added at some stage with a task for “later” to improve, though, with a little hope for the “later” ever to come.
Here is a story in four acts:
- Needs and means, analysing the requirements for enterprise apps and available off-the-shelf solutions.
- Auth Flows, sequence diagrams of relevant authentication/authorisation flows (OAuth2, OIDC).
- Writing the code in C#, nuts & bolts of coding a Transparent Auth Gateway in .NET.
- Deploying to Azure, explaining App Registrations and Firewall settings (Azure WAF / Front Door).
Where’s the best place to start?… Well, it’s the requirement analysis.
1.1. Authentication for Open apps vs Enterprise apps [≠]
Most people are familiar with the auth requirements for Open apps that the public at large can access. But in the enterprise world of closed ecosystems, the Authentication concern, confirming the user’s identity, has its own spin:
|Open apps||Enterprise apps|
|Supported identity providers||Multiple identity providers (Facebook, Twitter, etc.)||Single identity provider (e.g. Active Directory) supporting Single sign-on (SSO)|
|Form-based authentication (login/password) for explicitly created accounts in the app||Often supported||Never|
Choosing the preferred way for authentication, show errors, register, etc.
|Not required due to the single authority (Identity Provider).
UI might be needed to sign up only.
Such reliance on the single authentication authority (Identity Provider) for enterprise apps changes the perspective making many solutions for open apps less favourable.
1.2. Authorisation [=]
Well, if Authentication looks different between the two and it is more straightforward for enterprise apps, then Authorisation, verifying what the user has access to, looks pretty much the same for Enterprise and Open apps (see Authentication vs. Authorisation).
At the end, the Authorisation service has to issue a JWT or SAML token with a list of attributes (claims) to determine the user’s access.
There are 2 factors that make attributes/claims so special:
- they are domain-specific (a set of roles and attributes must be tailored to the app);
- require management (e.g. assigning to the users).
The above determines a need in an interface for managing users’ permissions and own service for issuing access tokens.
1.3. Hosting [≠]
While the Open apps may liaise with centralised identity services (SaaS), much stricter corporate policies often mandate running Identity services on their own premises, cloud, you name it.
Hence a self-hosted solution is required.
1.4. Summarising the requirements
We need a Transparent Auth Gateway as a trusted authority for our enterprise application(s) that
- Proxies identity checks.
Transparently (without user interaction) confirms the user’s identity from the linked authentication authority (Identity Provider), supporting SSO (e.g. Active Directory), since enterprises want users only to enter credentials into a corporate branded login page to reduce phishing and other password-based vulnerabilities.
- Issues access tokens.
A JWT or SAML token with app specific attributes (user’s roles/groups/etc.);
Again, to wrap it with firewalls and other security features;
- Does user management.
2. Transparent Auth Gateway vs Identity Federation Gateway
There might be some resemblance between Transparent Auth Gateway and Identity Federation Gateway that’s been popularised by IdentityServer. But a new name highlights an important difference:
- Identity Federation (or often shortened to just Federation) is the delegation of the user’s authentication to trusted Identity Providers (check out a more verbose definition in ”Privacy-Enhanced Identity Federation).
Close enough. But the word ”federation” implies a group of ID providers when we need just one.
- ”Federation” also carries some UI to select the provider when, in our case, this link is cemented under the hood without user interaction (so-called transparent authentication).
- Handling the authentication (Identity check) only is not enough; we need authorisation also, where both concerns are traditionally tacked under a vague shortening ”Auth“.
Here we go – Transparent Auth Gateway.
3. Off-the-shelf solutions
The best code is no code. Can we get what we need off the shelf?
3.1. Direct use of the single authentication authority?
The simplest solution could be directly using the authentication authority (e.g. Azure AD, AWS Directory Service, ADFS/LDAP, etc.).
It does authentication/identification. Why not add authorisation to it as well? All modern directory services support user groups, scopes and additional attributes that can be included in the user’s JWT or SAML token.👍
While possible, such decoupling of the app’s logic from the app itself has downstream costs for User Management. Usually, the Directory Service (e.g. AD) is controlled by a dedicated team / gatekeepers that won’t let changing users’ attributes (e.g. groups) to someone else. Hence, all users’ manipulations will get bogged in the corporate bureaucracy👎. It might not be an issue for small companies, but as soon as they grow layers of departments, the pain will surface.
3.2. Customer identity and access management in the cloud (AWS, Azure)
The next best bet is to leverage available cloud services.
Azure customers may consider Azure AD B2C when AWS has Amazon Cognito, and they both have a lot in common:
- Their pricing is user-based and is free for up to 50,000 monthly active users (MAUs).👍
- The user management must be done via the cloud provider – the Azure Portal (docs) or Amazon Cognito console (docs).👎
- The user roles must pre-exist (e.g. in the AD).👎
- Enriching the tokens with claims from the app (which is deemed as an external source) is tricky but possible.
- AD B2C provides API connectors that allow passing the user’s ObjectId to your API, and returning the roles along with other attributes to Azure AD B2C that would add them as claims into the issued token.
- Cognito provides pre-token generation Lambda trigger (docs) that requires a Lambda function to resolve the claims.
It does the basics, but the suggested path for resolving application-specific user claims/roles is rather fragile 👎.
3.3. Centralised Identity Managers? (Auth0, Crowd)
Centralised identity managers like Auth0 or Okta are mighty and support all the identity providers in the world, SSO and offer Federated Identity Management.👍
If price is not a concern, then what may stop you? Likely, it is the hosting as a SaaS outside the corporate cloud/premise. Also, the users’ management will be outsourced to the vendor. It all may go against corporate policies.👎
There are also self-managed solutions (private PaaS) like Atlassian Crowd that can be installed in the corporate cloud (available at a higher cost, of course). The users’ management will be under control till the company pays the subscription fee. And if a different UI/UX is not a concern, then it can be a good solution.👍
Just think of the hassle of bringing a PaaS to your own cloud. It cannot be a smooth experience – settings up the release pipeline, adjusting the Firewall rules, and modifying the infrastructure template, to mention some.
3.4. Libraries for custom build?
Hmm… Not exactly an off-the-shelf solution, but if you’re OK with the extra work of bringing a PaaS over, you could consider leveraging a popular library for writing your own auth solution.
Admittedly, Duende IdentityServer is the most popular library for auth projects in the .NET space. Microsoft is still endorsing its predecessor – IdentityServer4, which is free but not supported any more (.NET Core 3.1 is the last supported Framework).
Cost-wise, IdentityServer is cheaper than Atlassian Crowd. It comes with Federation Gateway out-of-the-box supporting multiple trusted identity providers. It’s well-known for providing high-abstraction layers over auth flows and ready-to-go examples bundling the UI, back-end and database (e.g. this one with docs).👍
Though, any deviation from the examples requires a deeper understanding of the library and the auth flows. So, our case of implementing a transparent auth gateway without flashing any pages to the user and requiring any actions would require a fair bit of time to dive in.
OpenIddict is a decent alternative to IdentityServer, distributed under Apache 2 license. It encompasses a different philosophy – being “close to the metal” provides more flexibility for customisation but doesn’t supply a full package as IdentityServer did (e.g. providing an admin UI and API). While the lack of features on paper may deter some, the incredible flexibility makes it the most suitable candidate for implementing a Transparent Auth Gateway.👍
There’s also Keycloak, a de-facto standard for auth projects in the Java world. It can not only run on OpenJDK, but also provides Docker containers with the whole suite coming out of the box (UI & API for admins and end-users)👍. And it is all under Apache 2 license. But there’s always the other side of the medal, and here we see some stiffness to customisations (e.g. custom grant types and login flows).
Go developers might be excited to see OAuth2 Proxy (MIT license) that also comes with pre-built Docker containers if you wish. Its focus is a bit narrower to just proxy authentication requests to various supported Identity Providers without app-specific authentication checks and user management out-of-the-box.
Remember not to get too excited about those solutions with small and neat Docker containers if you need extra bespoke app-specific authentication checks and user management to decouple from (or to extend) the linked Identity Provider. But Keycloak and OAuth2 Proxy are great for Java/Go devs if you want to build your own solution and use them as the starting point.
4. What’s next?
If you got that far reading, you understand there’s no simple solution for a complex problem that ticks all the boxes. You have to either compromise on the requirements or invest time/resources in creating a tailored solution.
In the next article, we’ll dive into the authentication/authorisation flows to gain a better understanding of how the Transparent Auth Gateway can be integrated into the solution.
If you have any thoughts drop a line in the comments below, on Twitter, LinkedIn, or Reddit.