Obviously we want systems that use modern authentication. In the case of Azure AD, you get the good stuff, like Conditional Access and a whole host of new authentication mechanisms, like Windows Hello & FIDO2.
This is a big jump, however, especially for old apps. And by old, I mean old - running on unsupported or deprecated platforms (or versions of those platforms), where the skillset doesnβt exist in your circle to update it, or where the vendor who created the platform has ceased to exist. Consider too that some legacy systems may be on-deck for total replacement, either with custom dev or off-the-shelf systems, where we want to keep costs as low as possible.
Like most modernization projects, there are different ways to approach the problem - in this case, Iβm focused on the βmoat-buildingβ method, where we dig out and isolate the problem systems and proxy access through more modern systems. This is a bit quick-and-dirty, but for systems that are slated for replacement or just canβt be touched, itβs a low-impact way to wrap new functionality around an old problem. You can apply this to all sorts of parts of a system as well - e.g., extracting and shipping data out of an old system into a new system and schema while slowly moving referencing bits over to the new system.
Letβs dig in.
Reverse proxying
Since weβve got a web app and we want to add only authentication, itβs relatively straightforward. We need to:
- Authenticate the user, using a typical oidc-tango
- Redirect to identity provider
- Consume and validate issued token
- Read claim data
- Transform some claim data before forwarding along
- In our specific case, we need specific values from the claims to be forwarded in a specific header
Layout
Our layout is straightforward. We have our original old app (weβll call it old-app.example.com
) and our front-end (myapp.example.com
). Weβll need to make sure DNS resolves on the Apache host for old-app.example.com
and that our old app server is configured for that host header or to accept all names. If itβs not in your local DNS, you could add it to /etc/hosts
for local resolution.
Next weβll want to make sure myapp.example.com
resolves to our Apache server. You would likely want to use named virtual hosts here, although you could get away with *
if you wanted. My virtual host on :80
is just redirecting to :443
- yours may need to do something different.
Lastly youβll want to make sure you have any TLS certs available and installed on the Apache host.
Iβm using Apache 2.4.* on Ubuntu 18.04, with binaries for mod_auth_openidc
2.3.3, which is available in the universe repositories.
Considerations
Since weβre usurping the user path to the app, weβll need to make sure we manipulate the network environment & DNS in a way to make the app either inaccessible or unusable if someone was to hit it directly. If hosted in Azure, this could be something like a two-subnet VNet, one subnet with the app and the other with the proxy, with NSGs locking down the app subnet to only allow traffic from the proxy subnet. On-prem there are myraid ways to segment networks and restrict access.
Youβll also want to host with TLS, Azure AD reply URLs will require https
except in the case of localhost.
Apache config
For apache, weβre going to use mod_auth_openidc
which is an OIDC-compliant relying party/client module for OpenID Connect.
Letβs take a look at the config.
Results
The mod_auth_openidc
package includes all the claims as passthrough headers, in addition to our custom header with our transformed value. My source claim in this case was preferred_username
, which we transformed via apache to X-jpda-header-loc
.
The advantage to this method is potentially many apps could live behind this proxy, with very little additional effort to onboard more. Of course the tradeoff with proxying is a single choke point for traffic, so carefully consider which apps should be grouped behind specific instances.
Top comments (0)