If you self-host web applications — dashboards, admin panels, internal tools, or APIs — one of the first questions you face is: how do I protect them from unauthorized access?
You cannot expose a grafana dashboard, a Portainer instance, or a custom internal API directly to the internet without authentication. Yet managing separate login systems for every service is tedious and error-prone.
The answer is an authentication proxy — a reverse proxy that intercepts requests, verifies the user’s identity against an identity provider (IdP), and forwards authenticated traffic to your backend services. In this guide, we compare the three leading open-source options: OAuth2-Proxy, Pomerium, and Traefik-Forward-Auth.
Why Use a Self-Hosted Auth Proxy?
Self-hosting your authentication proxy gives you full control over who can access your services:
- Single sign-on (SSO) — authenticate once, access all protected services
- Centralized access control — manage permissions from one place
- No per-service auth setup — protect apps that lack built-in authentication
- *Identity provider flexibilitykeycloakGoogle, GitHub, Keycloak, Authentik, OIDC, or dozens of others
- Zero-trust architecture — every request is verified, regardless of network location
Rather than configuring OAuth or basic auth separately for each application, an auth proxy sits in front of everything and handles authentication uniformly.
At a Glance: Comparison Table
| Feature | OAuth2-Proxy | Pomerium | Traefik-Forward-Auth |
|---|---|---|---|
| GitHub Stars | 14,217 | 4,748 | 2,379 |
| Language | Go | Go | Go |
| Last Updated | April 2026 | April 2026 | April 2026 |
| License | Apache 2.0 | Apache 2.0 | MIT |
| IdP Support | 20+ providers | OIDC, Google, Azure | Google, OIDC only |
| Zero-Trust / BeyondCorp | No | Yes (core feature) | No |
| gRPC / mTLS Support | No | Yes | No |
| Policy Engine (RBAC) | Basic headers | Full CEL policies | None |
| WebSocket Support | Yes | Yes | Yes |
| Traefik Integration | Via forwardAuth | Via forwardAuth | Native (same project) |
| docker Image Size | ~25 MB | ~45 MB | ~15 MB |
| Best For | General-purpose auth proxy | Zero-trust / enterprise | Simple Google/OIDC + Traefik |
OAuth2-Proxy: The Swiss Army Knife
OAuth2-Proxy (by the oauth2-proxy organization) is the most widely deployed open-source authentication proxy. It supports over 20 identity providers including Google, GitHub, GitLab, Azure AD, Keycloak, Authentik, and any OIDC-compatible IdP.
It works by intercepting incoming HTTP requests, checking for a valid session cookie, and redirecting unauthenticated users to your IdP’s login page. After successful authentication, it sets a signed cookie and injects user identity headers (X-Auth-Request-User, X-Auth-Request-Email, X-Auth-Request-Groups) into the upstream request — which your backend application can read to implement authorization.
Key Features
- Broad IdP support — Google, GitHub, GitLab, Azure AD, Bitbucket, Keycloak, Authentik, OIDC, and more
- Session management — Redis, Memcached, or cookie-based sessions
- Header injection — passes user identity to upstream services via HTTP headers
- Multiple deployment modes — works with NGINX, Traefik, HAProxy, Caddy, or any reverse proxy via
auth_requestor forward authentication - WebSocket support — can protect WebSocket connections
- Token refresh — automatically refreshes expiring OAuth tokens
Docker Compose Setup
Here is a production-ready Docker Compose configuration for OAuth2-Proxy with Google as the identity provider, sitting behind a reverse proxy:
| |
Generate the required secrets:
| |
NGINX Integration
When deployed behind NGINX, use the auth_request directive to delegate authentication:
| |
This pattern works identically with Traefik (forwardAuth), HAProxy (http-check), and Caddy (forward_auth directive).
Supported Identity Providers
OAuth2-Proxy has first-class support for these providers:
| Provider | Config Value | Notes |
|---|---|---|
google | Most popular, simple setup | |
| GitHub | github | Requires org/team config for access control |
| GitLab | gitlab | Works with self-hosted GitLab instances |
| Azure AD | azure | Supports Microsoft Entra ID |
| Keycloak | keycloak-oidc | Full RBAC via groups |
| Authentik | oidc | Works via generic OIDC provider |
| Any OIDC | oidc | Generic OpenID Connect support |
| Bitbucket | bitbucket | Team-based access control |
facebook | Available but rarely used | |
linkedin | Limited scope data |
Pomerium: Zero-Trust Access Proxy
Pomerium takes a fundamentally different approach. While OAuth2-Proxy is an authentication proxy that adds a login layer, Pomerium implements a full zero-trust / BeyondCorp architecture. Every request is authenticated, authorized, and encrypted — regardless of whether the user is on the internal network or the public internet.
Pomerium’s policy engine uses the Common Expression Language (CEL) to define fine-grained access rules based on user identity, device posture, time of day, and more. It also supports mutual TLS (mTLS) between services and can issue short-lived certificates.
Key Features
- Zero-trust by default — every request is verified, no implicit trust based on network location
- CEL policy engine — define access rules like
allow(user.email == "admin@corp.com" && user.groups.contains("engineering")) - Mutual TLS — automatic mTLS between services with short-lived certificates
- Device posture checks — verify device compliance before granting access
- gRPC and HTTP support — protects both HTTP/HTTPS and gRPC services
- Identity-aware proxy — not just authentication, but full identity propagation
- Built-in audit logging — every access decision is logged
Docker Compose Setup
Pomerium’s official example provides a clean starting point with autocert for TLS:
| |
Pomerium Policy Examples
The policy engine is Pomerium’s most powerful feature. Here are practical examples:
| |
For advanced use cases, CEL expressions allow programmatic access rules:
| |
Traefik-Forward-Auth: Minimalist Google/OIDC Auth
Traefik-Forward-Auth by Thomas Seddon is the simplest of the three. It is purpose-built to work with Traefik’s forwardAuth middleware and supports Google OAuth2 and generic OIDC providers. If you already use Traefik as your reverse proxy and only need Google or OIDC login, this is the lightest option.
Key Features
- Tiny footprint — minimal binary, fast startup, low memory usage
- Traefik native — designed specifically for Traefik’s forward authentication middleware
- Simple configuration — fewer moving parts than OAuth2-Proxy or Pomerium
- Google OAuth2 — one-command Google login for all Traefik services
- Generic OIDC — also supports any OpenID Connect provider
- Domain whitelisting — restrict access to specific email domains
Docker Compose Setup
Traefik-Forward-Auth works alongside Traefik. Here is a complete setup:
| |
Traefik configuration with forward auth middleware:
| |
Docker labels to protect a service:
| |
Choosing the Right Auth Proxy
Choose OAuth2-Proxy when:
- You need support for many identity providers (GitHub, GitLab, Bitbucket, Keycloak, etc.)
- You use NGINX, Caddy, or HAProxy (not just Traefik)
- You want a proven, battle-tested solution with a large community
- You need cookie-based sessions with Redis/Memcached backend
- Your applications read user identity from HTTP headers
Choose Pomerium when:
- You are building a zero-trust architecture
- You need fine-grained access policies (CEL expressions)
- You require mutual TLS between services
- You want device posture checks and conditional access
- You need to protect gRPC services alongside HTTP
- Audit logging of every access decision is required
Choose Traefik-Forward-Auth when:
- You already use Traefik as your reverse proxy
- You only need Google or OIDC authentication
- You want the simplest possible setup with minimal configuration
- You prefer a lightweight binary with low resource usage
- Your access control needs are basic (domain or email whitelisting)
Internal Ecosystem: How These Fit Together
An auth proxy is typically one piece of a larger self-hosted identity stack. For the identity provider itself, you might use a self-hosted IdP like Keycloak, Authentik, Authelia, or Zitadel — see our detailed IAM comparison and Authentik vs Keycloak vs Authelia guide for help choosing.
The auth proxy then sits between your IdP and your services. OAuth2-Proxy and Pomerium both support self-hosted IdPs via generic OIDC, meaning you can run Authentik or Keycloak on your own server and use it as the authentication backend — no Google or Azure dependency required.
For a complete overview of how reverse proxies integrate with auth proxies, see our reverse proxy comparison which covers NGINX, Traefik, Caddy, HAProxy, and their authentication patterns.
FAQ
What is the difference between OAuth2-Proxy and Pomerium?
OAuth2-Proxy is an authentication proxy that verifies user identity and passes it to upstream services via HTTP headers. Pomerium is a full zero-trust access proxy that adds policy-based authorization, mutual TLS, device posture checks, and audit logging on top of authentication. OAuth2-Proxy answers “who is this user?”; Pomerium answers “who is this user, are they authorized, is their device trusted, and should this specific request be allowed?”
Can I use OAuth2-Proxy with Authentik or Keycloak?
Yes. OAuth2-Proxy supports generic OIDC providers, which means any OIDC-compliant identity provider works — including self-hosted options like Authentik, Keycloak, Zitadel, and Ory Hydra. Configure OAUTH2_PROXY_PROVIDER=oidc and set the OIDC discovery URL to point to your IdP.
Does Pomerium replace my reverse proxy?
Not exactly. Pomerium includes its own routing capabilities and can terminate TLS directly, but many deployments run Pomerium behind Traefik, NGINX, or Caddy for certificate management, load balancing, or rate limiting. Pomerium can operate as a sidecar, a standalone proxy, or behind another reverse proxy.
Which auth proxy is easiest to set up?
Traefik-Forward-Auth is the simplest if you already use Traefik — it requires only a few environment variables and Docker labels on each protected service. OAuth2-Proxy requires more configuration but offers far broader IdP support. Pomerium has the steepest learning curve due to its policy engine but provides the most powerful access control.
Can these auth proxies protect WebSocket connections?
OAuth2-Proxy and Pomerium both support WebSocket connections. Traefik-Forward-Auth works with WebSockets through Traefik’s native WebSocket support, as the forward auth check only happens on the initial HTTP upgrade request.
Do I need HTTPS to use an auth proxy?
Yes. All three proxies require HTTPS (or at minimum TLS termination) in production because they set authentication cookies. Without HTTPS, session cookies would be transmitted in plaintext and could be intercepted. Use Let’s Encrypt with your reverse proxy for free, automated TLS certificates.
How do these handle token refresh and session expiry?
OAuth2-Proxy automatically refreshes expiring OAuth tokens and manages session expiry via its cookie or Redis/Memcached session store. Pomerium uses short-lived JWT tokens that are refreshed transparently. Traefik-Forward-Auth relies on Google/OIDC token expiry and re-authenticates users when tokens expire.