* Strip the port from the request host when matching cookie domains
GetCookieDomain suffix-matches the request host against each configured
cookie domain. When a reverse proxy rewrites the Host header to the
upstream's address, that host arrives as "host:port" and never matches,
so the request falls through to the "did not match any of the specific
cookie domains" warning and the shortest configured domain is used.
One way to hit this is Traefik's Errors middleware: it fetches a page
from a Service on port 443 with passHostHeader disabled, and forwards
the Host as "<host>:443". The request reaches oauth2-proxy correctly and
the resulting cookie is still usable, but every such request logs an
error that suggests a misconfiguration when none exists.
warnInvalidDomain, a few lines below in the same file, already calls
net.SplitHostPort on the host before comparing it to the cookie domain.
This makes GetCookieDomain consistent with it.
Tests cover a Host header with a port, an X-Forwarded-Host header with a
port, a non-standard port, and a host with a port that matches no
configured domain.
Signed-off-by: Kiril Jurbinsky <kiril@instaffo.com>
* chore: add changelog entry for #3546
Signed-off-by: Kiril Jurbinsky <kiril@instaffo.com>
* test: keep the new port entries at the end of the table
The port cases were inserted between the Host and X-Forwarded-Host
variants of the existing suffix-match case, which split a pair that
reads as one. Move them after the last existing entry instead.
Signed-off-by: Kiril Jurbinsky <kiril@instaffo.com>
* test: pin that a port part can no longer match a cookie domain
SplitHostPort does not require the port to be numeric, so a host such as
"evil.com:.cookies.test" used to suffix-match a configured cookie domain
through its port part, and the cookie was then set for that domain. Matching
now runs against the host alone, so it does not.
Covers both the Host header and X-Forwarded-Host, since GetRequestHost
returns one or the other into the same comparison.
A Host of this shape cannot be expressed through the request URL, because
http.NewRequest rejects it as an invalid port, so the table gains a rawHost
field that assigns req.Host after the request is built. That is how a server
populates it from the wire, and pkg/upstream and pkg/middleware already set
req.Host the same way in their tests.
Thanks to @Lrifton92 for spotting this.
Signed-off-by: Kiril Jurbinsky <kiril@instaffo.com>
---------
Signed-off-by: Kiril Jurbinsky <kiril@instaffo.com>
The package under pkg/clock is github.com/benbjohnson/clock, which is
archived. It's also way more complex than is what is actually needed
here, so we can entirely remove the dependency and remove the helper
package.
Fixes#2840.
Signed-off-by: David Symonds <dsymonds@gmail.com>
* Allow setting maximum number of csrf cookies, deleting the oldest if necessary
* Add a test for multiple CSRF cookies to remove the old cookie
* Add docs/changelog
* If limit is <=0 do not clear
Signed-off-by: test <bert@transtrend.com>
* Better docs
Co-authored-by: Jan Larwig <jan@larwig.com>
* direct check of option value
Co-authored-by: Jan Larwig <jan@larwig.com>
* direct use of option value
Co-authored-by: Jan Larwig <jan@larwig.com>
* sort based on clock compare vs time compare
Co-authored-by: Jan Larwig <jan@larwig.com>
* clock.Clock does not implement Compare, fix csrf cookie extraction after rename
Signed-off-by: Bert Helderman <bert@transtrend.com>
* Linter fix
* add method signature documentation and slight formatting
Signed-off-by: Jan Larwig <jan@larwig.com>
* fix: test case for csrf cookie limit and flag
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: Bert Helderman <bert@transtrend.com>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: test <bert@transtrend.com>
Co-authored-by: bh-tt <71650427+bh-tt@users.noreply.github.com>
* Issue 2311: runtime error: index out of range [0] with length 0 while extracting state of of the csrf
---------
Co-authored-by: tuunit <jan@larwig.com>
* Create session cookie when cookie-expire set 0
* Fix format
* add test
* fix lint error
* fix test code
* fix conflicted test case
* update test case of cookie expiration
* update tests of csrf cookies
* update docs
* Update docs/docs/configuration/overview.md
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
---------
Co-authored-by: tanuki884 <morkazuk@fsi.co.jp>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add the allowed_email_domains and the allowed_groups on the auth_request endpoint + support standard wildcard char for validation with sub-domain and email-domain.
Signed-off-by: Valentin Pichard <github@w3st.fr>
* Fix provider data initialisation
* PKCE Support
Adds Code Challenge PKCE support (RFC-7636) and partial
Authorization Server Metadata (RFC-8414) for detecting PKCE support.
- Introduces new option `--force-code-challenge-method` to force a
specific code challenge method (either `S256` or `plain`) for instances
when the server has not implemented RFC-8414 in order to detect
PKCE support on the discovery document.
- In all other cases, if the PKCE support can be determined during discovery
then the `code_challenge_methods_supported` is used and S256 is always
preferred.
- The force command line argument is helpful with some providers like Azure
who supports PKCE but does not list it in their discovery document yet.
- Initial thought was given to just always attempt PKCE since according to spec
additional URL parameters should be dropped by servers which implemented
OAuth 2, however other projects found cases in the wild where this causes 500
errors by buggy implementations.
See: https://github.com/spring-projects/spring-security/pull/7804#issuecomment-578323810
- Due to the fact that the `code_verifier` must be saved between the redirect and
callback, sessions are now created when the redirect takes place with `Authenticated: false`.
The session will be recreated and marked as `Authenticated` on callback.
- Individual provider implementations can choose to include or ignore code_challenge
and code_verifier function parameters passed to them
Note: Technically speaking `plain` is not required to be implemented since
oauth2-proxy will always be able to handle S256 and servers MUST implement
S256 support.
> If the client is capable of using "S256", it MUST use "S256", as "S256"
> is Mandatory To Implement (MTI) on the server. Clients are permitted
> to use "plain" only if they cannot support "S256" for some technical
> reason and know via out-of-band configuration that the server supports
> "plain".
Ref: RFC-7636 Sec 4.2
oauth2-proxy will always use S256 unless the user explicitly forces `plain`.
Fixes#1361
* Address PR comments by moving pkce generation
* Make PKCE opt-in, move to using the Nonce generater for code verifier
* Make PKCE opt-in, move to using the Nonce generater for code verifier
* Encrypt CodeVerifier in CSRF Token instead of Session
- Update Dex for PKCE support
- Expose HTTPBin for further use cases
* Correct the tests
* Move code challenges into extra params
* Correct typo in code challenge method
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Correct the extra space in docs
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Address changelog and new line nits
* Add generated docs
Co-authored-by: Valentin Pichard <github@w3st.fr>
Co-authored-by: Joel Speed <joel.speed@hotmail.co.uk>
* Set and verify a nonce with OIDC
* Create a CSRF object to manage nonces & cookies
* Add missing generic cookie unit tests
* Add config flag to control OIDC SkipNonce
* Send hashed nonces in authentication requests
* Encrypt the CSRF cookie
* Add clarity to naming & add more helper methods
* Make CSRF an interface and keep underlying nonces private
* Add ReverseProxy scope to cookie tests
* Align to new 1.16 SameSite cookie default
* Perform SecretBytes conversion on CSRF cookie crypto
* Make state encoding signatures consistent
* Mock time in CSRF struct via Clock
* Improve InsecureSkipNonce docstring
This includes a fix for our samesite cookie parsing. The behaviour
changed in 1.16 so that the default value now leaves it empty, so it's
equivalent to not setting it (as per spec)
Reorganized the structure of the Request Utils due to their widespread use
resulting in circular imports issues (mostly because of middleware & logger).
* Allow multiple cookie domains to be specified
* Use X-Forwarded-Host, if it exists, when selecting cookie domain
* Perform cookie domain sorting in config validation phase
* Extract get domain cookies to a single function
* Update pkg/cookies/cookies.go
Co-Authored-By: Joel Speed <Joel.speed@hotmail.co.uk>
* Update changelog
Co-authored-by: Marcos Lilljedahl <marcosnils@gmail.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Values of 'lax' and 'strict' can improve and mitigate
some categories of cross-site traffic tampering.
Given that the nature of this proxy is often to proxy
private tools, this is useful to take advantage of.
See: https://www.owasp.org/index.php/SameSite