# oauth2-proxy: an authentication reverse proxy for apps that have no login of their own

> oauth2-proxy sits in front of a web application, redirects unauthenticated visitors to an OAuth2 or OIDC provider, and forwards the resulting identity as HTTP headers. It is a good fit for internal dashboards and legacy apps; it is not an identity provider itself.

**oauth2-proxy/oauth2-proxy** — A reverse proxy that provides authentication with Google, Azure, OpenID Connect and many more identity providers.

- Repository: https://github.com/oauth2-proxy/oauth2-proxy
- Website: http://oauth2-proxy.github.io/oauth2-proxy/
- Stars: 15,035 · Forks: 2,202
- Language: Go
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/oauth2-proxy-oauth2-proxy

## The gap oauth2-proxy fills: apps that never learned to log anyone in

Plenty of software still assumes it lives on a trusted network. A Prometheus instance, an internal admin panel, an old Java console: each serves its pages to whoever asks. Rewriting them to speak OIDC is often more work than the application is worth, and sometimes the source is not available at all. oauth2-proxy takes the opposite approach. It places itself in front of the application as a reverse proxy, intercepts every request, and only lets traffic through once the visitor has completed an OAuth2 or OIDC flow with an external provider. The README describes the project as a tool that can act as a standalone reverse proxy or as middleware inside an existing reverse proxy or load balancer setup, which is the honest description of its scope: it authenticates, it does not manage identities. The audience is platform and infrastructure engineers who already have a provider (Google, Microsoft Entra ID, GitHub, login.gov, or any generic OIDC issuer such as Keycloak) and need to put a login wall in front of something that has none.

## How the request flow works, and where the identity ends up

The mechanism is a redirect loop with a signed cookie in the middle. An unauthenticated browser hits oauth2-proxy, which does not serve the upstream content; it sends the browser to the configured provider's authorization endpoint. After the user authenticates, the provider redirects back to oauth2-proxy's callback path, which exchanges the code for tokens and stores a session in an encrypted cookie. On subsequent requests the proxy validates that cookie and forwards the request upstream. The part that makes this useful rather than merely a gate is what travels with the forwarded request: the README states that specialised provider implementations can extract details about the user such as preferred usernames and groups, and that those details can be forwarded as HTTP headers to upstream applications. That is the integration contract. Your app does not implement OAuth2; it reads a header. The corollary is a security boundary you must respect yourself. If the upstream is reachable directly, bypassing the proxy, the headers mean nothing, and if the upstream trusts a client-supplied header of the same name, the whole scheme collapses. The repository layout reflects this design: providers/ holds the per-provider implementations, pkg/ holds the shared proxy and session logic, and oauthproxy.go and validator.go sit at the top level.

## Installing oauth2-proxy and getting a first login working

The README points to the Installation Docs and to the example setup files under contrib/local-environment in the repository. Two distribution channels are documented: compiled binaries published on GitHub for major architectures plus ppc64le and s390x, and container images. Since v7.6.0 the default image is based on GoogleContainerTools/distroless rather than Alpine; Alpine-based images are still published with tags suffixed with -alpine, for debugging or for architectures such as armv6. The upstream image registry is quay.io/oauth2-proxy/oauth2-proxy. The repository's own Dockerfile documents the environment-variable approach for the JWT signing key, noting that you can build the key into the container and then tell it where it is by setting OAUTH2_PROXY_JWT_KEY_FILE=/etc/ssl/private/jwt_signing_key.pem, which is useful for platforms such as GCP App Engine whose app.yaml cannot hold multi-line values. That same pattern, one environment variable per setting, is how the proxy is configured in a container:

```bash
OAUTH2_PROXY_JWT_KEY_FILE=/etc/ssl/private/jwt_signing_key.pem
```

Configuration can also come from a config file, since the project depends on spf13/viper, and flags are parsed with spf13/pflag. Before you start, generate the cookie secret; the documentation covers this, and it must be a random value of the expected length, not a passphrase you invented. If you are deploying on Kubernetes, the related searches around a Helm chart point at a separate chart repository, not at this one; the chart is not part of the files listed here, so treat its values as a different project's documentation.

## What oauth2-proxy is not: sessions, users and per-tenant isolation

The most common misunderstanding is to treat oauth2-proxy as an identity provider. It is not one. It has no user database, no password reset, no registration, no consent screens of its own. Every credential check happens at the provider. If the provider is down, your application is unreachable, and there is no local fallback unless you build one. The second limitation is subtler and bites people running multi-tenant software. The session lives in a cookie scoped to the proxy, and the upstream receives headers describing whoever holds that cookie. If a single upstream serves many tenants and relies on those headers for authorisation, the isolation between tenants is only as strong as the cookie handling and the header trust model. This is a deliberate design boundary, not a bug, but it means oauth2-proxy is the wrong tool when you need per-request authorisation decisions against a live policy engine. It is also the wrong tool for machine-to-machine APIs: the flow is built around a browser redirect. And note the security history in the README, which flags an open redirect vulnerability affecting versions older than v6.0.0 and states that running such a version is strongly discouraged. Any deployment still on a pre-v6 release is not a configuration problem to tune; it is a version to replace.

## oauth2-proxy versus a full identity platform such as Keycloak

