Based on Debian 10 "Buster" environment.

SSO with NGINX and Vouch Proxy

These configuration examples are based on the article "Use nginx to Add Authentication to Any Application" with some updates and additionals.

In this way, you can enable the OpenID Connect (OIDC) authentication with NGINX and Vouch Proxy. You don't need to implement the login mechanism to each application running behind the NGINX reverse proxy. In addition, user management can be completed in the ID management provider side (not within each application).

Prerequisites

System requirement

  1. NGINX with "auth_request" module
    • auth_request is included in any NGINX flavors of Debian package.
  2. docker.io or golang environment
    • Vouch Proxy is not available as Debian package, but it offers a docker image.
    • Compiling from the go source is another option.

The case

These examples are based on the case below.

  • The application is running on "app.example.com"
    • There can be app2, app3, and more
  • Vouch Proxy server is on "vouch.example.com"
  • All sites (applications) are connected via HTTPS
    • Using HTTP will affect the Vouch Proxy configurations
  • Using Okta for SSO gateway
    • It should work with any kind of OIDC (OpenID Connect) provider.

Vouch Proxy is compatible with many kinds of ID providers, such as GitHub and Google. This page will help you work with such providers.
Please have a look at the official examples.

Okta application

Okta offers the developer account for testing (free of charge up to 1,000 monthly active users). Visit developer.okta.com to start testing with this account.

The application should be set up according to the blog post.

  • This application doesn't show up to the User Home
  • To use this app as an authenticator, users have to visit directly to the application URL, not the Okta dashboard. (Then NGINX will redirect to the Vouch, Vouch will redirect to Okta.)

Set up Vouch Proxy

The easiest way to start Vouch Proxy is the docker image. To use the image, you'd better use NGINX as a reverse proxy.

Configure the NGINX site as a reverse proxy

Make a site configuration in /etc/nginx/sites-available and enable it. This will work as a reverse proxy to pass the connection to Vouch Proxy

Prepare configuration

Make /etc/vouch/config directory and store the following sample. This is based on the config example on the official site.
(keep the filename as config.yml)

Starting Vouch Proxy for the first time  (or upgrading)

Pull the docker image and run it with the prepared config file.

# docker run -d -p 9090:9090 --name vouch-proxy -v /etc/vouch/config:/config voucher/vouch-proxy
  • "-d" to use detached mode (run in the background)
  • "-p 9090:9090" to connect the port 9090 to the docker image 9090. If you want to use port 1090 redirected to Vouch Proxy, the option should be "-p 1090:9090"
  • "--name vouch-proxy" to use a short name to handle the image
  • "-v /etc/vouch/config:/config" to let the image to use /etc/vouch/config host directory as /config directory

Stop and Start the image

Once the image is started with the command above, the image can be handled with the name "vouch-proxy"

# docker stop vouch-proxy
# docker start vouch-proxy

If you change config.yml, then you need to restart the image to reload it.

Remove image

When you want to upgrade, remove the image before pulling the latest docker image.

# docker rm vouch-proxy
# docker rmi voucher/vouch-proxy

Then redo the initial docker run command above to pull the latest image and run.


Set up the application site

Set the NGINX as a reverse proxy, and let it redirect to the Vouch Proxy using the auth_request module.

Prepare the snippet for authentication

To reuse in the multiple sites, prepare a snippet in /etc/nginx/snippets

Configure the application site

Set up a site for "app.example.com" in /etc/nginx/sites-available

  • "snippets/ssl_example.com.conf" is a snippet to configure the ssl certificates and other related configurations.
  • user information is available with the following codes
    • PHP: $_SERVER['REMOTE_USER']
    • Ruby on Rails: request.env["HTTP_REMOTE_USER"]
    • Ruby Sinatra: same as above

Enable configurations

Reload NGINX to enable the site configurations.

# systemctl reload nginx

Tips

Logs for troubleshooting

There should be some hints on the logs.

NGINX logs are located in /var/log/nginx/
Vouch Proxy logs are available with the following command.

# docker logs vouch-proxy

allowAllUsers

The default configuration offers to specify the domains. Here is the difference.

Specifying the domains.

  • Application: app.example.com
  • Vouch Proxy: vouch.example.com
  • Users' mail addresses: name@mail.example.jp

With the above situation, the configuration should look like as below.

vouch:
  domains:
  - example.com
  - example.jp

If the users' mail addresses have a variety of domains, you have to list up all of them to permit the access.
This can be used to restrict the users with the specific mail domains by extracting them in the configuration, but that kind of management should be controlled in the OIDC provider side.

Instead of listing the domains, use "allowAllUsers: true" to accept anybody who is allowed in the OIDC provider side.
Even if you prefer this type, you still need to specify which domain to be used for the cookies. This will be the domain to be protected, i.e. callback and application domain.

vouch:
  allowAllUsers: true
  cookie:
    domain: example.com

Skipping the check

With the configuration explained in this page, any access will be checked. This means the batch jobs from the localhost will be redirected to the check.
For example, if a cronjob accesses the protected site with the headless chromium, it will still be redirected to the authentication (and probably that job will fail).

I couldn't find the good way to set the exception of accesses on NGINX nor Vouch Proxy, this can be realized simply opening another port for the HTTPS service.

Port 443 for the any inbound HTTPS access

  • This connection requires the authentication

Port 1443 for the HTTPS only from the localhost

  • This connection doesn't require the authentication
  • Firewall will block the inbound access to this port except for the localhost loopback

Both ports redirect to the backend application, but 1443 doesn't require the authentication and only available for the local loopback access.

Directly connecting to the backend port is another solution, only if the application is using the tcp port. (This is useful if the backend is running on the docker, but many native applications may be using Unix sockets...)

Less frequent authentication

If you feel there are too frequent redirection to the OIDC provider, you can extend the expiration of jwt.
Extend vouch.jwt.maxAge as well as vouch.cookie.maxAge.
In my case, it's 900 minutes (15 hours) to aim for the "once a day on the business hours" frequency.

vouch:
  cookie:
    maxAge: 900
  jwt:
    maxAge: 900