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>
Since Go 1.21 the go toolchain validates strictly the "go" version
directive in go.mod, and downloads and uses the requested toolchain if
necessary. See https://go.dev/doc/toolchain
So we can just run "go list" to tell the Go toolchain to validate our
build environment according to go.mod.
To extract the "go" directive version from go.mod (used to select the
Docker build image) we also use "go list".
* docs: clarify ingress-nginx integration and remove Lua block example for oauth2-proxy
This PR revises the integration guide for oauth2-proxy with ingress-nginx in Kubernetes:
Recommends the minimal configuration: just auth-url and auth-signin annotations.
Removes the Lua block example, as it did not work in practice despite following nginx documentation and extensive testing.
Clearly states that the official ingress-nginx external auth example is the recommended approach for most users.
Notes that advanced Lua/cookie handling is only needed for rare, advanced scenarios.
Signed-off-by: Jan Larwig <jan@larwig.com>
* doc: update 3 latest docs versions
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* fix: use GetSecret() in ticket.go makeCookie
The makeCookie method in ticket.go was using t.options.Secret directly, which
meant cookie-secret-file was not being respected. Updated to use GetSecret()
which handles both cookie-secret and cookie-secret-file properly.
Also added test coverage for cookie-secret-file functionality.
Fixes#3224
Signed-off-by: stagswtf <142280349+stagswtf@users.noreply.github.com>
* docs: update CHANGELOG.md for cookie-secret-file fix
Signed-off-by: stagswtf <142280349+stagswtf@users.noreply.github.com>
* correct PR link and undo file formatting
Signed-off-by: stagswtf <142280349+stagswtf@users.noreply.github.com>
* fix: error wrapping
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: stagswtf <142280349+stagswtf@users.noreply.github.com>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* fix: SourceHut documentation
- Add it to sidebar and provider index
- Fix broken link
This fixes an oversight in #2359, where I had not fully understood how
the documentation works.
Signed-off-by: Conrad Hoffmann <ch@bitfehler.net>
* fix: doc build instructions in docs/README.md
---------
Signed-off-by: Conrad Hoffmann <ch@bitfehler.net>
* bugfix: Gitaa team membership
Gitea doesn't properly fill in all the fields like GitHub,
so implement a series of fallbacks.
Signed-off-by: magic_rb <magic_rb@redalder.org>
* add changelog, documentation and fix groups list
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: magic_rb <magic_rb@redalder.org>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* Add sensible logging flag to default setup for logger
* Fix default value flag for sensitive logging
* Remove sensitive logging changes
* Add Cidaas provider
* Update CHANGELOG.md
* Add required groups scope to defaults
* Fix tests
* Remove if block with protected resource
* Fix linting
* Adjust provider sorting, fixes
* Directly handle error return
Co-authored-by: Jan Larwig <jan@larwig.com>
* Use less deep nesting
Co-authored-by: Jan Larwig <jan@larwig.com>
* Directly handle returned error
Co-authored-by: Jan Larwig <jan@larwig.com>
* Pass provider options to Cidaas provider
Co-authored-by: Jan Larwig <jan@larwig.com>
* Add import for provider options
* Fix tests
* Fix linting
* Add Cidaas doc page
* Add Cidaas provider doc page to overview
* Fix link in docs
* Fix link in docs
* Add link to Cidaas
* fix provider order in docs and changelog position
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Teko012 <112829523+Teko012@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Kevin Kreitner <kevinkreitner@gmail.com>
* add new docs version 7.11.x
* update to release version v7.11.0
* add changelog entry for v7.11.0
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* feat: add feature support for cookie-secret-file
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-Authored-By: Sandy Chen <Yuxuan.Chen@morganstanley.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* Perform a regex replace of $NUM to $$NUM before running envsubst
* Perform a regex replace of $NUM to $$NUM before running envsubst
* add test case; fix linter warnings; add method documentation
Signed-off-by: Jan Larwig <jan@larwig.com>
* add changelog entry
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* feat: Allow use more possible google admin-sdk api scopes.
* reduce cognitive complexity
Signed-off-by: Bob Du <i@bobdu.cc>
* remove unnecessary else block / indentation
Signed-off-by: Jan Larwig <jan@larwig.com>
* add changelog entry
Signed-off-by: Jan Larwig <jan@larwig.com>
* slight formatting and error message rephrasing
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: Bob Du <i@bobdu.cc>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* Change Dex port in local-environment from 4190 to 5556
Port 4190 is blocked by standards-compliant browsers (e.g. Firefox), as per https://fetch.spec.whatwg.org/#port-blocking.
Port 5556 is used by Dex in its example config files: 745e1114f3/examples/config-dev.yaml (L50)
* Fix upstream in local-environment/oauth2-proxy.cfg
http://httpbin.localtest.me:8080 is only exposed to the host, not to httpbin Docker network.
Causes Bad Gateway before.
* Do not expose unauthenticated httpbin service in local-environment
This defeats the point of having oauth2-proxy.
It has already been misleading by causing the bug fixed in cafc6af48fc38f6fe4395fb0c7e2638bc84e6091.
It serves as a bad example: users might accidentally expose the service they're trying to protect in the first place.
* Remove unnecessary httpbin.localtest.me alias from local-environment
* fix: redirect on invalid cookie
* docs: update changelog
* chore: remove duplicated code
* fix: status code handling if wrong http method is used
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.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>
* upgrade to go1.24.5
dependency updates
lint fixes
chore(deps): upgrade github.com/spf13/viper to v1.20.1
Note that this upgrade also implied to upgrade github.com/mitchellh/mapstructure
(nowadays unmaintained: https://gist.github.com/mitchellh/90029601268e59a29e64e55bab1c5bdc)
to github.com/go-viper/mapstructure/v2.
fix: adapt tests to match mapstructure v2 error messages
pkg/apis/options/load_test.go: skip tests on Go 1.23
Add a compile guard for Go < 1.24 for the pkg/apis/options/load_test.go
because the LoadYAML test depends on error messages produced by
encoding/json that changed slightly (names of embedded structs are now
reported). As we updated the test for go1.24, the test now fails on
1.23, but just for a slight difference, so we disable the test there.
fix: adapt tests to match mapstructure v2 error messages
remove pre 1.24 disclaimer
add changelog entry
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-Authored-By: Olivier Mengué <dolmen@cpan.org>
* add exclusion for 'avoid meaningless package names' in .golangci.yml
* chore(dep): upgrade all dependencies
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Olivier Mengué <dolmen@cpan.org>
Co-authored-by: Jan Larwig <jan@larwig.com>
* fix for github teams
* Update github.go
* added errorhandling
* Update github.md
* refactored GitHub provider
refactored hasOrg, hasOrgAndTeams and hasTeam into hasAccess to stay within function limit
* reverted Refactoring
* refactored github.go
- joined hasOrgAndTeamAccess into checkRestrictions
* refactored github.go
- reduced number of returns of function checkRestrictions to 4
* updated GitHub provider to accept legacy team ids
* GoFmt and golangci-lint
Formatted with GoFmt and followed recommendations of GoLint
* added Tests
added Tests for checkRestrictions.
* refactored in maintainer feedback
* Removed code, documentation and tests for legacy ids
* add changelog and update docs
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* docs: clear up multiple-providers is unimplemented
Currently this configuration option is held up by #926. So users don't
assume this solution will work for them, and later find the feature is
not yet implemented -- own the shortcoming clearly.
* doc: add note about missing multi provider implementation to versioned docs
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* add new docs version 7.9.x
* update to release version v7.9.0
* doc: add changelog summary
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* fix: use federated credentials to refresh token in entra id
* fix: add some error handling
* chore: update changelog
* chore: update comments
* chore: update comments
* doc: reference entra id docs and clearer phrasing of comments
Signed-off-by: Jan Larwig <jan@larwig.com>
---------
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
* Update Go version in devcontainer
* Add option to change response mode in authorization request
* Fix option name
* Update docs and changelog
* Rename config value to underscore
* Add unit tests for added parameter
* Move change to upcoming release
* Generate alpha config
---------
Co-authored-by: Michael Cornel <michael@stieler.it>
* Update gitlab.md with correct url for creating an application
* docs: fix gitlab docs url for oauth2 integration
---------
Co-authored-by: Jan Larwig <jan@larwig.com>
* update to release version v7.8.2
* docs: release letter
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
Remove github.com/oauth2-proxy/tools/reference-gen from dependencies.
Instead we are now running it with "go run" with a version suffix.
Long version:
- github.com/oauth2-proxy/tools/reference-gen is removed from
tools/tool/go
- in pkg/apis/options/doc.go we now run reference-run with a version
suffix (go run package@version) with the version comming from go.mod.
- the "//go:generate" line is split in 2 lines (using the -command
flag) for readability
- "go mod tidy" for cleaning dependencies from go.mod, go.sum
Note: we are not upgrading reference-gen here. That will be a further
separate change.
* Microsoft Entra ID Provider
* fix typo in function name
* documentation tweaks
* documentation and comment tweak
* docs tweaks
* final tweaks
* refactor: drop flag for skipping graph groups
* update legacy / deprecated provider page and sort provider overview
* reformat
* move entra-id provider into switch (treat like every other provider
* fix test case and reformat
* fix sidebar configuration
* apply review suggestions
* add pagination for graph api
* fix: do not error when groups unable to retrieve
* doc: number of groups fix
* restore master packages
* docs: tiny docs tweak
* address review comments
* fix codegen
---------
Co-authored-by: tuunit <jan@larwig.com>
The original example only protected the root (`/`) path, leaving other routes unsecured.
* docs: add syntax highlighting for nginx config
* docs: fix headings in `configuration/integration` page
* docs: fix redirect in caddy configuraion example
* new readme structure
* add adopters file
* add microsoft sponsorship
* add reference to adopter file
* add gopher slack invite link
* slightly rephrase nightly image section
* add sponsor request for action
* better formatting for contributor wall
* add longer wait time for stale PRs and issues and allow for exemption through bug and high-priority labels
* apply review suggestion
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
---------
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
When using sockets to pass data between e.g. nginx and oauth2-proxy it's
simpler to use sockets. Systemd can even facilitate this and pass the
actual socket directly.
This also means that only the socket runs with the same group as nginx
while the service runs with DynamicUser.
Does not support TLS yet.
nginx
```
server {
location /oauth2/ {
proxy_pass http://unix:/run/oauth2-proxy/oauth2.sock;
}
```
oauth2-proxy.socket
```
[Socket]
ListenStream=%t/oauth2.sock
SocketGroup=www-data
SocketMode=0660
```
Start oauth2-proxy with the parameter `--http-address=fd:3`.
Signed-off-by: Josef Johansson <josef@oderland.se>
When listening to a unix socket there is no RemoteAddr for http.Request.
Instead of setting nil, Go sets it to '@'. Marking the IP as trusted if
RemoteAddr allows rest of the settings for parsing remote address in
headers to be applied.
Signed-off-by: Josef Johansson <josef@oderland.se>
* 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>
* Remove trailing whitespaces in contribution.md
They make the pre-commit hook "trailing-whitespace" fail.
* Correct Go version in DevContainer and Contibution guide
* Mention value seperation for plural environment variables
* Mention value seperation for plural environment variables on version 7.6.x documentation
* change phrasing for better clarification
---------
Co-authored-by: tuunit <jan@larwig.com>
A regular (non-regex) file: upstream needs to strip the prefix so that it is equivalent to "mounting" the specified directory under the configured path in the URL space, but with regex rewriting the target path is determined by the rewriteTarget.
Fixesoauth2-proxy/oauth2-proxy#2242
* docs: make clear that any access token expiry dates are ignored
* clarify why access-token expiration cannot be validated
---------
Co-authored-by: Jan Larwig <jan@larwig.com>
* feat: Replace default Go user-agent with oauth2-proxy and version
* Add to CHANGELOG
* Make userAgentTransport configurable and composable
* Use correct naming convention for DefaultHTTPClient
* Move version to own package and use named arguments
* Update version path in Makefile
* Fix import path in Makefile
* Change importpath in dist.sh
* Minor style issues
By using the context created by the test, the goroutines produced in
http.Client is actually closed when cancelled and such, not leaked.
Signed-off-by: Josef Johansson <josef86@gmail.com>
* Session aware logout, backend logout url approach
* Add CHANGELOG.md and documentation for #1876
* Proper http handling and case change for golint compliance
* Update alpha_config.md
* Fix case conformity
* Change placeholder from ${id_token} to {id_token}
As this should be specified in a URL and curly braces should be escaped as %7b and %7d, therefore using {} shouldn't be an issue
* Apply suggestions from code review
Co-authored-by: Jan Larwig <jan@larwig.com>
* Add other suggestions
* Add suggestions and move background logout to generic provider
* Changelog updated
* Update oauthproxy.go
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add comment for gosec, remove sensitive data from log
---------
Co-authored-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* chore: bump go to version 1.21
update all depedencies as well
* fix linting issues based on golang 1.20 deprecations
* cleanup go depedencies
* add custom gomega matcher for option intefaces
* revert and upgrade golangci-lint to 1.55.2
* fix lint issues for v1.55.2 of golangci-lint
* fix toml loading test
* remove second runspecs call
* update go.sum
* revert testutil package
* feature: add release automation workflows
* deactivate provenancee because of behaviour change with buildx v0.10.0
* add changelog section extraction for github release notes
* fix registry path; fix EOF
* use correct version of golangci-lint; add additional workflow step for fetching all dependencies
* added envsubstring package and added simple test cases.imple tests.
* added documentation
* added changelog entry
* added documentation to wrong file
.
* changed tests to ginkgo format
* update project to use better maintained library
* use defer to clear test variable after tests finished
* updated docs for the new package documentation and fixed bad english
* refactored function to "reduce" complexity.
* updated changelog for new version
updated readme
* minor formatting
---------
Co-authored-by: Haydn Evans <h.evans@douglas.de>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Log error details when failed loading CSRF cookie
* Add a record about this PR to CHANGELOG.md
---------
Co-authored-by: Ondrej Charvat <ondrej.charvat@yunextraffic.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Create sha256sum for tar instead of binary
* chore: Add checksum for binary
* chore: Updated changelog
---------
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add possibility to encode the state param as UrlEncodedBase64
* Update CHANGELOG.md
* Update oauthproxy.go
Co-authored-by: Jan Larwig <jan@larwig.com>
---------
Co-authored-by: Jan Larwig <jan@larwig.com>
* update go-jose dependency by switching gopkg.in/square/go-jose.v2
with github.com/go-jose/go-jose/v3
* updated `CHANGELOG.md` with entry for PR #2356
---------
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add GitHub groups (orgs/teams) support
* align code of getTeams with getOrgs to support Github Enterprise Server instances with different domain
* add documentation
* add missing import after rebase
* add nightly build and push (#2297)
* add nightly build and push
* add date based nightly build tags
* only keep single multiarch image build and push
* add changelog
* add images to internal docs static files
* add docu for nightly builds
* remove unnecessary spaces
* update nightly repository
* Issue 978: Fix Custom cookie name breaks redis for session (#1949)
* Issue 978: Fix Custom cookie name breaks redis for session (see https://github.com/oauth2-proxy/oauth2-proxy/issues/978)
* Issue 978: Fix Custom cookie name breaks redis for session (see https://github.com/oauth2-proxy/oauth2-proxy/issues/978)
* Update CHANGELOG.md
* Issue 978: Fix Custom cookie name breaks redis for session
* Issue 978: Fix Custom cookie name breaks redis for session
* Issue 978: Fix Custom cookie name breaks redis for session
* Issue 978: Fix Custom cookie name breaks redis for session
* Issue 978: Fix Custom cookie name breaks redis for session
* Issue 978: Fix Custom cookie name breaks redis for session
* Update CHANGELOG.md
---------
Co-authored-by: Nuno Borges <Nuno.Borges@ctw.bmwgroup.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Support http.AllowQuerySemicolons (#2248)
* Support http.AllowQuerySemicolons
* Docs
* Make it clear we are overriding the handler
* Update documentation for allow-query-semicolons
* Fix changelog format
* Fix formatting
---------
Co-authored-by: MickMake <github@mickmake.com>
* Add GitHub groups (orgs/teams) support
* align code of getTeams with getOrgs to support Github Enterprise Server instances with different domain
* add documentation
* fix changelog & documentation
* fix missing import
---------
Co-authored-by: Tobias Mayer <github@tobiasm.de>
Co-authored-by: Nuno Miguel Micaelo Borges <miguelborges99@gmail.com>
Co-authored-by: Nuno Borges <Nuno.Borges@ctw.bmwgroup.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Tim White <tim.white@su.org.au>
Co-authored-by: MickMake <github@mickmake.com>
* add full support for all oidc config based providers to use and respect all configs set via OIDCConfig
* add changelog entry
---------
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Support http.AllowQuerySemicolons
* Docs
* Make it clear we are overriding the handler
* Update documentation for allow-query-semicolons
* Fix changelog format
* Fix formatting
---------
Co-authored-by: MickMake <github@mickmake.com>
* The `X-Forwarded-Uri` was required to bypass authentication
- Fix the `skip_auth_routes` option not working in Nginx
* Add tests for allowed requests with proxied `X-Forwarded-Uri` header
* Avoid nginx startup failure: host not found in upstream "oauth2-proxy"
* The `--reverse-proxy` option is required for nginx
* Update the change logs
* Use the authOnlyPath constant
* Remove the unused header `X-Scheme`
* add azure china support
Signed-off-by: Markus Blaschke <mblaschke82@gmail.com>
* update changelog
Signed-off-by: Markus Blaschke <mblaschke82@gmail.com>
* fix lint
Signed-off-by: Markus Blaschke <mblaschke82@gmail.com>
---------
Signed-off-by: Markus Blaschke <mblaschke82@gmail.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Added a checkbox for tested changes to PR template
* Update PULL_REQUEST_TEMPLATE.md
* Update .github/PULL_REQUEST_TEMPLATE.md
Co-authored-by: Jan Larwig <jan@larwig.com>
---------
Co-authored-by: Jan Larwig <jan@larwig.com>
* Add support for unix socket as upstream
* Add CHANGELOG.md entry
* Add Unix socket documentation
* Don't export unixRoundTripper, switch from string prefix to Scheme match
* Add basic unix server mock
* Add some tests and comments
* adding append option for custom CA certs
* updated test for changed GetCertPool signature, added testing to check functionality of empty and non-empty store
* adding legacy options as well
* update associated documentation
* fixing code climate complaints - reduce number of return statements
* Apply suggestions from code review
Changes caFilesAppend (and variants) to useSystemTrustStore
Co-authored-by: Jan Larwig <jan@larwig.com>
* Apply suggestions from code review
Fixes extra whitespaces and grammar.
Co-authored-by: Koen van Zuijlen <8818390+kvanzuijlen@users.noreply.github.com>
* fix indentation
* update changelog
---------
Co-authored-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Koen van Zuijlen <8818390+kvanzuijlen@users.noreply.github.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Update changelog for v7.5.1 release
* Create versioned docs for release v7.5.x
Created using: yarn run docusaurus docs:version 7.5.x
---------
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Embedding css and webfont dependencies allows the application to present
itself correctly in an environment that does not allow downloading the
files from a cdn.
Inspiration taken from #1492 but reworked to make use of embed.FS
simplifying the approach.
* Validate jsonpath in claim extractor
Signed-off-by: Joseph Weigl <joseph.weigl@audi.de>
* Add test and changelog for claim extractor json path
---------
Signed-off-by: Joseph Weigl <joseph.weigl@audi.de>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
the functions `isApiPath` and `isAllowedPath` use the `req.URL.Path` property which leads to faulty behavior when behind a reverse proxy. The correct path can be inferred from the `X-Forwarded-Uri` header by making use of the already provided `requestutil.GetRequestURI` function.
Co-authored-by: Jan Wystub <jan@bam-bam-bam.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>
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
* Issue 2016: CVE-2022-41717: DoS in Go net/http may lead to DoS
---------
Co-authored-by: Nuno Borges <Nuno.Borges@ctw.bmwgroup.com>
* Log the difference between invalid email and not authorized session
* Add changelog entry
* Remove superfluous argument
---------
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Added documentation for the keycloak-oidc provider in regard to the new Keycloak admin console "Admin2". As of v19.0.0 it is the default web console and OAuth2 proxy documentation has been updated to show end-users how to create a sample test Keycloak OIDC client to integrate with Oauth2 Proxy.
* Issue #1931
Added documentation for the keycloak-oidc provider in regard to the new Keycloak admin console "Admin2". As of v19.0.0 it is the default web console and OAuth2 proxy documentation has been updated to show end-users how to create a sample test Keycloak OIDC client to integrate with Oauth2 Proxy.
Added a link in the documentation to older keycloak-oidc pull request, as the provider currently evaluates aud from the access token and not the id token.
---------
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Ensure sign-in page background is uniform throughout the page
Configured banners that take up large amounts of space leave a gap of blank
background between where the body ends and the footer starts. Fix this by
setting the style for the section containing the banner to match the body and
footer
* Add changelog entry
---------
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Issue 1929: Oauth2-proxy v7.4.0 is not using alpine:3.16 as it is written in code & updates versions due to fixed CVEs
* Issue 1929: Oauth2-proxy v7.4.0 is not using alpine:3.16 as it is written in code & updates versions due to fixed CVEs
* Fixes CVE-2022-41721 (#1994)
See: https://avd.aquasec.com/nvd/2022/cve-2022-41717/
* update checkout actions (#1981)
* Fix a typo in oauthproxy.go (#2021)
* fix typo (#2001)
* Issue 1929: Oauth2-proxy v7.4.0 is not using alpine:3.16 as it is written in code & updates versions due to fixed CVEs
* Issue 1929: Oauth2-proxy v7.4.0 is not using alpine:3.16 as it is written in code & updates versions due to fixed CVEs
* Issue 1929: Oauth2-proxy v7.4.0 is not using alpine:3.16 as it is written in code & updates versions due to fixed CVEs
* Issue 1929: Oauth2-proxy v7.4.0 is not using alpine:3.16 as it is written in code & updates versions due to fixed CVEs
* Issue 1929: Oauth2-proxy v7.4.0 is not using alpine:3.16 as it is written in code & updates versions due to fixed CVEs
* Issue 1929: Oauth2-proxy v7.4.0 is not using alpine:3.16 as it is written in code & updates versions due to fixed CVEs
* Issue 1929: Oauth2-proxy v7.4.0 is not using alpine:3.16 as it is written in code & updates versions due to fixed CVEs
---------
Co-authored-by: Nuno Borges <Nuno.Borges@ctw.bmwgroup.com>
Co-authored-by: Jeroen Landheer <jlandheer@bintelligence.nl>
Co-authored-by: Ryuichi Watanabe <ryucrosskey@gmail.com>
Co-authored-by: Ho Kim <ho.kim@ulagbulag.io>
Co-authored-by: Terrell Russell <terrellrussell@gmail.com>
* feat: readiness check
* fix: no need for query param
* docs: add a note
* chore: move the readyness check to its own endpoint
* docs(cr): add godoc
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Fix uninitialized user claim
Some providers doesn't initialize data with setProviderDefaults function
(keycloak-oidc for example), therefore UserClaim is never initialized
with the default value and stay as an empty string.
This result in an empty user.
* Add CHANGELOG.md entry for #1873
* Call setProviderDefaults where missing
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Update go-redis/redis to v9.
- And updated redislock, testify, ginko and gomega have also been updated.
- Renamed the option `IdleTimeout` to `ConnMaxIdleTime` because of 517938a6b0/CHANGELOG.md
* Update CHANGELOG.md
* Dropping dot import of the types since they created aliases now
* fixing some error messages to make tests happy
* updating more error messages that were changed to make tests happy
* reverting error messages
Co-authored-by: Muhammad Arham <marham@i2cinc.com>
* initial commit: add groups to azure
Signed-off-by: andrewphamade@gmail.com <andrewphamade@gmail.com>
* fix deprecations and linting errors
Signed-off-by: Andrew Hamade <andrewphamade@gmail.com>
* remove groups testing from azure provider
Signed-off-by: Andrew Hamade <andrewphamade@gmail.com>
* fix test error
Signed-off-by: Andrew Hamade <andrewphamade@gmail.com>
* verify-generate
Signed-off-by: Andrew Hamade <andrewphamade@gmail.com>
Signed-off-by: andrewphamade@gmail.com <andrewphamade@gmail.com>
Signed-off-by: Andrew Hamade <andrewphamade@gmail.com>
* Avoid Nextcloud "Current user is not logged in" (Statuscode 997)
The error message results from oauth2-proxy trying to pass the
access token via URL. Instead it needs to be sent via header,
thus the Nextcloud provider requires a fix similar to what #1502
did before for the keycloak provider.
* Implement EnrichSession() for Nextcloud provider
Parse nested JSON to transform relevant information (groups, id,
email) from the OAuth2 userinfo endpoint into session.
* Update CHANGELOG.md (add link to PR #1750)
* Add API route config
In addition to requests with Accept header `application/json` return 401 instead of 302 to login page on requests matching API paths regex.
* Update changelog
* Refactor
* Remove unnecessary comment
* Reorder checks
* Lint Api -> API
Co-authored-by: Sebastian Halder <sebastian.halder@boehringer-ingelheim.com>
* dynamically update the htpasswdMap based on the changes made to the htpasswd file
* added tests to validate that htpasswdMap is updated after the htpasswd file is changed
* refactored `htpasswd` and `watcher` to lower cognitive complexity
* returned errors and refactored tests
* added `CHANGELOG.md` entry for #1701 and fixed the codeclimate issue
* Apply suggestions from code review
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Fix lint issue from code suggestion
* Wrap htpasswd load and watch errors with context
* add the htpasswd wrapped error context to the test
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Inconsistent code-challenge-method CLI flag and config file naming
- Allow previous config option for now to prevent breaking configs
Fixes#1667
* Add changelog entry
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
The Azure AD Doc mentioned a very broad and risky permission, which is not really required by the proxy, and some Admins won't even permit.
This change recommends using the much more restricted "openid", and also warns about the consent that could still be required in certain cases.
* docs/conf/overview: Add hint about cookie prefixes to --cookie-name
Cookie Prefixes further restricts the possibilities of session attacks because supporting clients will only accept cookies with one of the prefix if certain requirements were meet, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#cookie_prefixes
* Backport cookie prefixes to older docs
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Fix vulnerabilities on crypto, net and sys packages and change go version on Docker builder stage
* Changelog related PR $1774
Co-authored-by: Felipe Bonvicini Conti <felipe.conti@totvs.com.br>
* adding IdleTimeout with the redis-connection-idle-timeout flag, to keep redis connections in valid state, when Redis option is set
* docs update - add redis idle timeout configurations
* changelog update for #1691 fix
* Unbreak oauth2-proxy for keycloak provider after 2c668a
With 2c668a, oauth2-proxy fails a request if the token validation fails.
Token validation always fails with the keycloak provider, due to the
valudation request passing the token via the URL, and keycloak not
parsing the url for tokens.
This is fixed by forcing the validation request to pass the token via a
header.
This code taken from the DigitalOcean provider, which presumably forcing
the token to be passed via header for the same reason.
Test plan: I was unable to build a docker image to test the fix, but I
believe it is relatively simple, and it passes the "looks good to me"
test plan.
* Add changelog entry for unbreak keycloak
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
The correct URL for the oidc-issuer-url in KeyCloak v18.0 is: https://<keycloak host>/realms/<your realm>.
Using the old URL causes oauth2-proxy to crash on startup.
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add redirect instructions for gitlab on sub-dir
* include redirect instructions in unversioned docs
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Change error type for redirect parsing errors
This changes the error type returned when the proxy fails to parse the
redirect target to be a 400 error instead of a 500 error.
As far as I can tell, the only way that this can fail is a failure to
parse the properties of the request to identity the redirect target.
This indicates that the user has sent a malformed request, and so should
result in a 400 rather than a 500.
I've added a test to exercise this, based on a real work example.
* Update changelog
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add allowed_emails option to the auth endpoint query string
* Don't return true from checkAllowedEmailsOrDomains only because domains field was empty
* Fix checkAllowedEmailsOrDomains logic
* Added tests for allowed_emails query parameter
* Updated CHANGELOG
* Remove checkAllowedEmailsOrDomains
Co-authored-by: Nick Meves <nicholas.meves@gmail.com>
* Build ARMv8 Docker Images
Fixes#1593
* Change platform to arm64/v8
* Drop separate tags for different architectures
* Mark the architecture image tags for deprecation
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Use distroless debian11 docker image
* Add `Dockerfile` to `.dockerignore`
* Replace `nonroot` with the matching UID/GID
Alpine does not have that user, and it cause issues when trying to start the container
* Use a build arg for setting the runtime image
* Explain why `ARG RUNTIME_IMAGE` is at the top
* Add entry to CHANGELOG
* Move build-arg to `DOCKER_BUILDX_ARGS`
* 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>
Filtering `/dev/urandom` for alphanumeric characters resulted in loss of
input entropy to base64. Fixing this using a procedure with these steps:
* Read 32 bytes from `/dev/urandom` (`dd`)
* Base64-encode (`base64`)
* Strip newlines (`tr -d`)
* URL-Escape (`tr`)
* Append a final newline (`echo`)
This output should be equivalent to output generated using Python and
OpenSSL variants mentioned in the changed document file.
Newlines are stripped as `base64` wraps its output and the option to
disable this (`-w 0`) is not available in all implementations.
Fixes: #1511
You must explicitly configure oauth2-proxy (alpha config only) with which parameters are allowed to pass through, and optionally provide an allow-list of valid values and/or regular expressions for each one. Note that this mechanism subsumes the functionality of the "prompt", "approval_prompt" and "acr_values" legacy configuration options, which must be converted to the equivalent YAML when running in alpha config mode.
* implementation draft
* add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options
* refactor configs, added logging and add additional claim verification
* simplify logic by just having one configuration similar to oidc-email-claim
* added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers
* refactored verification to reduce complexity
* refactored verification to reduce complexity
* added docs
* adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options
* extend unit tests and ensure that audience is set with the value of aud claim configuration
* revert filemodes and update docs
* update docs
* remove unneccesary logging, refactor audience existence check and added additional unit tests
* fix linting issues after rebase on origin/main
* cleanup: use new imports for migrated libraries after rebase on origin/main
* adapt mock in keycloak_oidc_test.go
* allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation
* fixed formatting issue
* do not pass the whole options struct to minimize complexity and dependency to the configuration structure
* added changelog entry
* update docs
Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com>
Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
* Add ValidateSession function to LoginGovProvder to include Auth Header
* Update CHANGELOG for PR 1509
* Update logingov_test to include ValidationURL
* Remove the information about `Microsoft Azure AD`
* Put `proxy_buffer_size` in a code tag
* Update `CHANGELOG.md`
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
I was recently looking into the order in which oauth2-proxy evaluates it configuration options from the various sources.
I think this will also be helpful for other users.
Since oauth2-proxy is using viper, the order of configuration sources is as follows [1]:
> Viper uses the following precedence order. Each item takes precedence over the item below it:
>
> explicit call to Set
> flag
> env
> config
> key/value store
> default
[1] https://github.com/spf13/viper/blob/master/README.md#why-viper
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* init TLS.Config when connecting to Redis with TLS
* don't overwrite TLS config if it exists
* add tests for Redis with TLS
* remove hardcoded certs
* add GenerateCert func
* use GenerateCert util func
* fix issue reported by go fmt
* limit return statements in GenerateCert
* Use the httputil.NewSingleHostReverseProxy instad of yhat/wsutil for websocket proxying. This correctly handles 404 responses with keep-alive by terminating the tunnel rather than keeping it alive
* Tidy up dependencies - yhat/wsutil is no longer required
* Update changelog to include reference to 1348
Co-authored-by: Matt Lilley <matt.lilley@securitease.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
This change puts the groups from the htpasswd-user-group in the
session during the manual sign in process. This fixes the issue
with being unable to properly authenticate using the manual
sign in form when certain group membership is required (e.g. when
the --gitlab-group option is used).
The groups configured in the `htpasswd-user-group` are not
stored in the session, resulting in unauthorized errors when
group membership is required. Please see:
https://gist.github.com/janrotter/b3d806a59292f07fe83bc52c061226e0
for instructions on reproducing the issue.
RefreshSession will override session.Groups with the new
`groups` claims. We need to preserve all `project:` prefixed
groups and reattach them post refresh.
Previously this was only done in the `EnrichSession` stage
which would've missed Bearer usages & `RefreshSession`
would've overriden the User to the Subject.
* extract email from id_token for azure provider (#914)
* extract email from id_token for azure provider
this change fixes a bug when --resource is specified with non-Graph
api and the access token destined to --resource is used to call Graph
api
* fixed typo
* refactor GetEmailAddress to EnrichSessionState
* make getting email from idtoken best effort and fall back to previous behavior when it's absent
* refactor to use jwt package to extract claims
* fix lint
* refactor unit tests to use test table
refactor the get email logic from profile api
* addressing feedback
* added oidc verifier to azure provider and extract email from id_token if present
* fix lint and codeclimate
* refactor to use oidc verifier to verify id_token if oidc is configured
* fixed UT
* addressed comments
* minor refactor
* addressed feedback
* extract email from id_token first and fallback to access token
* fallback to access token as well when id_token doesn't have email claim
* address feedbacks
* updated change log!
* switch to docker buildx for multiarch builds
* add setup docker buildx action
* update docker push to push the multiarch image
* make multiarch image have parity with currently produced images by adding linux/armv6
* triaging issue with arm v6
* incorporating feedback
* fixing rebase disaster
* reset Makefile to blessed state
Co-authored-by: Weinong Wang <weinong@outlook.com>
Adding a new option to the yaml alpha config will result in failed tests
unless you manually increment the line count. This commit computes this
dynamically.
This allows urls with encoded characters (e.g.: /%2F/) to pass to the
upstream mux instead of triggering a HTTP 301 from the frontend.
Otherwise a /%2F/test/ will result in a HTTP 301 -> /test/
* switched to github.com/golang-jwt/jwt and updated golang.org/x/crypto to include CVE fixes
* added #1276 to changelog
Co-authored-by: Joshua Vécsei <git@vecsei.me>
* Extend email-domain validation with sub-domain capability
* Adding the CHANGELOG entry
* Fixing lint erros
* Fixing lint erros
* Renamed the emailDomains to allowedDomains, plus tests
* Bringing together all basic test-cases
* Fixing unit tests
* Add unit tests to validate additional vulnerability concerns
They will only be used in tests, but it doesn't play
nice with copy operations many tests use. The linter was
not happy. While the global clock needs mutexes for parallelism,
local Clocks only used it for Set/Add and didn't even use the
mutex for actual time functions.
The reflect.DeepCopy doesn't play nice with the new Lock and Clock
fields in sessions. And it added unneeded session deserialization
logic to every request.
The previous code didn't consider other languages and hid the output of failures. For example
```
$ LANG=es_ES.UTF-8 sha256sum -c sha256sum.txt
oauth2-proxy-v7.1.3.linux-amd64/oauth2-proxy: La suma coincide
```
* Fix - Refresh Session not working for multiple cookies (#1209)
* added comments for flattenheaders fix
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Updated Changelog.md
Co-authored-by: Rishi Kambil <rishi.kambil@lntinfotech.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add sensible logging flag to default setup for logger
* Add Redis lock
* Fix default value flag for sensitive logging
* Split RefreshSessionIfNeeded in two methods and use Redis lock
* Small adjustments to doc and code
* Remove sensible logging
* Fix method names in ticket.go
* Revert "Fix method names in ticket.go"
This reverts commit 408ba1a1a5.
* Fix methods name in ticket.go
* Remove block in Redis client get
* Increase lock time to 1 second
* Perform retries, if session store is locked
* Reverse if condition, because it should return if session does not have to be refreshed
* Update go.sum
* Update MockStore
* Return error if loading session fails
* Fix and update tests
* Change validSession to session in docs and strings
* Change validSession to session in docs and strings
* Fix docs
* Fix wrong field name
* Fix linting
* Fix imports for linting
* Revert changes except from locking functionality
* Add lock feature on session state
* Update from master
* Remove errors package, because it is not used
* Only pass context instead of request to lock
* Use lock key
* By default use NoOpLock
* Remove debug output
* Update ticket_test.go
* Map internal error to sessions error
* Add ErrLockNotObtained
* Enable lock peek for all redis clients
* Use lock key prefix consistent
* Fix imports
* Use exists method for peek lock
* Fix imports
* Fix imports
* Fix imports
* Remove own Dockerfile
* Fix imports
* Fix tests for ticket and session store
* Fix session store test
* Update pkg/apis/sessions/interfaces.go
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Do not wrap lock method
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Use errors package for lock constants
* Use better naming for initLock function
* Add comments
* Add session store lock test
* Fix tests
* Fix tests
* Fix tests
* Fix tests
* Add cookies after saving session
* Add mock lock
* Fix imports for mock_lock.go
* Store mock lock for key
* Apply elapsed time on mock lock
* Check if lock is initially applied
* Reuse existing lock
* Test all lock methods
* Update CHANGELOG.md
* Use redis client methods in redis.lock for release an refresh
* Use lock key suffix instead of prefix for lock key
* Add comments for Lock interface
* Update comment for Lock interface
* Update CHANGELOG.md
* Change LockSuffix to const
* Check lock on already loaded session
* Use global var for loadedSession in lock tests
* Use lock instance for refreshing and releasing of lock
* Update possible error type for Refresh
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
* Add a clock package for better time mocking
* Make Clock a struct so it doesn't need initialization
* Test clock package
* Use atomic for live time tests
* Refer to same clock.Mock throughout methods
* Initial commit of multiple provider logic:
1. Created new provider options.
2. Created legacy provider options and conversion options.
3. Added Providers to alpha Options.
4. Started Validation migration of multiple providers
5. Tests.
* fixed lint issues
* additional lint fixes
* Nits and alterations based on CR: manliy splitting large providers validation function and adding comments to provider options
* fixed typo
* removed weird : file
* small CR changes
* Removed GoogleGroups validation due to new allowed-groups (including tests). Added line in CHANGELOG
* Update pkg/apis/options/providers.go
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Update pkg/apis/options/providers.go
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Update pkg/apis/options/providers.go
Co-authored-by: Nick Meves <nick.meves@greenhouse.io>
* Initial commit of multiple provider logic:
1. Created new provider options.
2. Created legacy provider options and conversion options.
3. Added Providers to alpha Options.
4. Started Validation migration of multiple providers
5. Tests.
* fixed lint issues
* additional lint fixes
* Nits and alterations based on CR: manliy splitting large providers validation function and adding comments to provider options
* small CR changes
* auto generates alpha_config.md
* rebase (mainly service alpha options related conflicts)
* removed :
* Nits and alterations based on CR: manliy splitting large providers validation function and adding comments to provider options
* small CR changes
* Removed GoogleGroups validation due to new allowed-groups (including tests). Added line in CHANGELOG
* "cntd. rebase"
* ran make generate again
* last conflicts
* removed duplicate client id validation
* 1. Removed provider prefixes
2. altered optionsWithNilProvider logic
3. altered default provider logic
4. moved change in CHANELOG to 7.0.0
* fixed TestGoogleGroupOptions test
* ran make generate
* moved CHANGLOG line to 7.1.1
* moved changelog comment to 7.1.2 (additional rebase)
Co-authored-by: Yana Segal <yana.segal@nielsen.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Nick Meves <nick.meves@greenhouse.io>
"go mod download" does not depend on the VERSION env var, so moving the ARG directive after the RUN will allow better use of the Docker build cache - subsequent builds on the same machine need only re-run the "go mod download" if go.mod or go.sum has changed, rather than re-running it any time the VERSION value passed from the Makefile has changed
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* panic with GitLab project repository auth
* /api/v4/projects/:id can return nil permissions
Signed-off-by: Piers Harding <piers@ompka.net>
* Add GitLab test for group no access
Signed-off-by: Piers Harding <piers@ompka.net>
* Add example with traefik and keycloak
* Switch to dex
* Remove unneeded change in keycloak settings
* Taken into account review comments
* Add changelog entry
Co-authored-by: Frédéric Collonval <frederic.collonval@ariadnext.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add RequestID to the RequestScope
* Expose RequestID to auth & request loggers
* Use the RequestID in templated HTML pages
* Allow customizing the RequestID header
* Document new Request ID support
* Add more cases to scope/requestID tests
* Split Get vs Generate RequestID funtionality
* Add {{.RequestID}} to the request logger tests
* Move RequestID management to RequestScope
* Use HTML escape instead of sanitization for Request ID rendering
* extract email from id_token for azure provider
this change fixes a bug when --resource is specified with non-Graph
api and the access token destined to --resource is used to call Graph
api
* fixed typo
* refactor GetEmailAddress to EnrichSessionState
* make getting email from idtoken best effort and fall back to previous behavior when it's absent
* refactor to use jwt package to extract claims
* fix lint
* refactor unit tests to use test table
refactor the get email logic from profile api
* addressing feedback
* added oidc verifier to azure provider and extract email from id_token if present
* fix lint and codeclimate
* refactor to use oidc verifier to verify id_token if oidc is configured
* fixed UT
* addressed comments
* minor refactor
* addressed feedback
* extract email from id_token first and fallback to access token
* fallback to access token as well when id_token doesn't have email claim
* address feedbacks
* updated change log!
* Use a specialized ResponseWriter in middleware
* Track User & Upstream in RequestScope
* Wrap responses in our custom ResponseWriter
* Add tests for logging middleware
* Inject upstream metadata into request scope
* Use custom ResponseWriter only in logging middleware
* Assume RequestScope is never nil
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)
* GH-1015 Adds support for Traefik to OauthStart on '/oauth2/auth' endpoint
* Fix incorrect reference to signout path and point to signin path
- remove commented out alternative solutions and debug log statements
* Remove skip provider button check as SignIn method already does this
* Updated traefik example to match existing file configuration reference, updated tests
* Update doc and refactor nested conditional statements
* Revert code changes as static upstream provides the same functionality
- Add doc on using static upstream with Traefik ForwardAuth middleware
* update changelog
* Move the doc changes to 7.0.x versioned docs
* Re-add traefik docs update in the main docs overview.md
* add missing oauth2-proxy routing
Co-authored-by: Praveen Chinthala <PraveenChinthala@hollandandbarrett.com>
Add the Prometheus http.Handler to serve metrics at MetricsPath ("/metrics"
by default). This allows Prometheus to scrape metrics from OAuth2 Proxy.
Add a new middleware NewRequestMetrics and attach it to the preAuth
chain. This will collect metrics on all requests made to OAuth2 Proxy
Collapse some calls to Prinf() and os.Exit(1) to Fatalf as they are
equivalent. main() has a strict 50 lines limit so brevity in these
calls appreciated
* Use comma separated value for multiple claims
* Fix lint error
* Fix more tests
* Fix one more test
* Always flatten the headers
* Ensure we test the real multi-groups
* Only update map when necessary
* Update CHANGELOG
* Move to the right location of change log
* Fix blank line
* Add sensible logging flag to default setup for logger
* Use logger instead of fmt for info logging with sensible data
* Remove sensible logging flag
* Update CHANGELOG.md
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Reorganized the structure of the Request Utils due to their widespread use
resulting in circular imports issues (mostly because of middleware & logger).
* properly handle splitted cookies with names ending with _
* test update
* provide cookieName into joinCookies instead of processing the suffix
* changelog update
* test update
* Fix and enhance OIDC example
* Restructure
* Indent
* Add full stop.
* Add link
* Add minimalistic README
* Apply suggestions from code review
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add support for gitlab projets
* Add group membership in state
* Use prefixed allowed groups everywhere
* Fix: remove unused function
* Fix: rename func that add data to session
* Simplify projects and groups session funcs
* Add project access level for gitlab projects
* Fix: default access level
* Add per project access level
* Add user email when missing access level
* Fix: harmonize errors
* Update docs and flags description for gitlab project
* Add test with both projects and groups
* Fix: log error message
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Fix: make doc a markdown link
* Add notes about read_api scope for projects
* Fix: Verifier override in Gitlab Provider
This commit fixes a bug caused by an override of the Verifier value from *ProviderData inside GitlabProvider struct
* Fix: ensure data in session before using it
* Update providers/gitlab.go
Co-authored-by: Nick Meves <nick.meves@greenhouse.io>
* Rename gitlab project initializer
* Improve return value readbility
* Use splitN
* Handle space delimiters in set project scope
* Reword comment for AddProjects
* Fix: typo
* Rework error handling in addProjectsToSession
* Reduce branching complexity in addProjectsToSession
* Fix: line returns
* Better comment for addProjectsToSession
* Fix: enrich session comment
* Fix: email domains is handled before provider mechanism
* Add archived project unit test
* Fix: emails handling in gitlab provider
Co-authored-by: Wilfried OLLIVIER <wollivier@bearstech.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Nick Meves <nick.meves@greenhouse.io>
The existing URL no longer works. This commit updates the Chart
dependencies to use the new Stable chart URL.
This will fix the "Chart not found" errors that occur if these example
resources are used.
Please keep in mind this is only a bandaid, as the repository is still
EOL, and should not be used.
* Support TLS 1.3
* Set TLS 1.3 explicitly to fix gosec warning.
* Add an entry to changelog.
* Fix typo in the changelog.
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Implement azure token refresh
Based on original PR https://github.com/oauth2-proxy/oauth2-proxy/pull/278
* Update CHANGELOG.md
* Apply suggestions from code review
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Set CreatedAt to Now() on token refresh
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Allow complex structure for groups in group claim.
* Remove unused constant
* Update variable name
* Fix linting
* Use helper method
* Log error if not possible to append group value
* Add missing import
* Use own logger
* Fix imports
* Remove Dockerfile for testing
* Add Changelog entry
* Use formatGroup helper method and update tests
* Return string instead of string array
* Remove groups variable
* Return error in format method.
* Reorder imports
Co-authored-by: Nick Meves <nick.meves@greenhouse.io>
* Document set_xauthrequest with pass_access_token
Document feature implemented in https://github.com/oauth2-proxy/oauth2-proxy/pull/68
The feature is already decribed in in the nginx example but not clearly
on each respective parameters documentation.
* Update docs/configuration/configuration.md
Co-authored-by: Nick Meves <nick.meves@greenhouse.io>
Co-authored-by: Nick Meves <nick.meves@greenhouse.io>
* simplify github actions workflow
no more GOPATH, update Go to 1.15.x
* add script to install golangci-lint
* drop support for Go 1.14
* check docker build in ci
* update alpine linux to 3.12
* update CHANGELOG
* fix golangci-lint installation
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* update go-redis/redis to v8
testify, ginko and gomega have also been updated.
* update changelog
* Update pkg/sessions/redis/redis_store_test.go
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Home: Add a brief description of the behavior
I could not find this information anywhere and think it is quite important for understanding how to use and configure the proxy for different use cases.
(Especially the Ajax part is not mentioned anywhere else I believe.)
I tried to keep it general enough so that it won't need updating often yet useful enough to have good value :)
* Update docs/0_index.md
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* ci: migrate to Github Actions
* ci: optimize on feedback
* ci: run gocov in correct dir
* ci: running after-build script always
* ci: giving test script execute permission
* ci: correct error handling on test script
* ci: more verbose test script
* ci: configure CC_TEST_REPORTER_ID env
* ci: check existence of CC_TEST_REPORT_ID variable, skip if unset
* ci: check existence of CC_TEST_REPORT_ID variable, skip if unset
* update changelog
* Update CHANGELOG.md
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
It isn't used in any providers and we have future plans
to remove the specialness of PreferredUsername and make it
an optional field in the session.
User, Email & Groups will eventually be the only first class
fields on the session that are always set.
`findClaimsFromIDToken` would always have a `nil` access token and not be
able to hit the userinfo endpoint in Bearer case. If access token is nil,
default to legacy `session.Email = claim.Subject` that all JWT bearers used
to have, even if a valid profileURL is present.
This reverts to functionality before #499 where an OIDC
provider could be used with `--skip-jwt-bearer-tokens` and
tokens without an email or profileURL would still be valid.
This logic mirrors `middleware.createSessionStateFromBearerToken`
which used to be the universal logic before #499.
* Centralize Ticket management of persistent stores
persistence package with Manager & Ticket will handle
all the details about keys, secrets, ticket into cookies,
etc. Persistent stores just need to pass Save, Load &
Clear function handles to the persistent manager now.
* Shift to persistence.Manager wrapping a persistence.Store
* Break up the Redis client builder logic
* Move error messages to Store from Manager
* Convert ticket to private for Manager use only
* Add persistence Manager & ticket tests
* Make a custom MockStore that handles time FastForwards
* Strip X-Forwarded auth headers from whitelisted paths
For any paths that match skip-auth-regex, strip normal
X-Forwarded headers that would be sent based on pass-user-headers
or pass-access-token settings. This prevents malicious injecting
of authentication headers through the skip-auth-regex paths in
cases where the regex might be misconfigured and too open.
Control this behavior with --skip-auth-strip-headers flag. This
flag is set to TRUE by default (this is secure by default, but
potentially breaks some legacy configurations).
Only x-Forwarded headers stripped, left the Authorization header
untouched.
* Strip authorization header if it would be set
* Improve TestStripAuthHeaders test table
* Improve --skip-auth-strip-headers flag documentation
* Encode sessions with MsgPack + LZ4
Assumes ciphers are now mandatory per #414. Cookie & Redis sessions
can fallback to V5 style JSON in error cases. TODO: session_state.go
unit tests & new unit tests for Legacy fallback scenarios.
* Only compress encoded sessions with Cookie Store
* Cleanup msgpack + lz4 error handling
* Change NewBase64Cipher to take in an existing Cipher
* Add msgpack & lz4 session state tests
* Add required options for oauthproxy tests
More aggressively assert.NoError on all
validation.Validate(opts) calls to enforce legal
options in all our tests.
Add additional NoError checks wherever error return
values were ignored.
* Remove support for uncompressed session state fields
* Improve error verbosity & add session state tests
* Ensure all marshalled sessions are valid
Invalid CFB decryptions can result in garbage data
that 1/100 times might cause message pack unmarshal
to not fail and instead return an empty session.
This adds more rigor to make sure legacy sessions
cause appropriate errors.
* Add tests for legacy V5 session decoding
Refactor common legacy JSON test cases to a
legacy helpers area under session store tests.
* Make ValidateSession a struct method & add CHANGELOG entry
* Improve SessionState error & comments verbosity
* Move legacy session test helpers to sessions pkg
Placing these helpers under the sessions pkg removed
all the circular import uses in housing it under the
session store area.
* Improve SignatureAuthenticator test helper formatting
* Make redis.legacyV5DecodeSession internal
* Make LegacyV5TestCase test table public for linter
* Implements --ip-whitelist option
* Included IPWhitelist option to allow one-or-more selected CIDR ranges
to bypass OAuth2 authentication.
* Adds IPWhitelist, a fast lookup table for multiple CIDR ranges.
* Renamed IPWhitelist ipCIDRSet
* Fixed unessesary pointer usage in ipCIDRSet
* Update CHANGELOG.md
* Update CHANGELOG.md
* Updated to not use err.Error() in printf statements
* Imrpoved language for --ip-whitelist descriptions.
* Improve IP whitelist options error messages
* Clarify options single-host normalization
* Wrote a book about ipCIDRSet
* Added comment to IsWhitelistedIP in oauthproxy.go
* Rewrite oauthproxy test case as table driven
* oops
* Support whitelisting by low-level remote address
* Added more test-cases, improved descriptions
* Move ip_cidr_set.go to pkg/ip/net_set.go
* Add more whitelist test use cases.
* Oops
* Use subtests for TestIPWhitelist
* Add minimal tests for ip.NetSet
* Use switch statment
* Renamed ip-whitelist to whitelist-ip
* Update documentation with a warning.
* Update pkg/apis/options/options.go
* Update CHANGELOG.md
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Update pkg/ip/net_set_test.go
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Update pkg/ip/net_set_test.go
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Update pkg/ip/net_set_test.go
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Apply suggestions from code review
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* fix fmt
* Move ParseIPNet into abstraction
* Add warning in case of --reverse-proxy
* Update pkg/validation/options_test.go
* Rename --whitelist-ip to --trusted-ip
* Update oauthproxy.go
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* fix
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add req.host to targetURL when redirecting to https
The req.URL.Host might not be present when redirecting to https if the
given req.URL is something like "/". In such scenario, the req.Host is
still present and valid.
This commit adds the original req.Host to the targetURL before returning
the 308 status, to avoid having a `Location: https:///` in the response.
* Bring back empty line
* Wrap the setting of targetURL.Host in a condition
* Add a comment to the test explaining why the redirectURL includes example.com
* Add changelog entry
A blank user agent is considered == to an empty string. When no -ping-user-agent option is specified, this is considered to be an empty string.
This reveals two problems:
- When no ping-user-agent is specified, main.go sets up a health check user agent of ""
- When no user agent is specified, the empty string is still checked against the health check user agents.
Now the health check middleware ignores blank user agents and paths in order to sanitise it's input to avoid this issue.
Additional tests have been added to verify these situations.
This also removes the check for the decoded from the valid secret size
check. The code was unreachable because encryption.SecretBytes will only
return the decoded secret if it was the right length after decoding.
Moves the logic for redirecting to HTTPs to a middleware package and adds tests for this logic.
Also makes the functionality more useful, previously it always redirected to the HTTPS address of the proxy, which may not have been intended, now it will redirect based on if a port is provided in the URL (assume public facing 80 to 443 or 4180 to 8443 for example)
This means that we can keep the list of reviewers up to date based on team membership, rather than this file. Will make it easier to add and remove people going forward
* Changed how gitlab-group is parsed, from string to []string
See #637
* Point out that gitlab-group can be a list
See #637
* Reflect to the []string change on pkg/apis/options/options.go
See #637
* Move cfg option gitlab_group to gitlab_groups
See #637
* Renamed Group to Groups
See #637
* Reflect the change on gitlab.go as well
See #637
* Added #639
* Added the author of #639 to the CHANGELOG
* Add the gitlab_groups env change to CHANGELOG.md
See #639
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
When using the configured provider JWT Verifier, it makes
sense to use the provider `CreateSessionStateFromBearerToken`
method. For any extra JWT Issuers, they should use a generic
default verifier.
* Adding one more example - keycloak - alongside with dex IDP.
* don't expose keycloak and proxy ports to the host
* specify email-domain list option in documentation
* get rid of nginx and socat to simplify the example as per https://github.com/oauth2-proxy/oauth2-proxy/pull/604#issuecomment-640054390
* get rid of the scripts - use static file for keycloak startup
* changelog entry
* Update CHANGELOG.md
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
This helper method is only applicable for Base64 wrapped
encryption since it operated on string -> string primarily.
It wouldn't be used for pure CFB/GCM ciphers. After a messagePack
session refactor, this method would further only be used for
legacy session compatibility - making its placement in cipher.go
not ideal.
Have it take in a cipher init function as an argument.
Remove the confusing `newCipher` method that matched legacy behavior
and returns a Base64Cipher(CFBCipher) -- instead explicitly ask for
that in the uses.
During the upcoming encoded session refactor, AES GCM is ideal
to use as the Redis (and other DB like stores) encryption wrapper
around the session because each session is encrypted with a
distinct secret that is passed by the session ticket.
All Encrypt/Decrypt Cipher implementations will now take
and return []byte to set up usage in future binary compatible
encoding schemes to fix issues with bloat encrypting to strings
(which requires base64ing adding 33% size)
* Add an option to allow health checks based on User-Agent.
* Formatting fix
* Rename field and avoid unnecessary interface.
* Skip the redirect fix so it can be put into a different PR.
* Add CHANGELOG entry
* Adding a couple tests for the PingUserAgent option.
* Parse Redis cluster and sentinel urls
* Add changelog entry for #573
* Add unit tests for redis session store
* Use %v for error fmt
Co-authored-by: Amnay Mokhtari <amnay.mokhtari@adevinta.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Refactor the utils package to other areas
Move cookieSession functions to cookie session store
& align the double implementation of SecretBytes to be
united and housed under encryption
* Remove unused Provider SessionFromCookie/CookieForSession
These implementations aren't used, these are handled in the cookie store.
* Add changelog entry for session/utils refactor
* Implements -real-client-ip-header option.
* The -real-client-ip-header determines what HTTP header is used for
determining the "real client IP" of the remote client.
* The -real-client-ip-header option supports the following headers:
X-Forwarded-For X-ProxyUser-IP and X-Real-IP (default).
* Introduces new realClientIPParser interface to allow for multiple
polymorphic classes to decide how to determine the real client IP.
* TODO: implement the more standard, but more complex `Forwarded` HTTP
header.
* Corrected order of expected/actual in test cases
* Improved error message in getRemoteIP
* Add tests for getRemoteIP and getClientString
* Add comment explaining splitting of header
* Update documentation on -real-client-ip-header w/o -reverse-proxy
* Add PR number in changelog.
* Fix typo repeated word: "it"
Co-Authored-By: Joel Speed <Joel.speed@hotmail.co.uk>
* Update extended configuration language
* Simplify the language around dependance on -reverse-proxy
Co-Authored-By: Joel Speed <Joel.speed@hotmail.co.uk>
* Added completions
* Reorder real client IP header options
* Update CHANGELOG.md
* Apply suggestions from code review
Co-authored-by: Isabelle COWAN-BERGMAN <Izzette@users.noreply.github.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Henry Jenkins <henry@henryjenkins.name>
* Add basic string functions to templates
Co-authored-by: Oliver <oliver006@users.noreply.github.com>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Henry Jenkins <henry@henryjenkins.name>
* Add -user-id-claim to support other claims than email
Fix#431 - This is a minimal change to allow the user to configure which claim is
the source of the "user ID".
- Add the option `user-id-claim` (defaults to email)
- OIDC extracts this claim into session.Email (to be renamed later)
- providers: add `CreateSessionStateFromBearerToken` with a default impl taken from
`GetJwtSession` and overridden by oidc to respect `user-id-claim`
Once #466 is merged, I can continue to rename SessionState.Email to .UserID
and add HTTP headers with a corresponding name.
* Apply suggestions from code review
Co-Authored-By: Joel Speed <Joel.speed@hotmail.co.uk>
* Review feedback: Don't extract claims manually
Instead, parse them twice - it might be sligtly slower but less bug-prone as the code evolves.
* Fix indentation
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Allow the OIDC issuer verification to be skipped if desired.
* Remove stale warning
* Add CHANGELOG entry
Co-authored-by: Henry Jenkins <henry@henryjenkins.name>
Co-authored-by: Dan Bond <pm@danbond.io>
* 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>
* feature: switch Azure AD graph API to Microsoft Graph API
* Update CHANGELOG
* Expand Breaking Changes notice
* Update CHANGELOG.md
Co-Authored-By: Joel Speed <Joel.speed@hotmail.co.uk>
* fix: use constant http method
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* addint redirect capability to sign_out
* updating changelog
* Add a new param to set the Authorization header to up-stream systems as Basic user:password
* Resolving code review
* mutual exclusiv changes for Basic and Bearer Authorization header
* Fixed the merge mixup and comment error
* Updated changelog and fixed typo
* Adding the new entry in changelog
Co-authored-by: Costel Moraru <costel.moraru-germany@ibm.com>
* Prevent browser caching during auth flow
* simplify no-cache logic, add tests and update changelog
* checking noCacheHeaders does not exists in response headers from upstream
* remove unnecessary codes
* add no-cache headers in SignInPage and OAuthStart for proxy mode
https://github.com/oauth2-proxy/oauth2-proxy/pull/453#discussion_r405072222
when type asserting fails here, err is reassigned with nil and the
default block of the switch prints out <nil> in the error message. This
makes debugging a configuration or access token issue difficult
The particular error this surfaces is:
Response: {
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
}
Signed-off-by: Josh Bielick <jbielick@gmail.com>
* feature: Implement graceful shutdown
Propagate the request context to the Redis client.
It is possible to propagate a context cancel to Redis client if the connection is closed by the HTTP client.
The redis.Cmdable cannot use WithContext, so added the Client interface to handle redis.Client and redis.ClusterClient transparently.
Added handling of Unix signals to http server.
Upgrade go-redis/redis to v7.
* Update dependencies
- Upgrade golang/x/* and google-api-go
- Migrate fsnotify import from gopkg.in to github.com
- Replace bmizerany/assert with stretchr/testify/assert
* add doc for wrapper interface
* Update CHANGELOG.md
* fix: upgrade fsnotify to v1.4.9
* fix: remove unnessary logging
* fix: wait until all connections have been closed
* refactor: move chan to main for testing
* add assert to check if stop chan is empty
* add an idiomatic for sync.WaitGroup with timeout
* Upgrade base image tags and golangci-lint
* Upgrade golang and golangci-lint in travis-ci
* fix: tests, pointed out by golangci-lint and format files
* Upgrade dependencies
* update changelog
* fix: tests related to https://github.com/pusher/oauth2_proxy/pull/418
* Separate tests using go version build tags
* Update CHANGELOG
* Revert "Separate tests using go version build tags"
This reverts commit 9b7e65eb90cae954dc7b6316345d3207205d488a.
* fix test to support go1.14 and go1.13
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* cleaned up source to make golangci-lint pass
* providers/azure_test.go: use build in POST constant
* options_test.go: do not export unnecessary variables
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Clarify how to rename CLI options to be able to set them in the config file. I have just spent an hour trying to find out why `whitelist_domain="..."` does not work :-)
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Previously in #401, an option was added to support forwarding the email
address as the username to the upstream service when the PassBasicAuth
option is used.
The PassBasicAuth option is not appropriate for all users, with PassUserHeaders
allowing very similar functionality without specifying a basic auth headers.
The PreferEmailToUser option has been expanded to support the PassUserHeaders
option.
* Add support for preferred username.
* Add missing TOC entries.
* Add note about preferred_username support.
* Adjust tests.
* Check on not implemented error for GetPreferredUsername() call.
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
With some providers the Username is an upstream Unique ID, like fex. in the
case of Google.
When matching this with downstream databases, it's sometimes preferred to use
the email address as the known identifier.
However, when _mixing_ this with sometimes other sources, like htaccess, which
doesn't have a concept of an email address, it can turn difficult.
This change makes the headers _prefer_ to use the Email address, if such exists,
for the Username identifier when passing data to downstream services.
Defaults to Off.
Signed-off-by: D.S. Ljungmark <ljungmark@modio.se>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Add nsswitch.conf to Docker image
Created nsswitch.conf to use locally defined translations before DNS. Copied to /etc/nsswitch.conf in the image.
* Add new line
* Updated Changelog
Co-authored-by: Dan Bond <danbond@protonmail.com>
* OIDC Token Refresh works without id_tokens
Addresses https://github.com/pusher/oauth2_proxy/issues/318
Refactoring the OIDC provider so that the refresh process works when there are
no id_tokens present in the response. Added unit tests to the oidc_test.go to prove
the redeem and refresh still work.
The expiry time of the session is now taken from the outh token expiry and not
the id_token (preventing stale access_tokens in sessions).
* Refactoring the to use a KeySetStub in the oidc_test.go. This allows the
elimination of the slightly contrived function passing elements used
previously. (This change is being applied to address the bug #318)
* Changes as per the PR comments and preparing for 5.x release
* Fixup changelog
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Extend the redis session store to support redis cluster
* rename function newRedisClient to newRedisCmdable
* update docs about redis cluster as session store
* update autocomplete script with redis cluster options
* add check about conflict between option redis-use-sentinel and redis-use-cluster
* update change log
* Update docs/configuration/sessions.md
Co-Authored-By: Joel Speed <Joel.speed@hotmail.co.uk>
* Update pkg/sessions/redis/redis_store.go
Co-Authored-By: Joel Speed <Joel.speed@hotmail.co.uk>
* add the dropped option back
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
* Fix login page fragment handling after soft reload on Firefox.
* Add comments.
* Move changelog entry to correct place.
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Felix Fontein <felix@fontein.de>
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
* Added userinfo endpoint
* Added documentation for the userinfo endpoint
* Update oauthproxy.go
Co-Authored-By: Dan Bond <pm@danbond.io>
* Suggested fixes : Streaming json to rw , header set after error check
* Update oauthproxy.go
Co-Authored-By: Dan Bond <pm@danbond.io>
* fix session.Email
* Ported tests and updated changelog
* Added version check for bash version gteq 4
* Added entry to CHANGELOG for bash 4.0 configure script dependency
* Corrected changelog entry to right format
* Fixed link in changelog entry
* Remove uneeded new line.
* worked on wrapping errors in requests.go, added defer statements
* removed .idea (generated by goland)
* added another require.NoError
* Update pkg/requests/requests.go
Co-Authored-By: Dan Bond <pm@danbond.io>
* fixed out-of-order imports
* changelog entry added
* swapped error definitions to use fmt.Errorf rather than Wrap()
* formatting changes, added new defers to requests_test.go
* suppot for go1.12 pipeline removed from travis pipeline, .idea/ added to gitignore
* Reorder changelog entry
======================================================
changelog note
[#274](https://github.com/pusher/oauth2_proxy/pull/274) Add github api pagination support (@toshi-miura ,@apratina)
======================================================
I didn't edit CHANGELOG.md.
Since # 102 was taken over and the change difference of CHANGELOG.md was large
* Remove shadowing of predeclared identifier: new.
* strings.ReplaceAll instead of strings.Replace with -1.
* Change strings.ToLower comparison to strings.EqualFold.
* Rewrite if-else-if-else chain as a switch.
The current sample configuration for kubernetes ingress demonstrates
using the `auth-signin` annotation to redirect a user to oauth2_proxy's
signin page. It constructs the link to do so by directly concatenating
`$request_uri` as the `rd` parameter, so the sign-in page knows where to
send the user after signin is complete.
However, this does not work correctly if the original request URI
contains multiple query parameters separated by an ampersand, as that
ampersand is interpereted as separating query parameters of the
`/oauth2/start` URI. For example:
If the user requests a URL:
https://example.com/foo?q1=v1&q2=v2
they may be redirected to the signin url
https://example.com/oauth2/start?rd=https://example.com/foo?q1=v1&q2=v2
and after completing signin, oauth2_proxy will redirect them to
https://example.com/foo?q1=v1
nginx-ingress added an $escaped_request_uri variable about a year ago,
to help resolve this kind of issue
(https://github.com/kubernetes/ingress-nginx/pull/2811)
Add a new provider for Bitbucket,
can be configured from the options
specifying team and/or repository
that the user must be part/have access
to in order to grant login.
alone
Previously some headers that are normally set by the proxy (and may be
replied upstream for authorization decisiions) were not being set
depending on values in the users sesssion.
This change ensure that if a given header is sometimes set, it will
always be either set or removed.
It might be worth considerating always deleting these headers if we
didn't add them.
* New flag "-ssl-upstream-insecure-skip-validation" to skip SSL validation for upstreams with self generated / invalid SSL certificates.
* Fix tests for modified NewReverseProxy method.
* Added change to the changelog.
* Remove duplicate entries from changelog.
* Adding documentation for Okta OIDC provider.
* additional clean up.
* Clearer heading
* Forgot a word.
* updated documentation based on ReillyProcentive review.
* Per steakunderscore review: removed defaults. Removed extra hardening steps (expiration, https only etc) not directly related to setting up Okta w/ OIDC
* Initial version of OIDC based GitLab provider
* Add support for email domain check to GitLab provider
* Add gitlab.com as default issuer for GitLab provider
* Update documentation for GitLab provider
* Update unit tests for new GitLab provider implementation
* Update CHANGELOG for GitLab provider
* Rename GitLab test access token as response to linter
* Check Google group membership with hasMember and get.
This PR is an enhancement built on
https://github.com/pusher/oauth2_proxy/pull/160. That PR reduces the
number of calls to the Google Admin API and simplifies the code by
using the hasMember method. It also supports checking membership in
nested groups.
However, the above message doesn't handle members who are not a part
of the domain. The hasMember API returns a 400 for that case. As a
fallback, when the API returns a 400, this change will try using the
`get` API which works as expected for members who aren't a part of the
domain. Supporting members who belong to the Google group but aren't
part of the domain is a requested feature from
https://github.com/pusher/oauth2_proxy/issues/95.
https://developers.google.com/admin-sdk/directory/v1/reference/members/get
Note that nested members who are not a part of the domain will not be
correctly detected with this change.
* Update CHANGELOG.
* Fix incorrect JSON and stop escaping strings.
* Add comments for each scenario.
* Current OIDC implementation asserts that user email check must come
from JWT token claims. OIDC specification also allows for source
of user email to be fetched from userinfo profile endpoint.
http://openid.net/specs/openid-connect-core-1_0.html#UserInfo
* First, attempt to retrieve email from JWT token claims. Then fall back to
requesting email from userinfo endpoint.
* Don't fallback to subject for email
https://github.com/bitly/oauth2_proxy/pull/481
- Add `ping-path` option to enable switching on and passing to `logger.go`
Default remains unchanged at: `"/ping"`
- Add note in configuration.md about silence flag taking precedence
Potential tests:
- `options.go` sets `logger.SetExcludePath` based on silence flag?
- Changing `PingPath` reflected in router?
Useful for excluding /ping endpoint to reduce log volume.
This is somewhat more verbose than a simple bool to disable logging of
the `/ping` endpoint.
Perhaps better to add `-silence-ping-logging` bool flag to `options.go` and
pass in the `/ping` endpoint as part of `logger` declaration in `options.go`.
Could be extended into a slice of paths similar to go-gin's `SkipPaths`:
https://github.com/gin-gonic/gin/blob/master/logger.go#L46
Add ability to silence logging of requests to /ping endpoint, reducing
log clutter
Pros:
- Don't have to change all handlers to set/not set silent ping logging
- Don't have to duplicate `loggingHandler` (this could be preferable yet)
Cons:
- Leaking oauth2proxy logic into `package logger`
- Defining default pingPath in two locations
Alternative:
- Add generic exclude path to `logger.go` and pass in `/ping`.
This will let Docker cache the results of the vendor dependencies.
Making re-builds during testing faster.
Also clean-up spurious test & rm in ./configure
Fix an unsupported protocol scheme error when validating tokens by
ensuring that the ValidateURL generates a non-empty string. The Azure
provider doesn't define any ValidateURL and therefore uses the default
value of `url.Parse("")` which is not `nil`.
The following log summary shows the issue:
2019/06/14 12:26:04 oauthproxy.go:799: 10.244.1.3:34112 ("10.244.1.1") refreshing 16h26m29s old session cookie for Session{email:jonas.fonseca@example.com user:jonas.fonseca token:true} (refresh after 1h0m0s)
2019/06/14 12:26:04 internal_util.go:60: GET ?access_token=eyJ0...
2019/06/14 12:26:04 internal_util.go:61: token validation request failed: Get ?access_token=eyJ0...: unsupported protocol scheme ""
2019/06/14 12:26:04 oauthproxy.go:822: 10.244.1.3:34112 ("10.244.1.1") removing session. error validating Session{email:jonas.fonseca@example.com user:jonas.fonseca token:true}
As of I think go1.8 GOPATH is by default $HOME/go so it is incorrect to
assume that it is set.
If not set, then the Makefile assumes gometalinter will be in
/bin/gometalinter, which it likely is not, and thus fails.
We could change configure to set GOPATH in the .env, however then we
would be assuming that GOPATH is a single entry - whereas like other
paths, it can contain more than one value.
So instead this commit stops trying to install gometalinter, and like
dep, it assumes that it is installed prior.
(and since the current behaviour of the Makefile is affecting state
external to the project, that seems more logical)
Use simple USER directive.
Using `addgroup` in final `arm` image when building on amd64 doesn't work.
I must have made a mistake during cross build verification.
Alternative is to use qemu-static but it's not worth it for this.
* Use encoding/json for SessionState serialization
In order to make it easier to extend in future.
* Store only email and user in cookie when cipher is unavailable
This improves safety and robustness, and also preserves the existing
behaviour.
* Add TestEncodeSessionState/TestDecodeSessionState
Use the test vectors with JSON encoding just introduced.
* Support session state encoding in older versions
* Add test cases for legacy session state strings
* Add check for wrong expiration time in session state strings
* Avoid exposing time.Time zero value when encoding session state string
* Update CHANGELOG.md
* first stab at login.gov provider
* fixing bugs now that I think I understand things better
* fixing up dependencies
* remove some debug stuff
* Fixing all dependencies to point at my fork
* forgot to hit save on the github rehome here
* adding options for setting keys and so on, use JWT workflow instead of PKCE
* forgot comma
* was too aggressive with search/replace
* need JWTKey to be byte array
* removed custom refresh stuff
* do our own custom jwt claim and store it in the normal session store
* golang json types are strange
* I have much to learn about golang
* fix time and signing key
* add http lib
* fixed claims up since we don't need custom claims
* add libs
* forgot ioutil
* forgot ioutil
* moved back to pusher location
* changed proxy github location back so that it builds externally, fixed up []byte stuff, removed client_secret if we are using login.gov
* update dependencies
* do JWTs properly
* finished oidc flow, fixed up tests to work better
* updated comments, added test that we set expiresOn properly
* got confused with header and post vs get
* clean up debug and test dir
* add login.gov to README, remove references to my repo
* forgot to remove un-needed code
* can use sample_key* instead of generating your own
* updated changelog
* apparently golint wants comments like this
* linter wants non-standard libs in a separate grouping
* Update options.go
Co-Authored-By: timothy-spencer <timothy.spencer@gsa.gov>
* Update options.go
Co-Authored-By: timothy-spencer <timothy.spencer@gsa.gov>
* remove sample_key, improve comments related to client-secret, fix changelog related to PR feedback
* github doesn't seem to do gofmt when merging. :-)
* update CODEOWNERS
* check the nonce
* validate the JWT fully
* forgot to add pubjwk-url to README
* unexport the struct
* fix up the err masking that travis found
* update nonce comment by request of @JoelSpeed
* argh. Thought I'd formatted the merge properly, but apparently not.
* fixed test to not fail if the query time was greater than zero
* fixes deletion of splitted cookies
* three minor adjustments to improve the tests
* changed cookie name matching to regex
* Update oauthproxy.go
Co-Authored-By: einfachchr <einfachchr@gmail.com>
* removed unused variable
* Changelog
* Added conditional to prevent user-supplied redirect URL getting
clobbered
Change-type: patch
* use redirectURL as OAuthCallbackURL (as it should be!)
Change-type: patch
Type: docs
I simply added the word health check. I was searching all over the
package for a health check, to only realise that it had been called
ping. I think the small addition might help others avoid my troubles.
Run as non-root user and group
In the unlikely event that you are currently persisting data to disk then this
change may break file read/write access due to a change in the UID/GID that the
oauth2_proxy process runs as.
Run as non-root system user and group `oauth2proxy` with UID/GID `2000` to avoid clashing with typical local users.
An alternative to creating a separate user is to ~~chown binary and~~ run as `USER nobody`, which also works, can amend this PR if required.
Least access privileges.
Close: https://github.com/pusher/oauth2_proxy/issues/78
Locally with Docker (`-version`):
```
$ ps aux | grep oauth2
2000 25192 6.0 0.0 0 0 ? Ds 15:53 0:00 [oauth2_proxy]
```
Running in Kubernetes 1.13 with the following also specified:
```
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10001
```
```
$ kubectl exec -it -n oauth2-proxy oauth2-proxy-85c9f58ffc-dz9lr sh
/opt $ whoami
whoami: unknown uid 10001
/opt $ ps aux
PID USER TIME COMMAND
1 10001 0:00 /opt/oauth2_proxy --whitelist-domain=.example.com --cookie-domain=example.com --email-domain=example.com --upstream=file:///dev/null --http-address=0.0.0.0:4180
11 10001 0:00 sh
17 10001 0:00 ps aux
```
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [x] My change requires a change to the documentation or CHANGELOG.
- [x] I have updated the documentation/CHANGELOG accordingly.
- [x] I have created a feature (non-master) branch for my PR.
If the GOPATH enviroment variable was not set, go uses the default
GOPATH (~/go/).
The configure script was only checking if the GOPATH environment
is set. If it wasn't the script was failing.
Instead of checking if the GOPATH environment variable is set, check if
"go env GOPATH" returns a non-emtpy string.
* Access token forwarding through nginx auth request
Related to #420.
(cherry picked from commit b138872bea)
Signed-off-by: David Holsgrove <david.holsgrove@biarri.com>
* Improved documentation for auth request token
(cherry picked from commit 6fab314f72)
Signed-off-by: David Holsgrove <david.holsgrove@biarri.com>
* Update README.md
Example should set header as `X-Access-Token`
Co-Authored-By: davidholsgrove <davidholsgrove@users.noreply.github.com>
* Update Changelog to reference https://github.com/pusher/oauth2_proxy/pull/68
* Fix Changelog message location
* Implemented flushing interval
When proxying streaming responses, it would not flush the response writer buffer until some seemingly random point (maybe the number of bytes?). This makes it flush every 1 second by default, but with a configurable interval.
* flushing CHANGELOG
* gofmt and goimports
Update Dockefile to get a much smaller footprint with alpine image.
Optimize ordering of build steps to avoid needless downloads.
Include CA certificates needed for practical use.
Nginx never sends the body with the auth_request sub-request, but
keeps the original Content-Length header by default. Without some
config tweaks, this results in the request to /oauth2/auth hanging.
For some GHE instances where a user can have more than 100
organizations, traversing the other pages is important otherwise
oauth2_proxy will consider the user unauthorized. This change traverses
the list returned by the API to avoid that.
Update github provider tests to include this case.
- Save both user and email in session state:
Encoding/decoding methods save both email and user
field in session state, for use cases when User is not derived from
email's local-parth, like for GitHub provider.
For retrocompatibility, if no user is obtained by the provider,
(e.g. User is an empty string) the encoding/decoding methods fall back
to the previous behavior and use the email's local-part
Updated also related tests and added two more tests to show behavior
when session contains a non-empty user value.
- Added first basic GitHub provider tests
- Added GetUserName method to Provider interface
The new GetUserName method is intended to return the User
value when this is not the email's local-part.
Added also the default implementation to provider_default.go
- Added call to GetUserName in redeemCode
the new GetUserName method is used in redeemCode
to get SessionState User value.
For backward compatibility, if GetUserName error is
"not implemented", the error is ignored.
- Added GetUserName method and tests to github provider.
* don't add in failed compiled regexes for skip auth regex option
* improve test coverage for skip auth regex option to handle partial
success case
* add tests for incorrect upstream options parsing errors
Since I'm no longer with 18F, I've re-released hmacauth under the ISC
license as opposed to the previous CC0 license. There have been no
changes to the hmacauth code itself, and all tests still pass.
See the README for usage with Dex or any other OIDC provider.
To test run a backend:
python3 -m http.server
Run dex and modify the example config with the proxy callback:
go get github.com/coreos/dex/cmd/dex
cd $GOPATH/src/github.com/coreos/dex
sed -i.bak \
's|http://127.0.0.1:5555/callback|http://127.0.0.1:5555/oauth2/callback|g' \
examples/config-dev.yaml
make
./bin/dex serve examples/config-dev.yaml
Then run the oauth2_proxy
oauth2_proxy \
--oidc-issuer-url http://127.0.0.1:5556/dex \
--upstream http://localhost:8000 \
--client-id example-app \
--client-secret ZXhhbXBsZS1hcHAtc2VjcmV0 \
--cookie-secret foo \
--email-domain '*' \
--http-address http://127.0.0.1:5555 \
--redirect-url http://127.0.0.1:5555/oauth2/callback \
--cookie-secure=false
Login with the username/password "admin@example.com:password"
/oauth2/auth is not more sensitive than other /oauth2/ paths,
does not need "internal" protection
"spdy" protocol is obsolete, http2 is the thing to enable now.
But it's orthogonal anyway.
No need for two separate content/upstream location blocks in
this example, reduce to just one, with a comment that it could
be serving files instead of proxying.
The Cookie Prefixes spec disallows the use of the `domain` attribute in cookies
if the `__Host-` prefix is used
(https://tools.ietf.org/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.2).
There's no need to set it to the host by default, so make it optional. If it is
set to a non-empty value, still output a warning if it is not a suffix of the
host, as that's likely not wanted.
Fixes#352.
This is useful in Nginx auth_request mode, if a 401 handler is
configured to redirect to the sign-in page. As the request URL
does not reflect the actual URL, the value is taken from the
header "X-Auth-Request-Redirect" instead. Based on #247
This is enhancement of #173 to use "Auth Request" consistently in
the command-line option, configuration file and response headers.
It always sets the X-Auth-Request-User response header and if the
email is available, sets X-Auth-Request-Email as well.
When checking user membership against Google groups the groups are checked one
at a time and in the order that they were supplied. If one of the groups does
not exist then the checking is halted with the following error.
google.go:201: googleapi: Error 404: Resource Not Found: groupKey, notFound
None of the groups following the missing group are checked either. This means
that something as trivial as a typo in the first group will make it impossible
for anybody to login.
This change catches the 404, logs a message, and then carries on as usual. In
this way a typo will cause a particular group to stop working but will not
affect any other groups.
golang.org/x/oauth2/google is same repo as golang.org/x/oauth2
- this sometimes confused gpm/git
cloud.google.com/go/compute/metadata is a missing dependency
of golang.org/x/oauth2
* This fixes https://github.com/bitly/oauth2_proxy/issues/205
* Add new boolean option -pass-user-headers
to control whether X-Forwarded-User and X-Forwarded-Email
headers will be set (as opposed to HTTP BASIC auth)
* This is required e.g. for grafana [1] where
X-Forwarded-User is needed but HTTP BASIC auth fails
(password is not known and must not be known in this scenario)
* Keep behaviour of PassBasicAuth unchanged for compatibility
[1] http://docs.grafana.org/installation/configuration/#authproxy
print the error stack trace
point to my fork in oauthproxy.go
addint pointers to ruta-goomba fork in mulitple files
change api endpoint
replace hard-coded github api endpoint with variables
resetting fall through github urls to point to github.com
fix malformed url
changes to enable use with enterprise github
The path should be provided as a file:// url with the full operating system path.
An alias to where the directory is available as can be specified by appending
a fragment (ie. "#/static/") at the end of the URL.
By setting this to "force", certain providers, like Google,
will interject an additional prompt on every new session. With other values,
like "auto", this prompt is not forced upon the user.
* New SessionState to consolidate email, access token and refresh token
* split ServeHttp into individual methods
* log on session renewal
* log on access token refresh
* refactor cookie encription/decription and session state serialization
This adds a "*" option to --email-domain to disable email validation, and this renames `--google-apps-domain` to `--email-domain` for clarity across providers
On these platforms, the `done <- true` statement in during TearDown() was
hanging, since the `watcher_unsupported.go` version was never draining the
channel. Also took the opportunity to update the WatchForUpdates() signature
to not return bool anymore.
TestValidatorOverwriteEmailListViaRenameAndReplace was deadlocking on
Windows because, on Windows, fsnotify.Watcher will continue to watch a
renamed file using its new name. On other systems, it appears the watch on
a file is removed after a rename.
The fix is to explicitly remove the watch to ensure the watch is resumed
under the original name.
These test failures from #93 inspired this change:
https://travis-ci.org/bitly/google_auth_proxy/jobs/62474406https://travis-ci.org/bitly/google_auth_proxy/jobs/62474407
Both tests exhibited this pattern:
2015/05/13 22:10:54 validating: is xyzzy@example.com valid? false
2015/05/13 22:10:54 watching interrupted on event: "/tmp/test_auth_emails_300880185": CHMOD
2015/05/13 22:10:54 watching resumed for /tmp/test_auth_emails_300880185
2015/05/13 22:10:54 reloading after event: "/tmp/test_auth_emails_300880185": CHMOD
panic: test timed out after 1m0s
[snip]
goroutine 175 [chan send]:
github.com/bitly/google_auth_proxy.(*ValidatorTest).TearDown(0xc2080bc330)
/home/travis/gopath/src/github.com/bitly/google_auth_proxy/validator_test.go:27 +0x43
github.com/bitly/google_auth_proxy.TestValidatorOverwriteEmailListViaRenameAndReplace(0xc2080f2480)
/home/travis/gopath/src/github.com/bitly/google_auth_proxy/validator_watcher_test.go:103 +0x3b9
[snip]
goroutine 177 [chan send]:
github.com/bitly/google_auth_proxy.func·017()
/home/travis/gopath/src/github.com/bitly/google_auth_proxy/validator_test.go:34 +0x41
I realized that the spurious CHMOD events were causing calls to
`func() { updated <- true }` (from validator_test.go:34), which caused
the goroutine running the watcher to block. At the same time,
ValidatorTest.TearDown was blocked by trying to send into the `done` channel.
The solution was to create a flag that ensured only one value was ever sent
into the update channel.
This test failure from #92 inspired this change:
https://travis-ci.org/bitly/google_auth_proxy/jobs/62425336
2015/05/13 16:27:33 using authenticated emails file /tmp/test_auth_emails_952353477
2015/05/13 16:27:33 watching /tmp/test_auth_emails_952353477 for updates
2015/05/13 16:27:33 validating: is xyzzy@example.com valid? true
2015/05/13 16:27:33 watching interrupted on event: "/tmp/test_auth_emails_952353477": CHMOD
2015/05/13 16:27:33 watching resumed for /tmp/test_auth_emails_952353477
2015/05/13 16:27:33 reloading after event: "/tmp/test_auth_emails_952353477": CHMOD
2015/05/13 16:27:33 watching interrupted on event: "/tmp/test_auth_emails_952353477": REMOVE
2015/05/13 16:27:33 validating: is xyzzy@example.com valid? false
2015/05/13 16:27:33 watching resumed for /tmp/test_auth_emails_952353477
2015/05/13 16:27:33 reloading after event: "/tmp/test_auth_emails_952353477": REMOVE
2015/05/13 16:27:33 failed opening authenticated-emails-file="/tmp/test_auth_emails_952353477", open /tmp/test_auth_emails_952353477: no such file or directory
I believe that what happened was that the call to reload the file after the
second "reloading after event" lost the race when the test shut down and the
file was removed. This change introduces a `done` channel that ensures
outstanding actions complete and the watcher exits before the test removes the
file.
This change extracts the UserMap class from NewValidator() so that its
LoadAuthenticatedEmailsFile() method can be called concurrently. This method
is called by a goroutine containing a fsnotify.Watcher watching the
authenticated emails file.
Watching isn't forever aborted when the authenticated emails file disappears.
The goroutine will call os.Stat() up to twenty times a second if the file is
persistently missing, but that's the pathological case, not the common one.
The common case is that some editors (including Vim) will perform a
rename-and-replace when updating a file, triggering fsnotify.Rename events,
and the file will temporarily disappear. This watcher goroutine handles that
case.
Also, on some platforms (notably Arch Linux), a remove will be preceded by a
fsnotify.Chmod, causing a race between the upcoming fsnotify.Remove and the
call to UserMap.LoadAuthenticatedEmailsFile(). Hence, we treat fsnotify.Chmod
the same as fsnotify.Remove and fsnotify.Rename. There's no significant
penalty to re-adding a file to the watcher.
Also contains the following small changes from the summary of commits below:
- Minor optimization of email domain search
- Fixed api_test.go on Windows
- Add deferred File.Close() calls where needed
- Log error and return if emails file doesn't parse
These are the original commits from #89 squashed into this one:
0c6f2b6 Refactor validator_test to prepare for more tests
e0c792b Add more test cases to validator_test
a9a9d93 Minor optimization of email domain search
b763ea5 Extract LoadAuthenticatedEmailsFile()
8cdaf7f Introduce synchronized UserMap type
1b84eef Add UserMap methods, locking
af15dcf Reload authenticated-emails-file upon update
6d95548 Make UserMap operations lock-free
Per:
- http://stackoverflow.com/questions/21447463/is-assigning-a-pointer-atomic-in-golang
- https://groups.google.com/forum/#!msg/golang-nuts/ueSvaEKgyLY/ZW_74IC4PekJ
75755d5 Fix tests on Windows
d0eab2e Ignore email file watcher Chmod events
0b9798b Fix watcher on Ubuntu 12.04
3a8251a WaitForReplacement() to retry emails file watch
a57fd29 Add deferred File.Close() calls where needed
Because correctness: Don't leak file handles anywhere, and prepare for
future panics and early returns.
52ed3fd Log error and return if emails file doesn't parse
40100d4 Add gopkg.in/fsnotify.v1 dependency to Godeps file
17dfbbc Avoid a race when Remove is preceded by Chmod
Found out the hard way that _incoming_ cookies do _not_ have their expiration
timestamps encoded. To perform auto-refresh based on expiration time, we have
to recalculate it from the time encoded in the cookie value.
The intention is to refresh the cookie whenever the user accesses an
authenticated service with less than `cookie-refresh` time to go before the
cookie expires.
Without this change, clicking the sign-in button on /oauth2/sign_in will
always redirect back to /oauth2/sign_in, essentially creating an infinite
loop.
This is the first step towards genericizing the google_auth_proxy to support
OAuth2 providers other than Google as discussed in #65. The `api` package will
enable multiple providers to use the same `api.Request()` implementation.
xargs sed -i "s#quay.io/oauth2-proxy/oauth2-proxy:v[0-9]\+\.[0-9]\+\.[0-9]\+#quay.io/oauth2-proxy/oauth2-proxy:v${VERSION}#g"
- name:Commit and push
run:|
VERSION=${{ steps.validate.outputs.version }}
git checkout -b release/v${VERSION}
git commit -am "update to release version v${VERSION}"
git push -u origin release/v${VERSION}
- name:Create PR
env:
GITHUB_TOKEN:${{ secrets.GITHUB_TOKEN }}
run:|
VERSION=v${{ steps.validate.outputs.version }}
gh pr create -B master -H release/${VERSION} --title "release ${VERSION}" --body "Release branch and changes created by GitHub Actions. This PR should include changes to the docs, CHANGELOG and local environment files."
stale-issue-message:'This issue has been inactive for 180 days. If the issue is still relevant please comment to re-activate the issue. If no action is taken within 14 days, the issue will be marked closed.'
stale-pr-message:'This pull request has been inactive for 180 days. If the pull request is still relevant please comment to re-activate the pull request. If no action is taken within 14 days, the pull request will be marked closed.'
org.opencontainers.image.description="A reverse proxy that provides authentication with Google, Azure, OpenID Connect and many more identity providers."\
A reverse proxy that provides authentication using Google OAuth2 to validate
individual accounts, or a whole google apps domain.
OAuth2-Proxy is a flexible, open-source tool that can act as either a standalone reverse proxy or a middleware component integrated into existing reverse proxy or load balancer setups. It provides a simple and secure way to protect your web applications with OAuth2 / OIDC authentication. As a reverse proxy, it intercepts requests to your application and redirects users to an OAuth2 provider for authentication. As a middleware, it can be seamlessly integrated into your existing infrastructure to handle authentication for multiple applications.
OAuth2-Proxy supports a lot of OAuth2 as well as OIDC providers. Either through a generic OIDC client or a specific implementation for Google, Microsoft Entra ID, GitHub, login.gov and others. Through specialised provider implementations oauth2-proxy can extract more details about the user like preferred usernames and groups. Those details can then be forwarded as HTTP headers to your upstream applications.
OAuth2-Proxy's [Installation Docs](https://oauth2-proxy.github.io/oauth2-proxy/installation) cover how to install and configure your setup. Additionally you can take a further look at the [example setup files](https://github.com/oauth2-proxy/oauth2-proxy/tree/master/contrib/local-environment).
We publish oauth2-proxy as compiled binaries on GitHub for all major architectures as well as more exotic ones like `ppc64le` as well as `s390x`.
## Installation
Check out the [latest release](https://github.com/oauth2-proxy/oauth2-proxy/releases/latest).
1. Download [Prebuilt Binary](https://github.com/bitly/google_auth_proxy/releases) or build from `master` with `$ go get github.com/bitly/google_auth_proxy` which should put the binary in `$GOROOT/bin`
2. Register an OAuth Application with Google
3. Configure Google Auth Proxy using config file, command line options, or environment variables
4. Deploy behind a SSL endpoint (example provided for Nginx)
### Images
## OAuth Configuration
From `v7.6.0` and up the base image has been changed from Alpine to [GoogleContainerTools/distroless](https://github.com/GoogleContainerTools/distroless).
This image comes with even fewer installed dependencies and thus should improve security. The image therefore is also slightly smaller than Alpine.
For debugging purposes (and those who really need it. e.g. `armv6`) we still provide images based on Alpine. The tags of these images are suffixed with `-alpine`.
You will need to register an OAuth application with google, and configure it with Redirect URI(s) for the domain you
intend to run `google_auth_proxy` on.
Since 2023-11-18 we build nightly images directly from the `master` branch and provide them at `quay.io/oauth2-proxy/oauth2-proxy-nightly`.
These images are considered unstable and therefore should **NOT** be used for production purposes unless you know what you're doing.
1. Create a new project: https://console.developers.google.com/project
2. Under "APIs & Auth", choose "Credentials"
3. Now, choose "Create new Client ID"
* The Application Type should be **Web application**
* Enter your domain in the Authorized Javascript Origins `https://internal.yourcompany.com`
* Enter the correct Authorized Redirect URL `https://internal.yourcompany.com/oauth2/callback`
* NOTE: `google_auth_proxy` will _only_ callback on the path `/oauth2/callback`
4. Under "APIs & Auth" choose "Consent Screen"
* Fill in the necessary fields and Save (this is _required_)
5. Take note of the **Client ID** and **Client Secret**
Would you like to sponsor the project then please contact us at [sponsors@oauth2-proxy.dev](mailto:sponsors@oauth2-proxy.dev)
`google_auth_proxy` can be configured via [config file](#config-file), [command line options](#command-line-options) or [environment variables](#environment-variables).
Join the #oauth2-proxy [Slack channel](https://gophers.slack.com/archives/CM2RSS25N) to chat with other users of oauth2-proxy or reach out to the maintainers directly. Use the [public invite link](https://invite.slack.golangbridge.org/) to get an invite for the Gopher Slack space.
An example [google_auth_proxy.cfg](contrib/google_auth_proxy.cfg.example) config file is in the contrib directory. It can be used by specifying `-config=/etc/google_auth_proxy.cfg`
OAuth2-Proxy is a community-driven project. We rely on the contribut️ions of our users to continually improve it. While review times can vary, we appreciate your patience and understanding. As a volunteer-driven project, we strive to keep this project stable and might take longer to merge changes.
### Command Line Options
If you want to contribute to the project. Please see our [Contributing](https://oauth2-proxy.github.io/oauth2-proxy/community/contribution) guide.
```
Usage of google_auth_proxy:
-authenticated-emails-file="": authenticate against emails via file (one per line)
-client-id="": the Google OAuth Client ID: ie: "123456.apps.googleusercontent.com"
-client-secret="": the OAuth Client Secret
-config="": path to config file
-cookie-domain="": an optional cookie domain to force cookies to (ie: .yourcompany.com)*
-cookie-expire=168h0m0s: expire timeframe for cookie
-cookie-httponly=true: set HttpOnly cookie flag
-cookie-https-only=true: set secure (HTTPS) cookies (deprecated. use --cookie-secure setting)
-cookie-secret="": the seed string for secure cookies
-cookie-secure=true: set secure (HTTPS) cookie flag
-custom-templates-dir="": path to custom html templates
-display-htpasswd-form=true: display username / password login form if an htpasswd file is provided
-google-apps-domain=: authenticate against the given Google apps domain (may be given multiple times)
-htpasswd-file="": additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -s" for SHA encryption
-http-address="127.0.0.1:4180": [http://]<addr>:<port> or unix://<path> to listen on for HTTP clients
-pass-basic-auth=true: pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
-pass-host-header=true: pass the request Host Header to upstream
-redirect-url="": the OAuth Redirect URL. ie: "https://internalapp.yourcompany.com/oauth2/callback"
-skip-auth-regex=: bypass authentication for requests path's that match (may be given multiple times)
-upstream=: the http url(s) of the upstream endpoint. If multiple, routing is based on path
-version=false: print version string
```
Who uses OAuth2-Proxy? Have a look at our new [ADOPTERS](ADOPTERS.md) file and
feel free to open a PR to add your organisation.
### Environment variables
Thanks to all the people who already contributed ❤
The environment variables `GOOGLE_AUTH_PROXY_CLIENT_ID`, `GOOGLE_AUTH_PROXY_CLIENT_SECRET`, `GOOGLE_AUTH_PROXY_COOKIE_SECRET`, `GOOGLE_AUTH_PROXY_COOKIE_DOMAIN` and `GOOGLE_AUTH_PROXY_COOKIE_EXPIRE` can be used in place of the corresponding command-line arguments.
This example has a [Nginx](http://nginx.org/) SSL endpoint proxying to `google_auth_proxy` on port `4180`.
`google_auth_proxy` then authenticates requests for an upstream application running on port `8080`. The external
endpoint for this example would be `https://internal.yourcompany.com/`.
## Security
An example Nginx config follows. Note the use of `Strict-Transport-Security` header to pin requests to SSL
via [HSTS](http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security):
If you believe you have found a vulnerability within OAuth2 Proxy or any of its dependencies, please do **NOT** open an issue or PR on GitHub, please do **NOT** post any details publicly.
Security disclosures **MUST** be done in private. If you have found an issue that you would like to bring to the attention of the maintainers, please compose an email and send it to the list of people listed in our [MAINTAINERS](MAINTAINERS) file.
location / {
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-Scheme $scheme;
proxy_connect_timeout 1;
proxy_send_timeout 30;
proxy_read_timeout 30;
}
}
```
For more details read our full [Security Docs](https://oauth2-proxy.github.io/oauth2-proxy/community/security#security-disclosures)
The command line to run `google_auth_proxy` would look like this:
### Security Notice for v6.0.0 and older
```bash
./google_auth_proxy \
--google-apps-domain="yourcompany.com" \
--upstream=http://127.0.0.1:8080/ \
--cookie-secret=... \
--cookie-secure=true \
--client-id=... \
--client-secret=...
```
If you are running a version older than v6.0.0 we **strongly recommend** to the current version.
See [open redirect vulnerability](https://github.com/oauth2-proxy/oauth2-proxy/security/advisories/GHSA-5m6c-jp6f-2vcv) for details.
## Endpoint Documentation
## Repository History
Google Auth Proxy responds directly to the following endpoints. All other endpoints will be proxied upstream when authenticated.
**2018-11-27:** This repository was forked from [bitly/OAuth2_Proxy](https://github.com/bitly/oauth2_proxy). Versions v3.0.0 and up are from this fork and will have diverged from any changes in the original fork. A list of changes can be seen in the [CHANGELOG](CHANGELOG.md).
* /ping - returns an 200 OK response
* /oauth2/sign_in - the login page, which also doubles as a sign out page (it clears cookies)
* /oauth2/start - a URL that will redirect to start the OAuth cycle
* /oauth2/callback - the URL used at the end of the OAuth cycle. The oauth app will be configured with this ass the callback url.
**2020-03-29:** This project was formerly hosted as `pusher/oauth2_proxy` but has been renamed to `oauth2-proxy/oauth2-proxy`. Going forward, all images shall be available at `quay.io/oauth2-proxy/oauth2-proxy` and binaries will be named `oauth2-proxy`.
## Logging Format
## License
Google Auth Proxy logs requests to stdout in a format similar to Apache Combined Log.
The is a legacy document to explain the manual process of creating and publishing a new release of oauth2-proxy. As of now the release process has been automated with GitHub Actions workflows. For more information have a look at the workflows `create-release.yml` and `publish-release.yml`.
Here's how OAuth2 Proxy releases are created.
## Schedule
Our aim is to release once a quarter, but bug fixes will be prioritised and might be released earlier.
## The Process
Note this uses `v4.1.0` as an example release number.
1. Create a draft Github release
* Use format `v4.1.0` for both the tag and title
2. Update [CHANGELOG.md](CHANGELOG.md)
* Write the release highlights
* Copy in headings ready for the next release
3. Create release commit
```
git checkout -b release-v4.1.0
```
4. Create pull request getting other maintainers to review
5. Copy the release notes in to the draft Github release, adding a link to [CHANGELOG.md](CHANGELOG.md)
6. Update you local master branch
```
git checkout master
git pull
```
7. Create & push the tag
```
git tag v4.1.0
git push --tags
```
8. Make the release artefacts
```
make release
```
9. Upload all the files (not the folders) from the `/release` folder to Github release as binary artefacts. There should be both the tarballs (`tar.gz`) and the checksum files (`sha256sum.txt`).
10. Publish release in Github
11. Make and push docker images to Quay
```
make build-docker-all
make push-docker-all
```
Note: Ensure the docker tags don't include `-dirty`. This means you have uncommitted changes.
12. Verify everything looks good at [quay](https://quay.io/repository/oauth2-proxy/oauth2-proxy?tag=latest&tab=tags) and [github](https://github.com/oauth2-proxy/oauth2-proxy/releases)
Run `make up` to deploy local dex, etcd and oauth2-proxy instances in Docker containers. Review the [`Makefile`](Makefile) for additional deployment options.
kubectl --namespace ingress-nginx rollout status --timeout 5m deployment/ingress-nginx-controller
# default Pod CIDR is 10.244.0.0/16 https://github.com/kubernetes-sigs/kind/blob/a6e8108025bc7a9440beedb8ef7714aec84fe87e/pkg/apis/config/v1alpha4/default.go#L52
# what makes cluster host IP equal to 10.244.0.1
# thus we add dex.localtest.me and oauth2-proxy.localtest.me stub hosts pointing to this IP
Visit http://httpbin.localtest.me or http://hello-world.localtest.me/
Note: When accessing the service for the first time you will need to authenticate with Dex. It is configured using static credentials for testing. With username `admin@example.com` and password set to `password`.
1. Any request passing through the proxy (and not matched by `--skip-auth-regex`) is checked for the proxy's session cookie (`--cookie-name`) (or, if allowed, a JWT token - see `--skip-jwt-bearer-tokens`).
2. If authentication is required but missing then the user is asked to log in and redirected to the authentication provider (unless it is an Ajax request, i.e. one with `Accept: application/json`, in which case 401 Unauthorized is returned)
3. After returning from the authentication provider, the oauth tokens are stored in the configured session store (cookie, redis, ...) and a cookie is set
4. The request is forwarded to the upstream server with added user info and authentication headers (depending on the configuration)
Notice that the proxy also provides a number of useful [endpoints](features/endpoints.md).
If you find a bug, please open an Issue. When opening an Issue or Pull Request please follow the preconfigured template and take special note of the checkboxes.
If you want to fix a bug, add a new feature or extend existing functionality, please create a fork, create a feature branch and open a PR back to this repo.
Please mention open bug issue number(s) within your PR if applicable.
We suggest using [Visual Studio Code](https://code.visualstudio.com/docs/languages/go) with the official [Go for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=golang.go) extension.
# Go version
See the `go.mod` file in the root of this repository for the version of Go used by this project.
You can follow [the installation guide for Go](https://go.dev/doc/install),
and you can find this specific Go version on [the Go downloads page](https://go.dev/dl/).
# Preparing your fork
Clone your fork, create a feature branch and update the depedencies to get started.
Before you can start your local version of oauth2-proxy, you will have to use the provided docker compose files to start a local upstream service and identity provider. We suggest using [httpbin](https://hub.docker.com/r/kennethreitz/httpbin) as your upstream for testing as it allows for request and response introspection of all things HTTP.
Inside the `contrib/local-environment` directory you can use the `Makefile` for
starting different example setups:
- Dex as your IdP: `make up` or `make down`
- Dex as your IdP using the alpha-config: `make alpha-config-up`
- Keycloak as your IdP: `make keycloak-up`
- Dex as your IdP & nginx reverse proxy: `make nginx-up`
- and many more...
Check out the `Makefile` to see what is available.
The username and password for all setups is usually `admin@example.com` and `password`.
The docker compose setups expose the services with a dynamic reverse DNS resolver: localtest.me
The alpha package supports the use of environment variables in place of yaml keys, allowing sensitive values to be pulled from somewhere other than the yaml file.
When using environment variables, your yaml will look like this:
```yaml
providers:
- provider: azure
clientSecret: ${CLIENT_SECRET}
...
```
Where CLIENT_SECRET is an environment variable.
More information and available patterns can be found [here](https://github.com/a8m/envsubst#docs)
## Removed options
The following flags/options and their respective environment variables are no
Usage of these options allows users to access alpha features that are not
available as part of the primary configuration structure for OAuth2 Proxy.
:::warning
The options within this structure are considered alpha.
They may change between releases without notice.
:::
| Field | Type | Description |
| ----- | ---- | ----------- |
| `upstreamConfig` | _[UpstreamConfig](#upstreamconfig)_ | UpstreamConfig is used to configure upstream servers.<br/>Once a user is authenticated, requests to the server will be proxied to<br/>these upstream servers based on the path mappings defined in this list. |
| `injectRequestHeaders` | _[[]Header](#header)_ | InjectRequestHeaders is used to configure headers that should be added<br/>to requests to upstream servers.<br/>Headers may source values from either the authenticated user's session<br/>or from a static secret value. |
| `injectResponseHeaders` | _[[]Header](#header)_ | InjectResponseHeaders is used to configure headers that should be added<br/>to responses from the proxy.<br/>This is typically used when using the proxy as an external authentication<br/>provider in conjunction with another proxy such as NGINX and its<br/>auth_request module.<br/>Headers may source values from either the authenticated user's session<br/>or from a static secret value. |
| `server` | _[Server](#server)_ | Server is used to configure the HTTP(S) server for the proxy application.<br/>You may choose to run both HTTP and HTTPS servers simultaneously.<br/>This can be done by setting the BindAddress and the SecureBindAddress simultaneously.<br/>To use the secure server you must configure a TLS certificate and key. |
| `metricsServer` | _[Server](#server)_ | MetricsServer is used to configure the HTTP(S) server for metrics.<br/>You may choose to run both HTTP and HTTPS servers simultaneously.<br/>This can be done by setting the BindAddress and the SecureBindAddress simultaneously.<br/>To use the secure server you must configure a TLS certificate and key. |
| `providers` | _[Providers](#providers)_ | Providers is used to configure your provider. **Multiple-providers is not<br/>yet working.** [This feature is tracked in<br/>#925](https://github.com/oauth2-proxy/oauth2-proxy/issues/926) |
### AzureOptions
(**Appears on:** [Provider](#provider))
| Field | Type | Description |
| ----- | ---- | ----------- |
| `tenant` | _string_ | Tenant directs to a tenant-specific or common (tenant-independent) endpoint<br/>Default value is 'common' |
| `graphGroupField` | _string_ | GraphGroupField configures the group field to be used when building the groups list from Microsoft Graph<br/>Default value is 'id' |
### BitbucketOptions
(**Appears on:** [Provider](#provider))
| Field | Type | Description |
| ----- | ---- | ----------- |
| `team` | _string_ | Team sets restrict logins to members of this team |
| `repository` | _string_ | Repository sets restrict logins to user with access to this repository |
### ClaimSource
(**Appears on:** [HeaderValue](#headervalue))
ClaimSource allows loading a header value from a claim within the session
| Field | Type | Description |
| ----- | ---- | ----------- |
| `claim` | _string_ | Claim is the name of the claim in the session that the value should be<br/>loaded from. Available claims: `access_token``id_token``created_at`<br/>`expires_on` `refresh_token``email``user``groups``preferred_username`. |
| `prefix` | _string_ | Prefix is an optional prefix that will be prepended to the value of the<br/>claim if it is non-empty. |
| `basicAuthPassword` | _[SecretSource](#secretsource)_ | BasicAuthPassword converts this claim into a basic auth header.<br/>Note the value of claim will become the basic auth username and the<br/>basicAuthPassword will be used as the password value. |
### Duration
#### (`string` alias)
(**Appears on:** [Upstream](#upstream))
Duration is as string representation of a period of time.
A duration string is a is a possibly signed sequence of decimal numbers,
each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
### GitHubOptions
(**Appears on:** [Provider](#provider))
| Field | Type | Description |
| ----- | ---- | ----------- |
| `org` | _string_ | Org sets restrict logins to members of this organisation |
| `team` | _string_ | Team sets restrict logins to members of this team |
| `repo` | _string_ | Repo sets restrict logins to collaborators of this repository |
| `token` | _string_ | Token is the token to use when verifying repository collaborators<br/>it must have push access to the repository |
| `users` | _[]string_ | Users allows users with these usernames to login<br/>even if they do not belong to the specified org and team or collaborators |
### GitLabOptions
(**Appears on:** [Provider](#provider))
| Field | Type | Description |
| ----- | ---- | ----------- |
| `group` | _[]string_ | Group sets restrict logins to members of this group |
| `projects` | _[]string_ | Projects restricts logins to members of these projects |
### GoogleOptions
(**Appears on:** [Provider](#provider))
| Field | Type | Description |
| ----- | ---- | ----------- |
| `group` | _[]string_ | Groups sets restrict logins to members of this Google group |
| `adminEmail` | _string_ | AdminEmail is the Google admin to impersonate for api calls |
| `serviceAccountJson` | _string_ | ServiceAccountJSON is the path to the service account json credentials |
| `useApplicationDefaultCredentials` | _bool_ | UseApplicationDefaultCredentials is a boolean whether to use Application Default Credentials instead of a ServiceAccountJSON |
| `targetPrincipal` | _string_ | TargetPrincipal is the Google Service Account used for Application Default Credentials |
### Header
(**Appears on:** [AlphaOptions](#alphaoptions))
Header represents an individual header that will be added to a request or
response header.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `name` | _string_ | Name is the header name to be used for this set of values.<br/>Names should be unique within a list of Headers. |
| `preserveRequestValue` | _bool_ | PreserveRequestValue determines whether any values for this header<br/>should be preserved for the request to the upstream server.<br/>This option only applies to injected request headers.<br/>Defaults to false (headers that match this header will be stripped). |
| `values` | _[[]HeaderValue](#headervalue)_ | Values contains the desired values for this header |
### HeaderValue
(**Appears on:** [Header](#header))
HeaderValue represents a single header value and the sources that can
make up the header value
| Field | Type | Description |
| ----- | ---- | ----------- |
| `value` | _[]byte_ | Value expects a base64 encoded string value. |
| `fromEnv` | _string_ | FromEnv expects the name of an environment variable. |
| `fromFile` | _string_ | FromFile expects a path to a file containing the secret value. |
| `claim` | _string_ | Claim is the name of the claim in the session that the value should be<br/>loaded from. Available claims: `access_token``id_token``created_at`<br/>`expires_on` `refresh_token``email``user``groups``preferred_username`. |
| `prefix` | _string_ | Prefix is an optional prefix that will be prepended to the value of the<br/>claim if it is non-empty. |
| `basicAuthPassword` | _[SecretSource](#secretsource)_ | BasicAuthPassword converts this claim into a basic auth header.<br/>Note the value of claim will become the basic auth username and the<br/>basicAuthPassword will be used as the password value. |
### KeycloakOptions
(**Appears on:** [Provider](#provider))
| Field | Type | Description |
| ----- | ---- | ----------- |
| `groups` | _[]string_ | Group enables to restrict login to members of indicated group |
| `roles` | _[]string_ | Role enables to restrict login to users with role (only available when using the keycloak-oidc provider) |
### LoginGovOptions
(**Appears on:** [Provider](#provider))
| Field | Type | Description |
| ----- | ---- | ----------- |
| `jwtKey` | _string_ | JWTKey is a private key in PEM format used to sign JWT, |
| `jwtKeyFile` | _string_ | JWTKeyFile is a path to the private key file in PEM format used to sign the JWT |
| `pubjwkURL` | _string_ | PubJWKURL is the JWK pubkey access endpoint |
### LoginURLParameter
(**Appears on:** [Provider](#provider))
LoginURLParameter is the configuration for a single query parameter that
can be passed through from the `/oauth2/start` endpoint to the IdP login
URL. The "default" option specifies the default value or values (if any)
that will be passed to the IdP for this parameter, and "allow" is a list
of options for ways in which this parameter can be set or overridden via
the query string to `/oauth2/start`.
If _only_ a default is specified and no "allow" then the parameter is
effectively fixed - the default value will always be used and anything
passed to the start URL will be ignored. If _only_ "allow" is specified
but no default then the parameter will only be passed on to the IdP if
the caller provides it, and no value will be sent otherwise.
Examples:
# A parameter whose value is fixed
```
name: organization
default:
- myorg
```
A parameter that is not passed by default, but may be set to one of a
fixed set of values
```
name: prompt
allow:
- value: login
- value: consent
- value: select_account
```
A parameter that is passed by default but may be overridden by one of
a fixed set of values
```
name: prompt
default: ["login"]
allow:
- value: consent
- value: select_account
```
A parameter that may be overridden, but only by values that match a
regular expression. For example to restrict `login_hint` to email
addresses in your organization's domain:
```
name: login_hint
allow:
- pattern: '^[^@]*@example\.com$'
# this allows at most one "@" sign, and requires "example.com" domain.
```
Note that the YAML rules around exactly which characters are allowed
and/or require escaping in different types of string literals are
convoluted. For regular expressions the single quoted form is simplest
as backslash is not considered to be an escape character. Alternatively
use the "chomped block" format `|-`:
```
- pattern: |-
^[^@]*@example\.com$
```
The hyphen is important, a `|` block would have a trailing newline
character.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `name` | _string_ | Name specifies the name of the query parameter. |
| `default` | _[]string_ | _(Optional)_ Default specifies a default value or values that will be<br/>passed to the IdP if not overridden. |
| `allow` | _[[]URLParameterRule](#urlparameterrule)_ | _(Optional)_ Allow specifies rules about how the default (if any) may be<br/>overridden via the query string to `/oauth2/start`. Only<br/>values that match one or more of the allow rules will be<br/>forwarded to the IdP. |
### MicrosoftEntraIDOptions
(**Appears on:** [Provider](#provider))
| Field | Type | Description |
| ----- | ---- | ----------- |
| `allowedTenants` | _[]string_ | AllowedTenants is a list of allowed tenants. In case of multi-tenant apps, incoming tokens are<br/>issued by different issuers and OIDC issuer verification needs to be disabled.<br/>When not specified, all tenants are allowed. Redundant for single-tenant apps<br/>(regular ID token validation matches the issuer). |
| `issuerURL` | _string_ | IssuerURL is the OpenID Connect issuer URL<br/>eg: https://accounts.google.com |
| `insecureAllowUnverifiedEmail` | _bool_ | InsecureAllowUnverifiedEmail prevents failures if an email address in an id_token is not verified<br/>default set to 'false' |
| `insecureSkipIssuerVerification` | _bool_ | InsecureSkipIssuerVerification skips verification of ID token issuers. When false, ID Token Issuers must match the OIDC discovery URL<br/>default set to 'false' |
| `insecureSkipNonce` | _bool_ | InsecureSkipNonce skips verifying the ID Token's nonce claim that must match<br/>the random nonce sent in the initial OAuth flow. Otherwise, the nonce is checked<br/>after the initial OAuth redeem & subsequent token refreshes.<br/>default set to 'true'<br/>Warning: In a future release, this will change to 'false' by default for enhanced security. |
| `skipDiscovery` | _bool_ | SkipDiscovery allows to skip OIDC discovery and use manually supplied Endpoints<br/>default set to 'false' |
| `jwksURL` | _string_ | JwksURL is the OpenID Connect JWKS URL<br/>eg: https://www.googleapis.com/oauth2/v3/certs |
| `publicKeyFiles` | _[]string_ | PublicKeyFiles is a list of paths pointing to public key files in PEM format to use<br/>for verifying JWT tokens |
| `emailClaim` | _string_ | EmailClaim indicates which claim contains the user email,<br/>default set to 'email' |
| `groupsClaim` | _string_ | GroupsClaim indicates which claim contains the user groups<br/>default set to 'groups' |
| `userIDClaim` | _string_ | UserIDClaim indicates which claim contains the user ID<br/>default set to 'email' |
| `audienceClaims` | _[]string_ | AudienceClaim allows to define any claim that is verified against the client id<br/>By default `aud` claim is used for verification. |
| `extraAudiences` | _[]string_ | ExtraAudiences is a list of additional audiences that are allowed<br/>to pass verification in addition to the client id. |
### Provider
(**Appears on:** [Providers](#providers))
Provider holds all configuration for a single provider
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientID` | _string_ | ClientID is the OAuth Client ID that is defined in the provider<br/>This value is required for all providers. |
| `clientSecret` | _string_ | ClientSecret is the OAuth Client Secret that is defined in the provider<br/>This value is required for all providers. |
| `clientSecretFile` | _string_ | ClientSecretFile is the name of the file<br/>containing the OAuth Client Secret, it will be used if ClientSecret is not set. |
| `keycloakConfig` | _[KeycloakOptions](#keycloakoptions)_ | KeycloakConfig holds all configurations for Keycloak provider. |
| `azureConfig` | _[AzureOptions](#azureoptions)_ | AzureConfig holds all configurations for Azure provider. |
| `microsoftEntraIDConfig` | _[MicrosoftEntraIDOptions](#microsoftentraidoptions)_ | MicrosoftEntraIDConfig holds all configurations for Entra ID provider. |
| `ADFSConfig` | _[ADFSOptions](#adfsoptions)_ | ADFSConfig holds all configurations for ADFS provider. |
| `bitbucketConfig` | _[BitbucketOptions](#bitbucketoptions)_ | BitbucketConfig holds all configurations for Bitbucket provider. |
| `githubConfig` | _[GitHubOptions](#githuboptions)_ | GitHubConfig holds all configurations for GitHubC provider. |
| `gitlabConfig` | _[GitLabOptions](#gitlaboptions)_ | GitLabConfig holds all configurations for GitLab provider. |
| `googleConfig` | _[GoogleOptions](#googleoptions)_ | GoogleConfig holds all configurations for Google provider. |
| `oidcConfig` | _[OIDCOptions](#oidcoptions)_ | OIDCConfig holds all configurations for OIDC provider<br/>or providers utilize OIDC configurations. |
| `loginGovConfig` | _[LoginGovOptions](#logingovoptions)_ | LoginGovConfig holds all configurations for LoginGov provider. |
| `id` | _string_ | ID should be a unique identifier for the provider.<br/>This value is required for all providers. |
| `provider` | _[ProviderType](#providertype)_ | Type is the OAuth provider<br/>must be set from the supported providers group,<br/>otherwise 'Google' is set as default |
| `name` | _string_ | Name is the providers display name<br/>if set, it will be shown to the users in the login page. |
| `caFiles` | _[]string_ | CAFiles is a list of paths to CA certificates that should be used when connecting to the provider.<br/>If not specified, the default Go trust sources are used instead |
| `useSystemTrustStore` | _bool_ | UseSystemTrustStore determines if your custom CA files and the system trust store are used<br/>If set to true, your custom CA files and the system trust store are used otherwise only your custom CA files. |
| `loginURL` | _string_ | LoginURL is the authentication endpoint |
| `loginURLParameters` | _[[]LoginURLParameter](#loginurlparameter)_ | LoginURLParameters defines the parameters that can be passed from the start URL to the IdP login URL |
| `authRequestResponseMode` | _string_ | AuthRequestResponseMode defines the response mode to request during authorization request |
| `redeemURL` | _string_ | RedeemURL is the token redemption endpoint |
| `profileURL` | _string_ | ProfileURL is the profile access endpoint |
| `skipClaimsFromProfileURL` | _bool_ | SkipClaimsFromProfileURL allows to skip request to Profile URL for resolving claims not present in id_token<br/>default set to 'false' |
| `resource` | _string_ | ProtectedResource is the resource that is protected (Azure AD and ADFS only) |
| `validateURL` | _string_ | ValidateURL is the access token validation endpoint |
| `scope` | _string_ | Scope is the OAuth scope specification |
| `allowedGroups` | _[]string_ | AllowedGroups is a list of restrict logins to members of this group |
| `code_challenge_method` | _string_ | The code challenge method |
| `backendLogoutURL` | _string_ | URL to call to perform backend logout, `{id_token}` would be replaced by the actual `id_token` if available in the session |
### ProviderType
#### (`string` alias)
(**Appears on:** [Provider](#provider))
ProviderType is used to enumerate the different provider type options
SecretSource references an individual secret value.
Only one source within the struct should be defined at any time.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `value` | _[]byte_ | Value expects a base64 encoded string value. |
| `fromEnv` | _string_ | FromEnv expects the name of an environment variable. |
| `fromFile` | _string_ | FromFile expects a path to a file containing the secret value. |
### Server
(**Appears on:** [AlphaOptions](#alphaoptions))
Server represents the configuration for an HTTP(S) server
| Field | Type | Description |
| ----- | ---- | ----------- |
| `BindAddress` | _string_ | BindAddress is the address on which to serve traffic.<br/>Leave blank or set to "-" to disable. |
| `SecureBindAddress` | _string_ | SecureBindAddress is the address on which to serve secure traffic.<br/>Leave blank or set to "-" to disable. |
| `TLS` | _[TLS](#tls)_ | TLS contains the information for loading the certificate and key for the<br/>secure traffic and further configuration for the TLS server. |
### TLS
(**Appears on:** [Server](#server))
TLS contains the information for loading a TLS certificate and key
as well as an optional minimal TLS version that is acceptable.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `Key` | _[SecretSource](#secretsource)_ | Key is the TLS key data to use.<br/>Typically this will come from a file. |
| `Cert` | _[SecretSource](#secretsource)_ | Cert is the TLS certificate data to use.<br/>Typically this will come from a file. |
| `MinVersion` | _string_ | MinVersion is the minimal TLS version that is acceptable.<br/>E.g. Set to "TLS1.3" to select TLS version 1.3 |
| `CipherSuites` | _[]string_ | CipherSuites is a list of TLS cipher suites that are allowed.<br/>E.g.:<br/>- TLS_RSA_WITH_RC4_128_SHA<br/>- TLS_RSA_WITH_AES_256_GCM_SHA384<br/>If not specified, the default Go safe cipher list is used.<br/>List of valid cipher suites can be found in the [crypto/tls documentation](https://pkg.go.dev/crypto/tls#pkg-constants). |
URLParameterRule represents a rule by which query parameters
passed to the `/oauth2/start` endpoint are checked to determine whether
they are valid overrides for the given parameter passed to the IdP's
login URL. Either Value or Pattern should be supplied, not both.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `value` | _string_ | A Value rule matches just this specific value |
| `pattern` | _string_ | A Pattern rule gives a regular expression that must be matched by<br/>some substring of the value. The expression is _not_ automatically<br/>anchored to the start and end of the value, if you _want_ to restrict<br/>the whole parameter value you must anchor it yourself with `^` and `$`. |
Upstream represents the configuration for an upstream server.
Requests will be proxied to this upstream if the path matches the request path.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `id` | _string_ | ID should be a unique identifier for the upstream.<br/>This value is required for all upstreams. |
| `path` | _string_ | Path is used to map requests to the upstream server.<br/>The closest match will take precedence and all Paths must be unique.<br/>Path can also take a pattern when used with RewriteTarget.<br/>Path segments can be captured and matched using regular experessions.<br/>Eg:<br/>- `^/foo$`: Match only the explicit path `/foo`<br/>- `^/bar/$`: Match any path prefixed with `/bar/`<br/>- `^/baz/(.*)$`: Match any path prefixed with `/baz` and capture the remaining path for use with RewriteTarget |
| `rewriteTarget` | _string_ | RewriteTarget allows users to rewrite the request path before it is sent to<br/>the upstream server (for an HTTP/HTTPS upstream) or mapped to the filesystem<br/>(for a `file:` upstream).<br/>Use the Path to capture segments for reuse within the rewrite target.<br/>Eg: With a Path of `^/baz/(.*)`, a RewriteTarget of `/foo/$1` would rewrite<br/>the request `/baz/abc/123` to `/foo/abc/123` before proxying to the<br/>upstream server. Or if the upstream were `file:///app`, a request for<br/>`/baz/info.html` would return the contents of the file `/app/foo/info.html`. |
| `uri` | _string_ | The URI of the upstream server. This may be an HTTP(S) server of a File<br/>based URL. It may include a path, in which case all requests will be served<br/>under that path.<br/>Eg:<br/>- http://localhost:8080<br/>- https://service.localhost<br/>- https://service.localhost/path<br/>- file://host/path<br/>If the URI's path is "/base" and the incoming request was for "/dir",<br/>the upstream request will be for "/base/dir". |
| `insecureSkipTLSVerify` | _bool_ | InsecureSkipTLSVerify will skip TLS verification of upstream HTTPS hosts.<br/>This option is insecure and will allow potential Man-In-The-Middle attacks<br/>between OAuth2 Proxy and the upstream server.<br/>Defaults to false. |
| `static` | _bool_ | Static will make all requests to this upstream have a static response.<br/>The response will have a body of "Authenticated" and a response code<br/>matching StaticCode.<br/>If StaticCode is not set, the response will return a 200 response. |
| `staticCode` | _int_ | StaticCode determines the response code for the Static response.<br/>This option can only be used with Static enabled. |
| `flushInterval` | _[Duration](#duration)_ | FlushInterval is the period between flushing the response buffer when<br/>streaming response from the upstream.<br/>Defaults to 1 second. |
| `passHostHeader` | _bool_ | PassHostHeader determines whether the request host header should be proxied<br/>to the upstream server.<br/>Defaults to true. |
| `proxyWebSockets` | _bool_ | ProxyWebSockets enables proxying of websockets to upstream servers<br/>Defaults to true. |
| `timeout` | _[Duration](#duration)_ | Timeout is the maximum duration the server will wait for a response from the upstream server.<br/>Defaults to 30 seconds. |
| `disableKeepAlives` | _bool_ | DisableKeepAlives disables HTTP keep-alive connections to the upstream server.<br/>Defaults to false. |
### UpstreamConfig
(**Appears on:** [AlphaOptions](#alphaoptions))
UpstreamConfig is a collection of definitions for upstream servers.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `proxyRawPath` | _bool_ | ProxyRawPath will pass the raw url path to upstream allowing for urls<br/>like: "/%2F/" which would otherwise be redirected to "/" |
| `upstreams` | _[[]Upstream](#upstream)_ | Upstreams represents the configuration for the upstream servers.<br/>Requests will be proxied to this upstream if the path matches the request path. |
The alpha package supports the use of environment variables in place of yaml keys, allowing sensitive values to be pulled from somewhere other than the yaml file.
When using environment variables, your yaml will look like this:
```yaml
providers:
- provider: azure
clientSecret: ${CLIENT_SECRET}
...
```
Where CLIENT_SECRET is an environment variable.
More information and available patterns can be found [here](https://github.com/a8m/envsubst#docs)
## Removed options
The following flags/options and their respective environment variables are no
## Configuring for use with the Nginx `auth_request` directive
**This option requires `--reverse-proxy` option to be set.**
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:
This minimal configuration works for standard authentication flows. Lua/cookie handling is only needed for advanced scenarios (e.g., multi-part cookies, custom session logic). See the official ingress-nginx example: https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/.
It is recommended to use `--session-store-type=redis` when expecting large sessions/OIDC tokens (_e.g._ with MS Azure).
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=".
## Configuring for use with the Traefik (v2) `ForwardAuth` middleware
**This option requires `--reverse-proxy` option to be set.**
### ForwardAuth with 401 errors middleware
The [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) allows Traefik to authenticate requests via the oauth2-proxy's `/oauth2/auth` endpoint on every request, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the whole request through. For example, on Dynamic File (YAML) Configuration:
### ForwardAuth with static upstreams configuration
Redirect to sign_in functionality provided without the use of `errors` middleware with [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) pointing to oauth2-proxy service's `/` endpoint
**Following options need to be set on `oauth2-proxy`:**
- `--upstream=static://202`: Configures a static response for authenticated sessions
- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly
## Configuring for use with the Caddy (v2) `forward_auth` directive
The [Caddy `forward_auth` directive](https://caddyserver.com/docs/caddyfile/directives/forward_auth) allows Caddy to authenticate requests via the `oauth2-proxy`'s `/auth`.
This example is for a simple reverse proxy setup where the `/oauth2/` path is kept under the same domain and failed auth requests (401 status returned) will be caught and redirected to the `sign_in` endpoint.
**Following options need to be set on `oauth2-proxy`:**
- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly
```nginx title="Caddyfile"
example.com {
# Requests to /oauth2/* are proxied to oauth2-proxy without authentication.
# You can't use `reverse_proxy /oauth2/* oauth2-proxy.internal:4180` here because the reverse_proxy directive has lower precedence than the handle directive.
handle /oauth2/* {
reverse_proxy oauth2-proxy.internal:4180 {
# oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers.
# The reverse_proxy directive automatically sets X-Forwarded-{For,Proto,Host} headers.
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Uri {uri}
}
}
# Requests to other paths are first processed by oauth2-proxy for authentication.
handle {
forward_auth oauth2-proxy.internal:4180 {
uri /oauth2/auth
# oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers.
# The forward_auth directive automatically sets the X-Forwarded-{For,Proto,Host,Method,Uri} headers.
header_up X-Real-IP {remote_host}
# If needed, you can copy headers from the oauth2-proxy response to the request sent to the upstream.
# Make sure to configure the --set-xauthrequest flag to enable this feature.
`oauth2-proxy` can be configured via [command line options](#command-line-options), [environment variables](#environment-variables) or [config file](#config-file) (in decreasing order of precedence, i.e. command line options will overwrite environment variables and environment variables will overwrite configuration file settings).
## Generating a Cookie Secret
To generate a strong cookie secret use one of the below commands:
# Valid 32 Byte Base64 URL encoding set that will decode to 24 []byte AES-192 secret
resource "random_password" "cookie_secret" {
length = 32
override_special = "-_"
}
```
</TabItem>
</Tabs>
## Config File
Every command line argument can be specified in a config file by replacing hyphens (-) with underscores (\_). If the argument can be specified multiple times, the config option should be plural (trailing s).
An example [oauth2-proxy.cfg](https://github.com/oauth2-proxy/oauth2-proxy/blob/master/contrib/oauth2-proxy.cfg.example) config file is in the contrib directory. It can be used by specifying `--config=/etc/oauth2-proxy.cfg`
## Config Options
### Command Line Options
| Flag | Description |
| ----------- | -------------------- |
| `--config` | path to config file |
| `--version` | print version string |
### General Provider Options
Provider specific options can be found on their respective subpages.
| Flag / Config Field | Type | Description | Default |
| flag: `--allowed-group`<br/>toml: `allowed_groups` | string \| list | Restrict login to members of a group or list of groups. Furthermore, if you aren't setting the `scope` and use `allowed_groups` with the generic OIDC provider the scope `groups` gets added implicitly. | |
| flag: `--backend-logout-url`<br/>toml: `backend_logout_url` | string | URL to perform backend logout, if you use `{id_token}` in the url it will be replaced by the actual `id_token` of the user session | |
| flag: `--client-id`<br/>toml: `client_id` | string | the OAuth Client ID, e.g. `"123456.apps.googleusercontent.com"` | |
| flag: `--client-secret-file`<br/>toml: `client_secret_file` | string | the file with OAuth Client Secret | |
| flag: `--code-challenge-method`<br/>toml: `code_challenge_method` | string | use PKCE code challenges with the specified method. Either 'plain' or 'S256' (recommended) | |
| flag: `--insecure-oidc-allow-unverified-email`<br/>toml: `insecure_oidc_allow_unverified_email` | bool | don't fail if an email address in an id_token is not verified | false |
| flag: `--insecure-oidc-skip-issuer-verification`<br/>toml: `insecure_oidc_skip_issuer_verification` | bool | allow the OIDC issuer URL to differ from the expected (currently required for Azure multi-tenant compatibility) | false |
| flag: `--insecure-oidc-skip-nonce`<br/>toml: `insecure_oidc_skip_nonce` | bool | skip verifying the OIDC ID Token's nonce claim | true |
| flag: `--jwt-key-file`<br/>toml: `jwt_key_file` | string | path to the private key file in PEM format used to sign the JWT so that you can say something like `--jwt-key-file=/etc/ssl/private/jwt_signing_key.pem`: required by login.gov | |
| flag: `--jwt-key`<br/>toml: `jwt_key` | string | private key in PEM format used to sign JWT, so that you can say something like `--jwt-key="${OAUTH2_PROXY_JWT_KEY}"`: required by login.gov | |
| flag: `--auth-request-response-mode`<br/>toml: `auth-request-response-mode` | string | Response mode to ask for during authentication request | |
| flag: `--oidc-audience-claim`<br/>toml: `oidc_audience_claims` | string | which OIDC claim contains the audience | `"aud"` |
| flag: `--oidc-email-claim`<br/>toml: `oidc_email_claim` | string | which OIDC claim contains the user's email | `"email"` |
| flag: `--oidc-extra-audience`<br/>toml: `oidc_extra_audiences` | string \| list | additional audiences which are allowed to pass verification | `"[]"` |
| flag: `--oidc-groups-claim`<br/>toml: `oidc_groups_claim` | string | which OIDC claim contains the user groups | `"groups"` |
| flag: `--oidc-issuer-url`<br/>toml: `oidc_issuer_url` | string | the OpenID Connect issuer URL, e.g. `"https://accounts.google.com"` | |
| flag: `--oidc-jwks-url`<br/>toml: `oidc_jwks_url` | string | OIDC JWKS URI for token verification; required if OIDC discovery is disabled and public key files are not provided | |
| flag: `--oidc-public-key-file`<br/>toml: `oidc_public_key_files` | string | Path to public key file in PEM format to use for verifying JWT tokens (may be given multiple times). Required if OIDC discovery is disabled na JWKS URL isn't provided | string \| list |
| flag: `--prompt`<br/>toml: `prompt` | string | [OIDC prompt](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest); if present, `approval-prompt` is ignored | `""` |
| flag: `--provider-ca-file`<br/>toml: `provider_ca_files` | string \| list | Paths to CA certificates that should be used when connecting to the provider. If not specified, the default Go trust sources are used instead. |
| flag: `--provider-display-name`<br/>toml: `provider_display_name` | string | Override the provider's name with the given string; used for the sign-in page | (depends on provider) |
| flag: `--scope`<br/>toml:`scope` | string | OAuth scope specification. Every provider has a default list of scopes which will be used in case no scope is configured. | |
| flag: `--skip-claims-from-profile-url`<br/>toml: `skip_claims_from_profile_url` | bool | skip request to Profile URL for resolving claims not present in id_token | false |
| flag: `--skip-oidc-discovery`<br/>toml: `skip_oidc_discovery` | bool | bypass OIDC endpoint discovery. `--login-url`, `--redeem-url` and `--oidc-jwks-url` must be configured in this case | false |
| flag: `--use-system-trust-store`<br/>toml: `use_system_trust_store` | bool | Determines if `provider-ca-file` files and the system trust store are used. If set to true, your custom CA files and the system trust store are used otherwise only your custom CA files. | false |
| flag: `--cookie-csrf-per-request`<br/>toml:`cookie_csrf_per_request` | bool | Enable having different CSRF cookies per request, making it possible to have parallel requests. | false |
| flag: `--cookie-csrf-per-request-limit`<br/>toml: `cookie_csrf_per_request_limit` | int | Sets a limit on the number of CSRF requests cookies that oauth2-proxy will create. The oldest cookie will be removed. Useful if users end up with 431 Request headers too large status codes. Only effective if --cookie-csrf-per-request is true | "infinite" |
| flag: `--cookie-domain`<br/>toml: `cookie_domains` | string \| list | Optional cookie domains to force cookies to (e.g. `.yourcompany.com`). The longest domain matching the request's host will be used (or the shortest cookie domain if there is no match). | |
| flag: `--cookie-expire`<br/>toml: `cookie_expire` | duration | expire timeframe for cookie. If set to 0, cookie becomes a session-cookie which will expire when the browser is closed. | 168h0m0s |
| flag: `--cookie-httponly`<br/>toml: `cookie_httponly` | bool | set HttpOnly cookie flag | true |
| flag: `--cookie-name`<br/>toml: `cookie_name` | string | the name of the cookie that the oauth_proxy creates. Should be changed to use a [cookie prefix](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#cookie_prefixes) (`__Host-` or `__Secure-`) if `--cookie-secure` is set. | `"_oauth2_proxy"` |
| flag: `--cookie-path`<br/>toml: `cookie_path` | string | an optional cookie path to force cookies to (e.g. `/poc/`) | `"/"` |
| flag: `--cookie-refresh`<br/>toml: `cookie_refresh` | duration | refresh the cookie after this duration; `0` to disable; not supported by all providers [^1] | |
| flag: `--cookie-samesite`<br/>toml: `cookie_samesite` | string | set SameSite cookie attribute (`"lax"`, `"strict"`, `"none"`, or `""`). | `""` |
| flag: `--cookie-secret`<br/>toml: `cookie_secret` | string | the seed string for secure cookies (optionally base64 encoded) | |
| flag: `--cookie-secret-file`<br/>toml: `cookie_secret_file` | string | For defining a separate cookie secret file to read the encryption key from | |
[^1]: The following providers support `--cookie-refresh`: ADFS, Azure, GitLab, Google, Keycloak and all other Identity Providers which support the full [OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens)
### Header Options
| Flag / Config Field | Type | Description | Default |
| flag: `--basic-auth-password`<br/>toml: `basic_auth_password` | string | the password to set when passing the HTTP Basic Auth header | |
| flag: `--set-xauthrequest`<br/>toml: `set_xauthrequest` | bool | set X-Auth-Request-User, X-Auth-Request-Groups, X-Auth-Request-Email and X-Auth-Request-Preferred-Username response headers (useful in Nginx auth_request mode). When used with `--pass-access-token`, X-Auth-Request-Access-Token is added to response headers. | false |
| flag: `--set-authorization-header`<br/>toml: `set_authorization_header` | bool | set Authorization Bearer response header (useful in Nginx auth_request mode) | false |
| flag: `--set-basic-auth`<br/>toml: `set_basic_auth` | bool | set HTTP Basic Auth information in response (useful in Nginx auth_request mode) | false |
| flag: `--skip-auth-strip-headers`<br/>toml: `skip_auth_strip_headers` | bool | strips `X-Forwarded-*` style authentication headers &`Authorization` header if they would be set by oauth2-proxy | true |
| flag: `--pass-access-token`<br/>toml: `pass_access_token` | bool | pass OAuth access_token to upstream via X-Forwarded-Access-Token header. When used with `--set-xauthrequest` this adds the X-Auth-Request-Access-Token header to the response | false |
| flag: `--pass-authorization-header`<br/>toml: `pass_authorization_header` | bool | pass OIDC IDToken to upstream via Authorization Bearer header | false |
| flag: `--pass-basic-auth`<br/>toml: `pass_basic_auth` | bool | pass HTTP Basic Auth, X-Forwarded-User, X-Forwarded-Email and X-Forwarded-Preferred-Username information to upstream | true |
| flag: `--prefer-email-to-user`<br/>toml: `prefer_email_to_user` | bool | Prefer to use the Email address as the Username when passing information to upstream. Will only use Username if Email is unavailable, e.g. htaccess authentication. Used in conjunction with `--pass-basic-auth` and `--pass-user-headers` | false |
| flag: `--pass-user-headers`<br/>toml: `pass_user_headers` | bool | pass X-Forwarded-User, X-Forwarded-Groups, X-Forwarded-Email and X-Forwarded-Preferred-Username information to upstream | true |
### Logging Options
| Flag / Config Field | Type | Description | Default |
| flag: `--errors-to-info-log`<br/>toml: `errors_to_info_log` | bool | redirects error-level logging to default log channel instead of stderr | false |
| flag: `--exclude-logging-path`<br/>toml: `exclude_logging_paths` | string | comma separated list of paths to exclude from logging, e.g. `"/ping,/path2"` | `""` (no paths excluded) |
| flag: `--logging-compress`<br/>toml: `logging_compress` | bool | Should rotated log files be compressed using gzip | false |
| flag: `--logging-filename`<br/>toml: `logging_filename` | string | File to log requests to, empty for `stdout` | `""` (stdout) |
| flag: `--logging-local-time`<br/>toml: `logging_local_time` | bool | Use local time in log files and backup filenames instead of UTC | true (local time) |
| flag: `--logging-max-age`<br/>toml: `logging_max_age` | int | Maximum number of days to retain old log files | 7 |
| flag: `--logging-max-backups`<br/>toml: `logging_max_backups` | int | Maximum number of old log files to retain; 0 to disable | 0 |
| flag: `--logging-max-size`<br/>toml: `logging_max_size` | int | Maximum size in megabytes of the log file before rotation | 100 |
| flag: `--request-id-header`<br/>toml: `request_id_header` | string | Request header to use as the request ID in logging | X-Request-Id |
| flag: `--request-logging-format`<br/>toml: `request_logging_format` | string | Template for request log lines | see [Logging Configuration](#logging-configuration) |
| flag: `--banner`<br/>toml: `banner` | string | custom (html) banner string. Use `"-"` to disable default banner. | |
| flag: `--custom-sign-in-logo`<br/>toml: `custom_sign_in_logo` | string | path or a URL to an custom image for the sign_in page logo. Use `"-"` to disable default logo. |
| flag: `--custom-templates-dir`<br/>toml: `custom_templates_dir` | string | path to custom html templates | |
| flag: `--display-htpasswd-form`<br/>toml: `display_htpasswd_form` | bool | display username / password login form if an htpasswd file is provided | true |
| flag: `--footer`<br/>toml: `footer` | string | custom (html) footer string. Use `"-"` to disable default footer. (Can be used to obfuscate the version) | |
| flag: `--show-debug-on-error`<br/>toml: `show_debug_on_error` | bool | show detailed error information on error pages (WARNING: this may contain sensitive information - do not use in production) | false |
### Probe Options
| Flag / Config Field | Type | Description | Default |
| flag: `--ping-path`<br/>toml: `ping_path` | string | the ping endpoint that can be used for basic health checks | `"/ping"` |
| flag: `--ping-user-agent`<br/>toml: `ping_user_agent` | string | a User-Agent that can be used for basic health checks | `""` (don't check user agent) |
| flag: `--ready-path`<br/>toml: `ready_path` | string | the ready endpoint that can be used for deep health checks | `"/ready"` |
| 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` |
| flag: `--api-route`<br/>toml: `api_routes` | string \| list | Requests to these paths must already be authenticated with a cookie, or a JWT if `--skip-jwt-bearer-tokens` is set. No redirect to login will be done. Return 401 if not. Format: path_regex | |
| flag: `--authenticated-emails-file`<br/>toml: `authenticated_emails_file` | string | authenticate against emails via file (one per line) | |
| flag: `--bearer-token-login-fallback`<br/>toml: `bearer_token_login_fallback` | bool | if `--skip-jwt-bearer-tokens` is set, if a request includes an invalid JWT (expired, malformed, missing required audiences, etc), fall back to normal login redirect as if the token were not sent at all. If false, respond 403 | true |
| flag: `--email-domain`<br/>toml: `email_domains` | string \| list | authenticate emails with the specified domain (may be given multiple times). Use `*` to authenticate any email | |
| flag: `--encode-state`<br/>toml: `encode_state` | bool | encode the state parameter as UrlEncodedBase64 | false |
| flag: `--extra-jwt-issuers`<br/>toml: `extra_jwt_issuers` | string | if `--skip-jwt-bearer-tokens` is set, a list of extra JWT `issuer=audience` (see a token's `iss`, `aud` fields) pairs (where the issuer URL has a `.well-known/openid-configuration` or a `.well-known/jwks.json`) | |
| flag: `--force-json-errors`<br/>toml: `force_json_errors` | bool | force JSON errors instead of HTTP error pages or redirects | `false` |
| 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: `--redirect-url`<br/>toml: `redirect_url` | string | the OAuth Redirect URL, e.g. `"https://internalapp.yourcompany.com/oauth2/callback"` | |
| 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: `--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-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: `--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:*`.
### Server Options
| Flag / Config Field | Type | Description | Default |
| flag: `--http-address`<br/>toml: `http_address` | string | `[http://]<addr>:<port>` or `unix://<path>` or `fd:<int>` (case insensitive) to listen on for HTTP clients. Square brackets are required for ipv6 address, e.g. `http://[::1]:4180` | `"127.0.0.1:4180"` |
| flag: `--https-address`<br/>toml: `https_address` | string | `[https://]<addr>:<port>` to listen on for HTTPS clients. Square brackets are required for ipv6 address, e.g. `https://[::1]:443` | `":443"` |
| flag: `--metrics-address`<br/>toml: `metrics_address` | string | the address prometheus metrics will be scraped from | `""` |
| flag: `--metrics-secure-address`<br/>toml: `metrics_secure_address` | string | the address prometheus metrics will be scraped from if using HTTPS | `""` |
| flag: `--metrics-tls-cert-file`<br/>toml: `metrics_tls_cert_file` | string | path to certificate file for secure metrics server | `""` |
| flag: `--metrics-tls-key-file`<br/>toml: `metrics_tls_key_file` | string | path to private key file for secure metrics server | `""` |
| flag: `--tls-cipher-suite`<br/>toml: `tls_cipher_suites` | string \| list | Restricts TLS cipher suites used by server to those listed (e.g. TLS_RSA_WITH_RC4_128_SHA) (may be given multiple times). If not specified, the default Go safe cipher list is used. List of valid cipher suites can be found in the [crypto/tls documentation](https://pkg.go.dev/crypto/tls#pkg-constants). | |
| flag: `--tls-min-version`<br/>toml: `tls_min_version` | string | minimum TLS version that is acceptable, either `"TLS1.2"` or `"TLS1.3"` | `"TLS1.2"` |
### Session Options
| Flag / Config Field | Type | Description | Default |
| flag: `--session-cookie-minimal`<br/>toml: `session_cookie_minimal` | bool | strip OAuth tokens from cookie session stores if they aren't needed (cookie session store only) | false |
| flag: `--session-store-type`<br/>toml: `session_store_type` | string | [Session data storage backend](sessions.md); redis or cookie | cookie |
| flag: `--redis-cluster-connection-urls`<br/>toml: `redis_cluster_connection_urls` | string \| list | List of Redis cluster connection URLs (e.g. `redis://HOST[:PORT]`). Used in conjunction with `--redis-use-cluster` | |
| flag: `--redis-connection-url`<br/>toml: `redis_connection_url` | string | URL of redis server for redis session storage (e.g. `redis://HOST[:PORT]`) | |
| flag: `--redis-insecure-skip-tls-verify`<br/>toml: `redis_insecure_skip_tls_verify` | bool | skip TLS verification when connecting to Redis | false |
| flag: `--redis-password`<br/>toml: `redis_password` | string | Redis password. Applicable for all Redis configurations. Will override any password set in `--redis-connection-url` | |
| flag: `--redis-sentinel-password`<br/>toml: `redis_sentinel_password` | string | Redis sentinel password. Used only for sentinel connection; any redis node passwords need to use `--redis-password` | |
| flag: `--redis-sentinel-master-name`<br/>toml: `redis_sentinel_master_name` | string | Redis sentinel master name. Used in conjunction with `--redis-use-sentinel` | |
| flag: `--redis-sentinel-connection-urls`<br/>toml: `redis_sentinel_connection_urls` | string \| list | List of Redis sentinel connection URLs (e.g. `redis://HOST[:PORT]`). Used in conjunction with `--redis-use-sentinel` | |
| flag: `--redis-use-cluster`<br/>toml: `redis_use_cluster` | bool | Connect to redis cluster. Must set `--redis-cluster-connection-urls` to use this feature | false |
| flag: `--redis-use-sentinel`<br/>toml: `redis_use_sentinel` | bool | Connect to redis via sentinels. Must set `--redis-sentinel-master-name` and `--redis-sentinel-connection-urls` to use this feature | false |
| flag: `--redis-connection-idle-timeout`<br/>toml: `redis_connection_idle_timeout` | int | Redis connection idle timeout seconds. If Redis [timeout](https://redis.io/docs/reference/clients/#client-timeouts) option is set to non-zero, the `--redis-connection-idle-timeout` must be less than Redis timeout option. Example: if either redis.conf includes `timeout 15` or using `CONFIG SET timeout 15` the `--redis-connection-idle-timeout` must be at least `--redis-connection-idle-timeout=14` | 0 |
### Upstream Options
| Flag / Config Field | Type | Description | Default |
| flag: `--ssl-upstream-insecure-skip-verify`<br/>toml: `ssl_upstream_insecure_skip_verify` | bool | skip validation of certificates presented when using HTTPS upstreams | false |
| flag: `--disable-keep-alives`<br/>toml: `disable_keep_alives` | bool | disable HTTP keep-alive connections to the upstream server | false |
| 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 | |
## Upstreams Configuration
`oauth2-proxy` supports having multiple upstreams, and has the option to pass requests on to HTTP(S) servers, unix socket or serve static files from the file system.
To configure **HTTP and HTTPS upstreams**, provide such a URL in `--upstream=URL`. The scheme+host portion and the path portion are extracted to configure proxying behavior. When processing incoming requests, the path portion becomes a lookup key for selecting the destination server of the proxied request.
* Upstream URLs *without a trailing slash,* like in `--upstream=http://service2.internal/foo`, will match an incoming request exactly to `/foo` in `https://this.o2p.example.com/foo`, and forward the request on to service2.internal, but not match a request to `https://this.o2p.example.com/foo/more` nor ...`.com/food`.
* Upstream URLs *with a trailing slash,* like in `--upstream=http://service1.internal/foo/`, will match any incoming request to any incoming requests's path *starting with*`/foo/`, like `/foo/` and `/foo/more` and `/foo/lots/more?etc`.
If multiple `--upstream` URLs' paths match an incoming request, the one with the longest matching path (the most specific match) takes priority over shorter (less specific) ones.
**Unix socket upstreams** are configured as `unix:///path/to/unix.sock`.
**Static file paths** are configured as a file:// URL. `file:///var/www/static/` will serve the files from that directory at `http://[oauth2-proxy url]/var/www/static/`, which may not be what you want. You can provide the path to where the files should be available by adding a fragment to the configured URL. The value of the fragment will then be used to specify which path the files are available at, e.g. `file:///var/www/static/#/static/` will make `/var/www/static/` available at `http://[oauth2-proxy url]/static/`.
Multiple upstreams can either be configured by supplying a comma separated list to the `--upstream` parameter, supplying the parameter multiple times or providing a list in the [config file](#config-file). When multiple upstreams are used routing to them will be based on the path they are set up with.
## Environment variables
Every command line argument can be specified as an environment variable by
prefixing it with `OAUTH2_PROXY_`, capitalising it, and replacing hyphens (`-`)
with underscores (`_`). If the argument can be specified multiple times, the
environment variable should be plural (trailing `S`).
This is particularly useful for storing secrets outside a configuration file
or the command line.
For example, the `--cookie-secret` flag becomes `OAUTH2_PROXY_COOKIE_SECRET`.
If a flag has the type `string | list` like the `--email-domain` flag it is
available as an environment variable in plural form e.g. `OAUTH2_PROXY_EMAIL_DOMAINS`
Values for type `string | list` usually have a plural environment variable name
Please check the type for each [config option](#config-options) first.
## Logging Configuration
By default, OAuth2 Proxy logs all output to stdout. Logging can be configured to output to a rotating log file using the `--logging-filename` command.
If logging to a file you can also configure the maximum file size (`--logging-max-size`), age (`--logging-max-age`), max backup logs (`--logging-max-backups`), and if backup logs should be compressed (`--logging-compress`).
There are three different types of logging: standard, authentication, and HTTP requests. These can each be enabled or disabled with `--standard-logging`, `--auth-logging`, and `--request-logging`.
Each type of logging has its own configurable format and variables. By default, these formats are similar to the Apache Combined Log.
Logging of requests to the `/ping` endpoint (or using `--ping-user-agent`) and the `/ready` endpoint can be disabled with `--silence-ping-logging` reducing log volume.
## 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:
| Client | 74.125.224.72 | The client/remote IP address. Will use the X-Real-IP header it if exists & reverse-proxy is set to true. |
| Host | domain.com | The value of the Host header. |
| Protocol | HTTP/1.0 | The request protocol. |
| RequestDuration | 0.001 | The time in seconds that a request took to process. |
| RequestID | 00010203-0405-4607-8809-0a0b0c0d0e0f | The request ID pulled from the `--request-id-header`. Random UUID if empty |
| RequestMethod | GET | The request method. |
| RequestURI | "/oauth2/auth" | The URI path of the request. |
| ResponseSize | 12 | The size in bytes of the response. |
| StatusCode | 200 | The HTTP status code of the response. |
| Timestamp | 2015/03/19 17:20:19 | The date and time of the logging event. |
| Upstream | - | The upstream data of the HTTP request. |
| UserAgent | - | The full user agent as reported by the requesting client. |
| Username | username@email.com | The email or username of the auth request. |
## Standard Log Format
All other logging that is not covered by the above two types of logging will be output in this standard logging format. This includes configuration information at startup and errors that occur outside of a session. The default format is below:
```
[2015/03/19 17:20:19] [main.go:40] <MESSAGE>
```
If you require a different format than that, you can configure it with the `--standard-logging-format` flag. The default format is configured as follows:
| `--github-org` | `github_org` | string | restrict logins to members of this organisation | |
| `--github-team` | `github_team` | string | restrict logins to members of any of these teams (slug) or (org:team), comma separated | |
| `--github-repo` | `github_repo` | string | restrict logins to collaborators of this repository formatted as `orgname/repo` | |
| `--github-token` | `github_token` | string | the token to use when verifying repository collaborators (must have push access to the repository) | |
| `--github-user` | `github_users` | string \| list | To allow users to login by username even if they do not belong to the specified org and team or collaborators | |
## Usage
1. Create a new project: https://github.com/settings/developers
2. Under `Authorization callback URL` enter the correct url ie `https://internal.yourcompany.com/oauth2/callback`
The GitHub auth provider supports two additional ways to restrict authentication to either organization and optional
team level access, or to collaborators of a repository. Restricting by these options is normally accompanied with `--email-domain=*`. Additionally, all the organizations and teams a user belongs to are set as part of the `X-Forwarded-Groups` header. e.g. `org1:team1,org1:team2,org2:team1`
NOTE: When `--github-user` is set, the specified users are allowed to log in even if they do not belong to the specified
org and team or collaborators.
To restrict access to your organization:
```shell
# restrict logins to members of this organisation
--github-org="your-org"
```
To restrict access to specific teams within an organization:
```shell
--github-org="your-org"
# restrict logins to members of any of these teams (slug), comma separated
--github-team="team1,team2,team3"
```
To restrict to teams within different organizations, keep the organization flag empty and use `--github-team` like so:
```shell
# keep empty
--github-org=""
# restrict logins to members to any of the following teams (format <org>:<slug>, like octo:team1), comma separated
| `--gitlab-group` | `gitlab_groups` | string \| list | restrict logins to members of any of these groups (slug), separated by a comma | |
| `--gitlab-projects` | `gitlab_projects` | string \| list | restrict logins to members of any of these projects (may be given multiple times) formatted as `orgname/repo=accesslevel`. Access level should be a value matching [Gitlab access levels](https://docs.gitlab.com/ee/api/members.html#valid-access-levels), defaulted to 20 if absent | |
## Usage
This auth provider has been tested against Gitlab version 12.X. Due to Gitlab API changes, it may not work for version
prior to 12.X (see [994](https://github.com/oauth2-proxy/oauth2-proxy/issues/994)).
Whether you are using GitLab.com or self-hosting GitLab, follow
[these steps to add an application](https://docs.gitlab.com/integration/oauth_provider/). Make sure to enable at
least the `openid`, `profile` and `email` scopes, and set the redirect url to your application url e.g.
https://myapp.com/oauth2/callback.
If you need projects filtering, add the extra `read_api` scope to your application.
The following config should be set to ensure that the oauth will work properly. To get a cookie secret follow
| `--google-admin-email` | `google_admin_email` | string | the google admin to impersonate for api calls | |
| `--google-group` | `google_groups` | string | restrict logins to members of this google group (may be given multiple times). If not specified and service account or default credentials are configured, all user groups will be allowed. | |
| `--google-service-account-json` | `google_service_account_json` | string | the path to the service account json credentials | |
| `--google-use-application-default-credentials` | `google_use_application_default_credentials` | bool | use application default credentials instead of service account json (i.e. GKE Workload Identity) | |
| `--google-target-principal` | `google_target_principal` | bool | the target principal to impersonate when using ADC | defaults to the service account configured for ADC |
## Usage
For Google, the registration steps are:
1. Create a new project: https://console.developers.google.com/project
2. Choose the new project from the top right project dropdown (only if another project is selected)
3. In the project Dashboard center pane, choose **"APIs & Services"**
4. In the left Nav pane, choose **"Credentials"**
5. In the center pane, choose **"OAuth consent screen"** tab. Fill in **"Product name shown to users"** and hit save.
6. In the center pane, choose **"Credentials"** tab.
- Open the **"New credentials"** drop down
- Choose **"OAuth client ID"**
- Choose **"Web application"**
- Application name is freeform, choose something appropriate
- Authorized JavaScript origins is your domain ex: `https://internal.yourcompany.com`
- Authorized redirect URIs is the location of oauth2/callback ex: `https://internal.yourcompany.com/oauth2/callback`
- Choose **"Create"**
7. Take note of the **Client ID** and **Client Secret**
It's recommended to refresh sessions on a short interval (1h) with `cookie-refresh` setting which validates that the
account is still authorized.
#### Restrict auth to specific Google groups on your domain. (optional)
1. Create a [service account](https://developers.google.com/identity/protocols/oauth2/service-account) and configure it
to use [Application Default Credentials / Workload Identity / Workload Identity Federation (recommended)](#using-application-default-credentials-adc--workload-identity--workload-identity-federation-recommended) or,
alternatively download the JSON.
2. Make note of the Client ID for a future step.
3. Under "APIs & Auth", choose APIs.
4. Click on Admin SDK and then Enable API.
5. Follow the steps on [Set up domain-wide delegation for a service account](https://developers.google.com/workspace/guides/create-credentials#optional_set_up_domain-wide_delegation_for_a_service_account)
and give the client id from step 2 the following oauth scopes:
oauth2-proxy can make use of [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials).
When deployed within GCP, this means that it can automatically use the service account attached to the resource. When deployed to GKE, ADC
can be leveraged through a feature called Workload Identity. Follow Google's [guide](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
to set up Workload Identity.
When deployed outside of GCP, [Workload Identity Federation](https://cloud.google.com/docs/authentication/provide-credentials-adc#wlif) might be an option.
You will need to register an OAuth application with a Provider (Google, GitHub or another provider), and configure it
with Redirect URI(s) for the domain you intend to run `oauth2-proxy` on.
Valid providers are :
- [ADFS](adfs.md)
- [Bitbucket](bitbucket.md)
- [Cidaas](cidaas.md)
- [DigitalOcean](digitalocean.md)
- [Facebook](facebook.md)
- [Gitea](gitea.md)
- [GitHub](github.md)
- [GitLab](gitlab.md)
- [Google](google.md) _default_
- [Keycloak](keycloak.md) (Deprecated)
- [Keycloak OIDC](keycloak_oidc.md)
- [LinkedIn](linkedin.md)
- [login.gov](login_gov.md)
- [Microsoft Azure](ms_azure_ad.md) (Deprecated)
- [Microsoft Entra ID](ms_entra_id.md)
- [Nextcloud](nextcloud.md)
- [OpenID Connect](openid_connect.md)
- [SourceHut](sourcehut.md)
The provider can be selected using the `provider` configuration value, or set in the [`providers` array using AlphaConfig](https://oauth2-proxy.github.io/oauth2-proxy/configuration/alpha-config#providers). However, [**the feature to implement multiple providers is not complete**](https://github.com/oauth2-proxy/oauth2-proxy/issues/926).
Please note that not all providers support all claims. The `preferred_username` claim is currently only supported by the
OpenID Connect provider.
## Email Authentication
To authorize a specific email-domain use `--email-domain=yourcompany.com`. To authorize individual email addresses use
`--authenticated-emails-file=/path/to/file` with one email per line. To authorize all email addresses use `--email-domain=*`.
## Adding a new Provider
Follow the examples in the [`providers` package](https://github.com/oauth2-proxy/oauth2-proxy/blob/master/providers/) to define a new
`Provider` instance. Add a new `case` to
[`providers.New()`](https://github.com/oauth2-proxy/oauth2-proxy/blob/master/providers/providers.go) to allow `oauth2-proxy` to use the
This is the legacy and deprecated provider for Keycloak, use [Keycloak OIDC Auth Provider](keycloak_oidc.md) if possible.
:::
1. Create new client in your Keycloak realm with **Access Type** 'confidential' and **Valid Redirect URIs** 'https://internal.yourcompany.com/oauth2/callback'
2. Take note of the Secret in the credential tab of the client
3. Create a mapper with **Mapper Type** 'Group Membership' and **Token Claim Name** 'groups'.
Make sure you set the following to the appropriate url:
| `--allowed-role` | `allowed_roles` | string \| list | restrict logins to users with this role (may be given multiple times). Only works with the keycloak-oidc provider. | |
| `--entra-id-allowed-tenant` | `entra_id_allowed_tenants` | string \| list | List of allowed tenants. In case of multi-tenant apps, incoming tokens are issued by different issuers and OIDC issuer verification needs to be disabled. When not specified, all tenants are allowed. Redundant for single-tenant apps (regular ID token validation matches the issuer). | |
| `--entra-id-federated-token-auth` | `entra_id_federated_token_auth` | boolean | Enable oAuth2 client authentication with federated token projected by Entra Workload Identity plugin, instead of client secret. | false |
## Configure App registration
To begin, create an App registration, set a redirect URI, and generate a secret. All account types are supported, including single-tenant, multi-tenant, multi-tenant with Microsoft accounts, and Microsoft accounts only.
For single-tenant and multi-tenant apps without groups, the only required scope is `openid` (See: [Scopes and permissions](https://learn.microsoft.com/en-us/entra/identity-platform/scopes-oidc#the-openid-scope)).
To make use of groups - for example use `allowed_groups` setting or authorize based on groups inside your service - you need to enable *groups claims* in the App Registration. When enabled, list of groups is present in the issued ID token. No additional scopes are required besides `openid`. This works up to 200 groups.
When user has more than 200 group memberships, OAuth2-Proxy attempts to retrieve the complete list from Microsoft Graph API's [`transitiveMemberOf`](https://learn.microsoft.com/en-us/graph/api/user-list-transitivememberof). Endpoint requires `User.Read` scope (delegated permission). This permission can be by default consented by user during first login. Set scope to `openid User.Read` to request user consent. Without proper scope, user with 200+ groups will authenticate with 0 groups. See: [group overages](https://learn.microsoft.com/en-us/security/zero-trust/develop/configure-tokens-group-claims-app-roles#group-overages).
Alternatively to user consent, both `openid` and `User.Read` permissions can be consented by admistrator. Then, user is not asked for consent on the first login, and group overage works with `openid` scope only. Admin consent can also be required for some tenants. It can be granted with [azuread_service_principal_delegated_permission_grant](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/service_principal_delegated_permission_grant) terraform resource.
For personal microsoft accounts, required scope is `openid profile email`.
See: [Overview of permissions and consent in the Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/permissions-consent-overview).
### Multi-tenant apps
To authenticate apps from multiple tenants (including personal Microsoft accounts), set the common OIDC issuer url and disable verification:
`insecure_oidc_skip_issuer_verification` setting is required to disable following checks:
* Startup check for matching issuer URL returned from [discovery document](https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration) with `oidc_issuer_url` setting. Required, as document's `issuer` field doesn't equal to `https://login.microsoftonline.com/common/v2.0`. See [OIDC Discovery 4.3](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation).
* Matching ID token's `issuer` claim with `oidc_issuer_url` setting during ID token validation. Required to support tokens issued by different tenants. See [OIDC Core 3.1.3.7](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation).
To provide additional security, Entra ID provider performs check on the ID token's `issuer` claim to match the `https://login.microsoftonline.com/{tenant-id}/v2.0` template.
### Workload Identity
Provider supports authentication with federated token, without need of using client secret. Following conditions have to be met:
* Cluster has public OIDC provider URL. For major cloud providers, it can be enabled with a single flag, for example for [Azure Kubernetes Service deployed with Terraform](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster), it's `oidc_issuer_enabled`.
* Workload Identity admission webhook is deployed on the cluster. For AKS, it can be enabled with a flag (`workload_identity_enabled` in Terraform resource), for clusters outside of Azure, it can be installed from [helm chart](https://github.com/Azure/azure-workload-identity).
* Appropriate federated credential is added to application registration.
application_id = azuread_application.application.id # ID of your application
display_name = "federation-cred"
description = "Workload identity for oauth2-proxy"
audiences = ["api://AzureADTokenExchange"] # Fixed value
issuer = "https://cluster-oidc-issuer-url..."
subject = "system:serviceaccount:oauth2-proxy-namespace-name:oauth2-proxy-sa-name" # set proper NS and SA name
}
```
</details>
* Kubernetes service account associated with oauth2-proxy deployment, is annotated with `azure.workload.identity/client-id: <app-registration-client-id>`
* oauth2-proxy pod is labeled with `azure.workload.identity/use: "true"`
* oauth2-proxy is configured with `entra_id_federated_token_auth` set to `true`.
`client_secret` setting can be omitted when using federated token authentication.