Nginx reverse proxy - passthrough basic authenication

36,134

This exact situation took me forever to figure out, but OSS is like that I guess. This post is a year old so maybe the original poster figured it out, or gave up?

Anyway, the problem for me at least was caused by a few things:

  1. IIS expects the realm string to be the same as what it sent to Nginx, but if your Nginx server_name is listening on a different address than the upstream then the server side WWW-Authenticate is not going to be what IIS was expecting and ignore it.
  2. The builtin header module doesn't clear the other WWW-Authenticate headers, particularly the problematic WWW-Authenticate: Negotiate. Using the headers-more module clears the old headers, and adds whatever you tell it to.

After this, I was able to finally push Sharepoint 2010 through Nginx.

Thanks stackoverflow.

server {
    listen 80;
    server_name your.site.com;

    location / {
            proxy_http_version      1.1;
            proxy_pass_request_headers on;
            proxy_set_header        Host            $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

            #proxy_pass_header      Authorization; //This didnt work for me
            more_set_input_headers  'Authorization: $http_authorization';

            proxy_set_header  Accept-Encoding  "";

            proxy_pass              https://sharepoint/;
            proxy_redirect          default;
            #This is what worked for me, but you need the headers-more mod
            more_set_headers        -s 401 'WWW-Authenticate: Basic realm="intranet.example.com"';
    }
}
Share:
36,134
Ryan
Author by

Ryan

Developer working primarily with SharePoint

Updated on July 09, 2022

Comments

  • Ryan
    Ryan almost 2 years

    I am trying to setup nginx as a reverse rpoxy server in front off several IIS web servers who are authenticating using Basic authentication.

    (note - this is not the same as nginx providing the auth using a password file - it should just be marshelling everythnig between the browser/server)

    Its working kind off - but getting repeatedly prompted for auth by every single resource (image/css etc) on a page.

    upstream my_iis_server {
          server 192.168.1.10;
    }
    
    server {
        listen       1.1.1.1:80;
        server_name  www.example.com;  
    
        ## send request back to my iis server ##
        location / {
         proxy_pass  http://my_iis_server;
         proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
         proxy_http_version      1.1;
         proxy_set_header        Connection "";
         proxy_pass_header       Authorization;     
         proxy_redirect off;
         proxy_buffering off;
         proxy_set_header        Host            $host;
         proxy_set_header        X-Real-IP       $remote_addr;
         proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
       }
    }
    
  • Ryan
    Ryan over 10 years
    The original poster did indeed give up and instead tried Microsofts IIS Application Request Routing (ARR) which did handle Basic and NTML auth without any problems, but caused some very strange problems with some of SharePoint 2013's Minimal Download Strategy (MDS) that I never got to the bottom off.
  • czerasz
    czerasz over 9 years
    Maybe this could be helpful: serverfault.com/questions/230749/…
  • Jonathan
    Jonathan almost 8 years
    @matt Hi I need to pass sth like username:password instead of realm="etc" will this still work?
  • deathangel908
    deathangel908 over 6 years
    more_set_input_headers more_set_headers what are those?
  • joaumg
    joaumg over 4 years
    @deathangel908 they are directives from headers-more module (github.com/openresty/headers-more-nginx-module) which can be compiled with nginx to add more functionalities.
  • argonym
    argonym almost 3 years
    The WWW-Authenticate header including the realm is sent by the upstream server (IIS), so it's certainly not expected by IIS in a client's request. Also it wouldn't make sense to define proxy_pass_header Authorization as that header is part of a client's request; and it should be passed by default as-is, so I don't know why the more_set_input_headers is needed.