Secure Internal Dashboards with OAuth2 Proxy: Block Unauthorized Access in a 15-Minute Setup

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Why You Shouldn’t Leave Your Dashboards “Exposed”

As DevOps engineers, we frequently deploy tools like Prometheus, Grafana, or internal dashboards. The catch is that many of these tools either lack a built-in login feature or have extremely weak Role-Based Access Control (RBAC).

To be honest, I’ve learned the hard way. I used to think that running a dashboard on an obscure port (like 8081 or 9090) was enough. The result? One morning while checking logs, I found over 5,000 brute-force SSH requests and a barrage of scans from unknown IPs. The lesson learned: anything exposed to the Internet must have a proper authentication layer.

Instead of wasting time coding a custom login module for every app, OAuth2 Proxy is a lifesaver. It acts as a protection layer (Reverse Proxy) sitting in front of your application. Want to view a Grafana chart? Users are forced to log in via company Google or GitHub accounts. Only after successful authentication will OAuth2 Proxy grant access.

Real-world OAuth2 Proxy Setup

There are many ways to install it, but I prefer using Docker Compose. This approach helps you manage configurations centrally and makes it easy to deploy across different environments.

1. Register an OAuth Provider with Google

First, you need a set of keys from the Google Cloud Console to enable the login feature:

  • Go to the Google Cloud Console and create a Project.
  • Navigate to APIs & Services > Credentials.
  • Create an OAuth client ID for a Web application.
  • In the Authorized redirect URIs field, enter the exact address: https://your-dashboard.com/oauth2/callback.

2. Quick Deployment with Docker Compose

Here is the docker-compose.yml file I typically use. Let’s assume your internal app is running on port 8080.

version: '3'
services:
  oauth2-proxy:
    image: quay.io/oauth2-proxy/oauth2-proxy:latest
    ports:
      - "4180:4180"
    environment:
      OAUTH2_PROXY_PROVIDER: "google"
      OAUTH2_PROXY_CLIENT_ID: "your-id.apps.googleusercontent.com"
      OAUTH2_PROXY_CLIENT_SECRET: "your-secret"
      # Generate secret using: python3 -c 'import os,base64; print(base64.urlsafe_b64encode(os.urandom(16)).decode())'
      OAUTH2_PROXY_COOKIE_SECRET: "dGhpcy1pcy1hLXNlY3JldC1rZXk=" 
      OAUTH2_PROXY_EMAIL_DOMAINS: "yourcompany.com" 
      OAUTH2_PROXY_UPSTREAMS: "http://your-app:8080"
      OAUTH2_PROXY_HTTP_ADDRESS: "0.0.0.0:4180"
      OAUTH2_PROXY_REDIRECT_URL: "https://your-dashboard.com/oauth2/callback"

Professional Nginx Integration Strategy

In practice, we rarely let OAuth2 Proxy handle traffic directly. The optimal approach is using Nginx as an entry point to handle SSL and request routing.

Leveraging the auth_request Module

This tip is worth its weight in gold: use the auth_request directive. When a request comes in, Nginx asks OAuth2 Proxy if the user is logged in. If yes, it passes through; if not, it immediately redirects them to the Google Login page.

Sample Nginx configuration for you:

server {
    listen 443 ssl;
    server_name dashboard.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    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-Auth-Request-Redirect $request_uri;
    }

    location / {
        auth_request /oauth2/auth;
        error_page 401 = /oauth2/start?rd=$scheme://$host$request_uri;

        # Pass user info into headers for backend processing if needed
        auth_request_set $email  $upstream_http_x_auth_request_email;
        proxy_set_header X-Email $email;

        proxy_pass http://127.0.0.1:8080;
    }
}

Critical Parameters to Note

  • Cookie Secret: This is the string used to encrypt the login session in the browser. Never use the default string to avoid session spoofing.
  • Email Domains: If setting this up for a company, specify the domain (e.g., yourcompany.com). Setting it to * means anyone with a Gmail account can gain access, which is very risky.
  • auth_request: This mechanism allows for background session checks without disrupting the user experience.

Testing and Troubleshooting

After restarting the service, try accessing the domain. If the Google Login screen appears instead of the Dashboard, congratulations, you’ve succeeded.

Quick Debugging Tips

The most common error is Invalid Redirect URI, usually caused by an incorrectly declared URL in the Google Console. Check the container logs to diagnose the issue:

docker logs -f oauth2-proxy-container-id

A “clean” log entry upon successful login will look like this:

[2023/10/27 10:00:01] [auth.go:12] authenticated user: "[email protected]"

3 Additional Real-World Tips

  • Restrict by GitHub Team: If using GitHub, you can restrict access to specific teams like SRE or Lead-Dev using the --github-team flag.
  • Auto Refresh Token: Configure --cookie-refresh to about 1 hour to ensure sessions stay fresh without forcing users to log in constantly.
  • Hardening Headers: Always add X-Frame-Options: DENY in Nginx to block clickjacking attacks on your admin panel.

Implementing OAuth2 Proxy takes only about 15-30 minutes, but the security benefits are massive. You’ll no longer have to worry about managing dozens of individual passwords or exposing dashboard ports. Good luck with your setup and sleep better at night!

Share: