mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2026-10-17 20:17:03 +02:00
release: v7.15.5 (#3553)
* update to release version v7.15.5 * Merge commit from fork Signed-off-by: Jan Larwig <jan@larwig.com> Co-authored-by: blakeroberts-wk <blake.roberts@workiva.com> * Merge commit from fork Signed-off-by: Jan Larwig <jan@larwig.com> * Merge commit from fork * fix: validate trusted IP proxy headers Respect trusted proxy boundaries before using real-client-IP headers for authentication bypass decisions and safely traverse X-Forwarded-For chains. Signed-off-by: Jan Larwig <jan@larwig.com> * fix: trusted-ip header bypass Signed-off-by: Jan Larwig <jan@larwig.com> * docs: add changelog entry Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> --------- Signed-off-by: Jan Larwig <jan@larwig.com> Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> * docs: changelog for v7.15.5 Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> * docs: update order of owners for prow Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> * ci: make the linter happy again Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> --------- Signed-off-by: Jan Larwig <jan@larwig.com> Signed-off-by: Jan Larwig <jan.larwig@digits.schwarz> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Jan Larwig <jan@larwig.com> Co-authored-by: blakeroberts-wk <blake.roberts@workiva.com> Co-authored-by: Jan Larwig <jan.larwig@digits.schwarz>
This commit is contained in:
co-authored by
blakeroberts-wk
Jan Larwig
Jan Larwig
parent
e05f04ef08
commit
bea3f04bf8
@@ -32,6 +32,11 @@ When integrating with Kubernetes web UIs, make sure to:
|
||||
Most integrations require the following OAuth2 Proxy configuration:
|
||||
|
||||
- `--reverse-proxy=true`: Required to correctly handle `X-Forwarded-*` headers
|
||||
- `--trusted-proxy-ip=<proxy CIDR>`: Restricts forwarded headers, including
|
||||
client identity used by `--trusted-ip`, to the reverse proxies' addresses or
|
||||
networks. Include the direct peer and every trusted hop that can appear in
|
||||
XFF. Without this option, all source addresses are trusted for backwards
|
||||
compatibility.
|
||||
- **Session storage**: For production deployments with large tokens due to a lot of claims like AD groups, use `--session-store-type=redis`
|
||||
|
||||
For provider-specific configuration, see the [OAuth Provider Configuration](../providers/index.md) documentation.
|
||||
|
||||
@@ -15,6 +15,17 @@ Configure OAuth2 Proxy with Nginx using the `auth_request` directive. Includes e
|
||||
|
||||
**This option requires `--reverse-proxy` option to be set.**
|
||||
|
||||
When Nginx connects from localhost as shown below, also configure OAuth2 Proxy
|
||||
with `--trusted-proxy-ip=127.0.0.1/32`. The example overwrites `X-Real-IP` with
|
||||
Nginx's transport peer address; do not pass through a client-supplied value,
|
||||
especially when `--trusted-ip` is enabled.
|
||||
|
||||
If using `--real-client-ip-header=X-Forwarded-For` with an appending proxy
|
||||
configuration such as `$proxy_add_x_forwarded_for`, list every trusted proxy hop
|
||||
in `--trusted-proxy-ip`. OAuth2 Proxy selects the first untrusted address from
|
||||
the right, not a client-supplied leftmost entry. The trust-all compatibility
|
||||
default cannot provide this protection.
|
||||
|
||||
The [Nginx `auth_request` directive](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) allows Nginx to authenticate requests via the oauth2-proxy's `/auth` endpoint, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the request through. For example:
|
||||
|
||||
```nginx
|
||||
@@ -60,23 +71,23 @@ server {
|
||||
auth_request_set $auth_cookie $upstream_http_set_cookie;
|
||||
add_header Set-Cookie $auth_cookie;
|
||||
|
||||
# When using the --set-authorization-header flag, some provider's cookies can exceed the 4kb
|
||||
# limit and so the OAuth2 Proxy splits these into multiple parts.
|
||||
# Large OIDC tokens can make the session cookie exceed the 4KB limit,
|
||||
# causing OAuth2 Proxy to split the cookie into multiple parts.
|
||||
# Nginx normally only copies the first `Set-Cookie` header from the auth_request to the response,
|
||||
# so if your cookies are larger than 4kb, you will need to extract additional cookies manually.
|
||||
auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1;
|
||||
# so extract the second part when using the default cookie name, `_oauth2_proxy`.
|
||||
auth_request_set $auth_cookie_upstream_1 $upstream_cookie__oauth2_proxy_1;
|
||||
|
||||
# Extract the Cookie attributes from the first Set-Cookie header and append them
|
||||
# to the second part ($upstream_cookie_* variables only contain the raw cookie content)
|
||||
if ($auth_cookie ~* "(; .*)") {
|
||||
set $auth_cookie_name_0 $auth_cookie;
|
||||
set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1";
|
||||
set $auth_cookie_0 $auth_cookie;
|
||||
set $auth_cookie_1 "_oauth2_proxy_1=$auth_cookie_upstream_1$1";
|
||||
}
|
||||
|
||||
# Send both Set-Cookie headers now if there was a second part
|
||||
if ($auth_cookie_name_upstream_1) {
|
||||
add_header Set-Cookie $auth_cookie_name_0;
|
||||
add_header Set-Cookie $auth_cookie_name_1;
|
||||
if ($auth_cookie_upstream_1) {
|
||||
add_header Set-Cookie $auth_cookie_0;
|
||||
add_header Set-Cookie $auth_cookie_1;
|
||||
}
|
||||
|
||||
proxy_pass http://backend/;
|
||||
@@ -91,6 +102,24 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-part session cookies
|
||||
|
||||
The example above is ready to use with the default `--cookie-name=_oauth2_proxy` setting and handles a session split into two cookies. If you configure a custom cookie name, update both references to the second cookie part:
|
||||
|
||||
| Cookie configuration | Nginx upstream cookie variable | `Set-Cookie` name |
|
||||
| --- | --- | --- |
|
||||
| Default (`_oauth2_proxy`) | `$upstream_cookie__oauth2_proxy_1` | `_oauth2_proxy_1=` |
|
||||
| `--cookie-name=my_cookie` | `$upstream_cookie_my_cookie_1` | `my_cookie_1=` |
|
||||
|
||||
For example, with `--cookie-name=my_cookie`, change the relevant lines to:
|
||||
|
||||
```nginx
|
||||
auth_request_set $auth_cookie_upstream_1 $upstream_cookie_my_cookie_1;
|
||||
set $auth_cookie_1 "my_cookie_1=$auth_cookie_upstream_1$1";
|
||||
```
|
||||
|
||||
If a session is split into more than two cookies, repeat the extraction for each additional numeric suffix. For consistently large sessions, prefer `--session-store-type=redis` so only a small session ticket is stored in the browser cookie.
|
||||
|
||||
### Understanding the `error_page` redirect pattern
|
||||
|
||||
The `auth_request` directive expects the authentication endpoint (`/oauth2/auth`) to return:
|
||||
@@ -137,12 +166,11 @@ location @oauth2_signin {
|
||||
|
||||
#### API / Machine routes (no redirect)
|
||||
|
||||
For API endpoints where clients expect a 401/403 status code (not a redirect):
|
||||
For API endpoints where clients expect a 401/403 status code (not a redirect), reuse the same `auth_request` header forwarding configuration from the main example as needed for your backend:
|
||||
|
||||
```nginx
|
||||
location /api/ {
|
||||
auth_request /oauth2/auth;
|
||||
error_page 401 =401; # Pass through the 401 status
|
||||
proxy_pass http://backend/;
|
||||
}
|
||||
```
|
||||
@@ -167,8 +195,6 @@ It is recommended to use `--session-store-type=redis` when expecting large sessi
|
||||
For a complete example of integrating oauth2-proxy with Kubernetes Dashboard on AKS using Azure Entra ID, including RBAC configuration and troubleshooting, see the [Kubernetes Dashboard on AKS](../providers/ms_entra_id.md#kubernetes-dashboard-on-aks) section in the Microsoft Entra ID provider documentation.
|
||||
:::
|
||||
|
||||
You have to substitute *name* with the actual cookie name you configured via --cookie-name parameter. If you don't set a custom cookie name the variable should be "$upstream_cookie__oauth2_proxy_1" instead of "$upstream_cookie_name_1" and the new cookie-name should be "_oauth2_proxy_1=" instead of "name_1=".
|
||||
|
||||
:::note
|
||||
If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated.
|
||||
:::
|
||||
|
||||
@@ -194,9 +194,40 @@ Provider specific options can be found on their respective subpages.
|
||||
### Proxy Options
|
||||
|
||||
:::warning
|
||||
When `--reverse-proxy` is enabled, configure `--trusted-proxy-ip` to the IPs or CIDR ranges of the reverse proxies that are allowed to send `X-Forwarded-*` headers. If you leave it unset, OAuth2 Proxy currently trusts all source IPs for backwards compatibility, which means a client that can reach OAuth2 Proxy directly may be able to spoof forwarded headers.
|
||||
When `--reverse-proxy` is enabled, configure `--trusted-proxy-ip` to the IPs or CIDR ranges of the reverse proxies that are allowed to send `X-Forwarded-*` headers. Include the direct peer and every trusted proxy hop that can appear in `X-Forwarded-For`. If you leave it unset, OAuth2 Proxy currently trusts all source IPs for backwards compatibility, which means a client that can reach OAuth2 Proxy directly may be able to spoof forwarded headers.
|
||||
:::
|
||||
|
||||
### Trusted client IPs behind a reverse proxy
|
||||
|
||||
`--trusted-ip` is an authentication bypass, not a list of trusted reverse
|
||||
proxies. When combining it with `--reverse-proxy`, always configure
|
||||
`--trusted-proxy-ip` with the direct proxy and every trusted intermediate proxy
|
||||
that can appear in XFF, and prevent clients from reaching OAuth2 Proxy directly.
|
||||
|
||||
OAuth2 Proxy accepts `--real-client-ip-header` only from those trusted peers.
|
||||
For `X-Forwarded-For`, it combines repeated header fields in their received order,
|
||||
then walks the chain from right to left and skips addresses covered by
|
||||
`--trusted-proxy-ip`. The first untrusted address is treated as the client;
|
||||
entries to its left are not used. This also applies to client-IP logging and
|
||||
callback diagnostics. For example, if a trusted proxy appends the actual client
|
||||
to `10.0.0.5, 198.51.100.23`, the client is `198.51.100.23`, not the potentially
|
||||
forged `10.0.0.5`. For single-value headers such as `X-Real-IP`, configure the
|
||||
edge proxy to overwrite any value supplied by the client.
|
||||
|
||||
If every address in the chain is in a trusted proxy range, the leftmost address
|
||||
is used for compatibility. Leaving `--trusted-proxy-ip` unset trusts all IPv4 and
|
||||
IPv6 addresses, so it retains this leftmost behavior and does **not** protect
|
||||
against forged XFF entries. Explicit, narrowly scoped proxy ranges are required.
|
||||
|
||||
For a trusted proxy, a missing client-IP header or malformed address encountered
|
||||
before reaching the client does not grant a trusted-IP exemption, even if the
|
||||
proxy's transport IP is in `--trusted-ip`. Logging falls back to the transport IP in these cases;
|
||||
callback diagnostics retain the `transport IP (client IP)` format when both are
|
||||
available. When reverse-proxy mode is disabled or the peer is not trusted, only
|
||||
the transport IP is evaluated. Unix socket connections have no transport IP to
|
||||
exempt; in reverse-proxy mode they retain the existing behavior of accepting
|
||||
client-IP headers, with the same XFF chain resolution.
|
||||
|
||||
| Flag / Config Field | Type | Description | Default |
|
||||
| ----------------------------------------------------------------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| flag: `--allow-query-semicolons`<br/>toml: `allow_query_semicolons` | bool | allow the use of semicolons in query args ([required for some legacy applications](https://github.com/golang/go/issues/25192)) | `false` |
|
||||
@@ -211,19 +242,19 @@ When `--reverse-proxy` is enabled, configure `--trusted-proxy-ip` to the IPs or
|
||||
| flag: `--htpasswd-file`<br/>toml: `htpasswd_file` | string | additionally authenticate against a htpasswd file. Entries must be created with `htpasswd -B` for bcrypt encryption | |
|
||||
| flag: `--htpasswd-user-group`<br/>toml: `htpasswd_user_groups` | string \| list | the groups to be set on sessions for htpasswd users | |
|
||||
| flag: `--proxy-prefix`<br/>toml: `proxy_prefix` | string | the url root path that this proxy should be nested under (e.g. /`<oauth2>/sign_in`) | `"/oauth2"` |
|
||||
| flag: `--real-client-ip-header`<br/>toml: `real_client_ip_header` | string | Header used to determine the real IP of the client, requires `--reverse-proxy` to be set (one of: X-Forwarded-For, X-Real-IP, X-ProxyUser-IP, X-Envoy-External-Address, or CF-Connecting-IP) | X-Real-IP |
|
||||
| flag: `--real-client-ip-header`<br/>toml: `real_client_ip_header` | string | Header used to determine the real IP of the client when the direct caller matches `--trusted-proxy-ip`; requires `--reverse-proxy` (one of: X-Forwarded-For, X-Real-IP, X-ProxyUser-IP, X-Envoy-External-Address, or CF-Connecting-IP) | X-Real-IP |
|
||||
| flag: `--redirect-url`<br/>toml: `redirect_url` | string | the OAuth Redirect URL, e.g. `"https://internalapp.yourcompany.com/oauth2/callback"` | |
|
||||
| flag: `--relative-redirect-url`<br/>toml: `relative_redirect_url` | bool | allow relative OAuth Redirect URL.` | false |
|
||||
| flag: `--reverse-proxy`<br/>toml: `reverse_proxy` | bool | are we running behind a reverse proxy, controls whether headers like X-Real-IP are accepted and allows X-Forwarded-\{Proto,Host,Uri\} headers to be used on redirect selection | false |
|
||||
| flag: `--trusted-proxy-ip`<br/>toml: `trusted_proxy_ips` | string \| list | list of IPs or CIDR ranges allowed to supply `X-Forwarded-*` headers when `--reverse-proxy` is enabled. If not set, OAuth2 Proxy preserves backwards compatibility by trusting all source IPs (`0.0.0.0/0`, `::/0`) and logs a warning at startup. Configure this to your reverse proxy addresses to prevent forwarded header spoofing. | `"0.0.0.0/0", "::/0"` |
|
||||
| flag: `--trusted-proxy-ip`<br/>toml: `trusted_proxy_ips` | string \| list | list of direct proxy IPs or CIDR ranges allowed to supply `X-Forwarded-*` headers when `--reverse-proxy` is enabled. Include every trusted proxy hop that can appear in XFF. If not set, OAuth2 Proxy preserves backwards compatibility by trusting all source IPs (`0.0.0.0/0`, `::/0`) and logs a warning at startup. | `"0.0.0.0/0", "::/0"` |
|
||||
| flag: `--signature-key`<br/>toml: `signature_key` | string | GAP-Signature request signature key (algorithm:secretkey) | |
|
||||
| flag: `--skip-auth-preflight`<br/>toml: `skip_auth_preflight` | bool | will skip authentication for OPTIONS requests | false |
|
||||
| flag: `--skip-auth-regex`<br/>toml: `skip_auth_regex` | string \| list | (DEPRECATED for `--skip-auth-route`) bypass authentication for requests paths that match (may be given multiple times) | |
|
||||
| flag: `--skip-auth-route`<br/>toml: `skip_auth_routes` | string \| list | bypass authentication for requests that match the method & path. Format: method=path_regex OR method!=path_regex. For all methods: path_regex OR !=path_regex | |
|
||||
| flag: `--skip-auth-regex`<br/>toml: `skip_auth_regex` | string \| list | (DEPRECATED for `--skip-auth-route`) bypass authentication for requests whose paths match (may be given multiple times). Matching uses the decoded path without query parameters; invalid or ambiguous paths cannot grant a path exemption. See [Skip-auth path matching](#skip-auth-path-matching). | |
|
||||
| flag: `--skip-auth-route`<br/>toml: `skip_auth_routes` | string \| list | bypass authentication for requests that match the method & path. Format: method=path_regex OR method!=path_regex. For all methods: path_regex OR !=path_regex. Matching uses the decoded path without query parameters; invalid or ambiguous paths cannot grant a path exemption, including with negated rules. See [Skip-auth path matching](#skip-auth-path-matching). | |
|
||||
| flag: `--skip-jwt-bearer-tokens`<br/>toml: `skip_jwt_bearer_tokens` | bool | will skip requests that have verified JWT bearer tokens (the token must have [`aud`](https://en.wikipedia.org/wiki/JSON_Web_Token#Standard_fields) that matches this client id or one of the extras from `extra-jwt-issuers`) | false |
|
||||
| flag: `--skip-provider-button`<br/>toml: `skip_provider_button` | bool | will skip sign-in-page to directly reach the next step: oauth/start | false |
|
||||
| flag: `--ssl-insecure-skip-verify`<br/>toml: `ssl_insecure_skip_verify` | bool | skip validation of certificates presented when using HTTPS providers | false |
|
||||
| flag: `--trusted-ip`<br/>toml: `trusted_ips` | string \| list | list of IPs or CIDR ranges to allow to bypass authentication (may be given multiple times). When combined with `--reverse-proxy` and optionally `--real-client-ip-header` this will evaluate the trust of the IP stored in an HTTP header by a reverse proxy rather than the layer-3/4 remote address. WARNING: trusting IPs has inherent security flaws, especially when obtaining the IP address from an HTTP header (reverse-proxy mode). Use this option only if you understand the risks and how to manage them. | |
|
||||
| flag: `--trusted-ip`<br/>toml: `trusted_ips` | string \| list | list of client IPs or CIDR ranges allowed to bypass authentication (may be given multiple times). With `--reverse-proxy`, the selected real-client-IP header is accepted only from direct callers matching `--trusted-proxy-ip`; otherwise the transport peer address is used. WARNING: this option bypasses authentication. Configure explicit trusted proxy ranges and ensure the proxy sanitizes client-IP headers. | |
|
||||
| flag: `--whitelist-domain`<br/>toml: `whitelist_domains` | string \| list | allowed domains for redirection after authentication. Prefix domain with a `.` or a `*.` to allow subdomains (e.g. `.example.com`, `*.example.com`) [^2] | |
|
||||
|
||||
[^2]: When using the `whitelist-domain` option, any domain prefixed with a `.` or a `*.` will allow any subdomain of the specified domain as a valid redirect URL. By default, only empty ports are allowed. This translates to allowing the default port of the URL's protocol (80 for HTTP, 443 for HTTPS, etc.) since browsers omit them. To allow only a specific port, add it to the whitelisted domain: `example.com:8080`. To allow any port, use `*`: `example.com:*`.
|
||||
@@ -273,6 +304,34 @@ When `--reverse-proxy` is enabled, configure `--trusted-proxy-ip` to the IPs or
|
||||
| flag: `--upstream-timeout`<br/>toml: `upstream_timeout` | duration | maximum amount of time the server will wait for a response from the upstream | 30s |
|
||||
| flag: `--upstream`<br/>toml: `upstreams` | string \| list | the http url(s) of the upstream endpoint, file:// paths for static files or `static://<status_code>` for static response. Routing is based on the path | |
|
||||
|
||||
### Skip-auth path matching
|
||||
|
||||
Both `--skip-auth-route` and the deprecated `--skip-auth-regex` match the
|
||||
percent-decoded path, excluding query parameters. In reverse-proxy mode,
|
||||
`X-Forwarded-Uri` is used only when the existing forwarded-header trust checks
|
||||
permit it. Original-URI metadata must use origin form (`/path?query`), not an
|
||||
absolute URL, authority, or relative path.
|
||||
|
||||
Invalid or ambiguous targets do not grant a path-based authentication exemption.
|
||||
This check happens before any regular expression or its negation is evaluated.
|
||||
In particular, exemptions are declined for malformed path escapes, `.` or `..`
|
||||
path segments, repeated slashes (including leading `//`), semicolons, backslashes,
|
||||
fragment-like `#` content, decoded `?` characters, and control characters.
|
||||
Encoded forms are checked after a single decoding pass; paths are not recursively
|
||||
decoded.
|
||||
|
||||
This intentionally also requires normal authentication for valid semicolon paths
|
||||
such as `/public/file;version=1` and repeated-slash paths such as `/public//file`.
|
||||
Fragments are no longer silently stripped. Ordinary query strings do not affect
|
||||
matching. Unambiguous escaped characters remain supported, and trailing slashes
|
||||
remain significant: `/public` and `/public/` are distinct matching paths.
|
||||
|
||||
These checks do not normalize or rewrite the upstream request target. A declined
|
||||
path exemption follows normal authentication and authorization; it is not an
|
||||
unconditional rejection of authenticated requests using unusual paths. Existing
|
||||
router redirects and separately configured exemptions, such as trusted client
|
||||
IPs or skipped preflight requests, are unchanged.
|
||||
|
||||
## Configuration Validation
|
||||
|
||||
The `--config-test` flag validates your configuration file without starting the proxy server. This is useful for:
|
||||
@@ -361,7 +420,7 @@ Logging of requests to the `/ping` endpoint (or using `--ping-user-agent`) and t
|
||||
|
||||
## Auth Log Format
|
||||
|
||||
Authentication logs are logs which are guaranteed to contain a username or email address of a user attempting to authenticate. These logs are output by default in the below format:
|
||||
Authentication logs describe authentication attempts. They include the user's username or email address when known, or `-` otherwise. OAuth callback diagnostics for missing or invalid CSRF cookies are authentication logs, controlled by `--auth-logging`, and include cookie names but not cookie values. These logs are output by default in the below format:
|
||||
|
||||
```
|
||||
<REMOTE_ADDRESS> - <REQUEST ID> - <user@domain.com> [2015/03/19 17:20:19] [<STATUS>] <MESSAGE>
|
||||
@@ -392,7 +451,7 @@ Available variables for auth logging:
|
||||
| RequestMethod | GET | The request method. |
|
||||
| Timestamp | 2015/03/19 17:20:19 | The date and time of the logging event. |
|
||||
| UserAgent | - | The full user agent as reported by the requesting client. |
|
||||
| Username | username@email.com | The email or username of the auth request. |
|
||||
| Username | username@email.com | The email or username of the auth request, or `-` if not yet known. |
|
||||
| Status | AuthSuccess | The status of the auth request. See above for details. |
|
||||
|
||||
## Request Log Format
|
||||
|
||||
@@ -5,7 +5,7 @@ title: Installation
|
||||
|
||||
1. Choose how to deploy:
|
||||
|
||||
a. Using a [Prebuilt Binary](https://github.com/oauth2-proxy/oauth2-proxy/releases) (current release is `v7.15.4`)
|
||||
a. Using a [Prebuilt Binary](https://github.com/oauth2-proxy/oauth2-proxy/releases) (current release is `v7.15.5`)
|
||||
|
||||
b. Using Go to install the latest release
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user