The related searches pair oauth2-proxy with Keycloak often enough that the distinction is worth stating plainly. Keycloak is an identity provider: it stores users, issues tokens, and can itself act as the OIDC issuer. oauth2-proxy is a client of an identity provider. It consumes the OIDC flow and turns the result into a gate plus headers. In practice the two are complementary, and the pairing people search for (oauth2-proxy with Keycloak) is exactly that: Keycloak holds the accounts, oauth2-proxy protects the applications that cannot talk to Keycloak directly. The same logic applies to comparisons with other self-hosted auth front ends. The difference in approach is where the user model lives. A platform that owns the user directory can make authorisation decisions with full knowledge of roles and groups over time; oauth2-proxy makes a decision per request based on what the provider returned and what the cookie carries. If you already have a provider, oauth2-proxy is a thin layer. If you do not, you are adopting two systems, not one.

## Maintenance, releases and what the MIT licence means here

The project is not archived, and the last push to the default branch was on 2026-09-20. Recent releases are v7.15.4 on 2026-08-20, v7.15.3 on 2026-06-09 and v7.15.2 on 2026-04-14, so the release cadence has been roughly every couple of months. The README is explicit about the governance model: it is a community-driven project that relies on contributions, and it warns that review times can vary and that as a volunteer-driven project it may take longer to merge changes. That is a real operational consideration if you depend on a patch landing quickly. Nightly images are built from master and published at quay.io/oauth2-proxy/oauth2-proxy-nightly; the README states these are considered unstable and should not be used for production. Upgrade cost is mostly configuration drift: the project depends on viper for config loading and pflag for flags, so a flag rename or a config key change shows up as a startup failure rather than silent misbehaviour, which is the friendlier failure mode. The licence is MIT, which is permissive and imposes no copyleft obligation on your own code; the README does not discuss trademark or support terms, and this is not legal advice. Security disclosures must go privately to the maintainers listed in MAINTAINERS.md, not through a public issue.

## Where it fits in an nginx or Envoy chain

Two of the most common search phrases around this project involve nginx and Envoy, and both reflect the same deployment shape. Rather than exposing oauth2-proxy to the internet directly, you keep your existing ingress and let it delegate authentication. In an nginx setup, the auth_request directive calls oauth2-proxy on a subrequest; only a 2xx response lets the original request proceed, and nginx then passes the identity headers to the upstream. With Envoy, the equivalent is the external authorisation filter, which calls oauth2-proxy as an authz service before routing. The reason this pattern dominates is that it keeps one authentication component in front of many applications while leaving TLS termination, routing and rate limiting where they already are. The cost is an extra network hop per request and one more component whose availability gates everything behind it. If oauth2-proxy is unreachable, the fail-closed behaviour of auth_request and the external authz filter means the protected routes return errors rather than opening up. That is the correct default, but it makes oauth2-proxy a single point of failure you should plan capacity and health checks around.

## Conclusion

Adopt oauth2-proxy when you have an application that cannot do OIDC itself and you already trust an external provider such as Google, Microsoft Entra ID or Keycloak. Do not adopt it as a user directory, a password store, or a replacement for an identity provider, and do not use it to protect a public multi-tenant SaaS front end where per-tenant session isolation matters. Before rolling it out, verify three things on your own setup: that your cookie secret is generated correctly, that your upstream reads the X-Auth-Request headers rather than trusting client-supplied ones, and that the provider you picked actually returns the groups or username claims you plan to forward.

## FAQ

### What does oauth2-proxy do?

It is a reverse proxy that intercepts requests to your application and redirects users to an OAuth2 or OIDC provider for authentication before letting them through. It can also run as middleware inside an existing reverse proxy or load balancer setup, and it forwards user details such as preferred usernames and groups to upstream applications as HTTP headers.

### Is oauth2-proxy safe?

The project has an OpenSSF Scorecard and OpenSSF Best Practices badge, and security disclosures are handled privately through the maintainers listed in MAINTAINERS.md. The README flags an open redirect vulnerability affecting versions older than v6.0.0 and strongly recommends running a current version. Safety also depends on your own deployment: the upstream must not be reachable except through the proxy, or the forwarded identity headers can be bypassed.

### How do I install oauth2-proxy?

The README points to the Installation Docs and to the example setup files under contrib/local-environment in the repository. Compiled binaries are published on GitHub for major architectures plus ppc64le and s390x, and container images are published at quay.io/oauth2-proxy/oauth2-proxy; since v7.6.0 the default image is based on distroless, with Alpine variants tagged with a -alpine suffix.

### How do I set up oauth2-proxy with a provider such as Keycloak?

You configure a provider, either a specific implementation such as Google or Microsoft Entra ID, or the generic OIDC client that works with any compliant issuer including Keycloak. The README notes that specialised provider implementations can extract more details about the user, such as preferred usernames and groups, and forward them as headers to the upstream application.

### What is the oauth2-proxy cookie secret?

It is the value oauth2-proxy uses to encrypt the session cookie that holds the user's authenticated state between requests. It is supplied through the OAUTH2_PROXY_COOKIE_SECRET environment variable or the equivalent flag, and the documentation covers generating it; it must be a random value of the expected length rather than a chosen passphrase.

## Sources

- [License: MIT](https://github.com/oauth2-proxy/oauth2-proxy/blob/master/LICENSE)
- [oauth2-proxy/oauth2-proxy on GitHub](https://github.com/oauth2-proxy/oauth2-proxy)
- [Project website](http://oauth2-proxy.github.io/oauth2-proxy/)
- [README](https://github.com/oauth2-proxy/oauth2-proxy/blob/master/README.md)
- [Releases](https://github.com/oauth2-proxy/oauth2-proxy/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/oauth2-proxy-oauth2-proxy
