Passing Static Credentials Upstream through NGinx: Making NGinx add credentials to upstream requests

Just over a year ago we went over how to setup a reverse proxy that would require our users to authenticate. In our original proxy article, we generated some NGinx configuration that looked a bit like…

location / {
    proxy_pass              http://jira;
    proxy_set_header        Host            $host;
    proxy_set_header        X-Real-IP       $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
}

And it worked. And everyone was happy. Until the day the request came in that NGinx should add a fixed set of credentials to all upstream web requests. Augh! Panic!

Let’s Do This!

Luckily, this isn’t too big of a request. We need only ask NGinx to pass an Authorization header upstream. That equates to exactly one extra directive:

    proxy_set_header        Authorization   "Basic am9ldXNlcjpzdXBlcnNlY3JldHBhc3N3b3Jk";

If you paid attention in the first part of the series, you’ll likely recognize proxy_set_header is adding a header named Authorization with some strange looking value. This value is made of two parts: “Basic” which, you might have guessed, indicates the use of basic authentication. And the second part? The credentials.

Basic authentication expects credentials to be a Base64 encoded string in the form username:password, or as I used for this example:

joeuser:mysupersecretpassword

If you try that string with an encoder, such as this one, you’ll see that you get the same string that I did. Now, just tuck that line in with the rest of our proxy headers and we’ll be good to go.

location / {
    proxy_pass              http://jira;
    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_set_header        Authorization   "Basic am9ldXNlcjpzdXBlcnNlY3JldHBhc3N3b3Jk";
}

And there we have it. Our requests now provide our upstream host with a fixed set of credentials.

Security PSA

Yay! All of our upstream requests contain an authorization header with our plain-text credentials! Yay… Wait a minute. What are you trying to pull?

Ah yes. The little matter of credentials. We might take just another second for this one. Since the credentials are Base64 encoded, they can be Base64 decoded, resulting in our credentials once again.

So, and this is very important, if you are going to pass credentials upstream, be aware that unless your upstream is HTTPS, those headers are readable by everyone between you and your upstream host. If all of the hops between your reverse proxy and your upstream are inside your network, this might not be an issue. Either way though, it is still worth remembering.

Additionally, regardless of whoever else sees the credentials, the upstream server will. If there is any possibility that the upstream server might not be fully trustable, remember that you are effectively tagging a Post-It note with credentials onto the request, just as if you had typed those details into a login form.