Custom Module for ARR Reverse Proxy to Pass the logged-in user to back-end servers

While I was working one of the issues with one of my customers, I encountered a scenario where in customer has an Application Request Routing server which is being used as a Revese Proxy. In the backend, they have an Apache server (Linux).  They want the logged in credentials to be passed from the client machine to the proxy server and from the proxy server the logged in credentials to be passed to the backend Apapche servers so that they can re-authenticate the user on Apache server.

The scenario was something like below:

Client (logged in user) => ARR Reverse Proxy (IIS) (logged in user) => (logged in user) Apache

What I did was pretty simple. I enabled windows authetication on the ARR server so that it gets logged in credentials. Once we get the logged in credentials, we have to set a Request Header with the value of the logged in credentials so that when the proxy makes a request to the backend apache server, this header will be passed and the backend server will be able to read the header and get the user credentials.

For setting a header, I created a simple custom http module and configured it on the reverse proxy server. Below is the code for the module:

using System;

using System.Security.Principal;

using System.Web;

namespace Module

{

    public class HttpToHttps : IHttpModule

    {

        // In the Init function, register for HttpApplication events by adding your handlers.

        public void Init(HttpApplication application)

        {

            application.PostAuthenticateRequest += new EventHandler(this.OnAuthorizeRequest);

        }

        public void Dispose()

        {

        }

        public void OnAuthorizeRequest(object sender, EventArgs e)

        {

            HttpApplication httpApplication = (HttpApplication)sender;

            HttpApplication application = (HttpApplication)sender;

            HttpContext context = application.Context;

            IIdentity id = HttpContext.Current.User.Identity;

            if (null != id)

            {

                application.Request.Headers.Set("REMOTE_USER", id.Name);

            }

        }

    }

}

First we created a rewrite rule to point to the backend server then added this module and tested it out.  Basically what this module does is, as soon as the request arrives with the Kerberos/NTLM token on the reverse proxy, it extracts the logged in user information and sets a custom request header with the value of logged in credentials.  So when the proxy makes a request to the backend server based on the rewrite rule, this header will be passed in request and the backend server can read the header and get the user info. On testing, I could see the REMOTE_USER header in the outbound request from proxy.

Below are the request headers for the request from the Client machine to Proxy server.

GET / HTTP/1.1

Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*

Accept-Language: en-US

User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)

Accept-Encoding: gzip, deflate

Connection: Keep-Alive

Host: sudixi418vm

Authorization: NTLM TlRMTVNTUAADAAAAGAAYAJYAAABKAUoBrgAAAA4ADgBY <<trimmed>>

below are the request headers for the outbound request from proxy which is reaching the backend server containing the remote_user header with the logged in user value which was fetched from the custom http module configured on proxy server.

GET / HTTP/1.1

Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*

Accept-Encoding: gzip, deflate

Accept-Language: en-US

Authorization: NTLM TlRMTVNTUAADAAAAGAAYAJYAAABKAUoBrgAAAA4ADgBY <<trimmed>>

Host: sudixi483vm

Max-Forwards: 10

User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)

X-Original-URL: /

REMOTE_USER: SUDIXI1\Administrator

X-Forwarded-For: 192.168.2.50:57639

X-ARR-LOG-ID: 1f5e738d-0172-4a8a-8151-7d30337802e9

Connection: Keep-Alive

Hope this helps! Happy Coding!!