Single Sign-on with Nginx

Fri, Jul 20, 2018 2-minute read

Putting a login screen in front of an internal service usually means baking authentication into the service itself. With Nginx, you can keep that concern out of your code entirely. In this post I’ll show how to use Nginx as a reverse proxy to enable single sign-on via Google OAuth2, so the proxy handles who gets in.

The piece that actually talks to Google is GitHub/Bitly’s oauth2_proxy, so that’s the first thing we need. It acts as our authenticator for communicating with the Google API.

Before it can do that, Google needs to know about us, so we create an OAuth2 API from the Google console.

That gives us our client ID and secret key, which we’ll feed to the proxy later.

With credentials in hand, the next job is wiring up Nginx as the reverse proxy, so the flow ends up as request -> nginx -> sso -> backend.

server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;
location /oauth2/ {
    proxy_pass       http://127.0.0.1:4180;
    proxy_set_header Host                    $host;
    proxy_set_header X-Real-IP               $remote_addr;
    proxy_set_header X-Scheme                $scheme;
    proxy_set_header X-Auth-Request-Redirect $request_uri;
  }
  location = /oauth2/auth {
    proxy_pass       http://127.0.0.1:4180;
    proxy_set_header Host             $host;
    proxy_set_header X-Real-IP        $remote_addr;
    proxy_set_header X-Scheme         $scheme;
    proxy_set_header Content-Length   "";
    proxy_pass_request_body           off;
  }

  	location / {
    
    auth_request /oauth2/auth;
    error_page 401 = /oauth2/sign_in;
    auth_request_set $user   $upstream_http_x_auth_request_user;
    auth_request_set $email  $upstream_http_x_auth_request_email;
    proxy_set_header X-User  $user;
    proxy_set_header X-Email $email;

    auth_request_set $auth_cookie $upstream_http_set_cookie;
    add_header Set-Cookie $auth_cookie;

    proxy_pass http://127.0.0.1:8080/; #assume our backend service at localhost 8080 port
  }

With the configuration in place, we start the proxy, handing it the keys and IDs from earlier.

./oauth2_proxy \
   --email-domain="webischia.com"  \
   --upstream=http://127.0.0.1:80/ \
   --cookie-secure=true \
   --client-id=*** \
   --client-secret=***

And that’s all it takes. From here on, anyone with your email domain can sign in to your website.