Feature: Allowing relative redirect url though an option

This commit is contained in:
Leandro Lafin 2024-07-12 11:04:23 -03:00
parent 896c679146
commit 7ca3ec6357
No known key found for this signature in database
GPG Key ID: 60C427B9DF40CB72
5 changed files with 102 additions and 10 deletions

View File

@ -13,6 +13,7 @@
- [#2128](https://github.com/oauth2-proxy/oauth2-proxy/pull/2128) Update dependencies (@vllvll) - [#2128](https://github.com/oauth2-proxy/oauth2-proxy/pull/2128) Update dependencies (@vllvll)
- [#2274](https://github.com/oauth2-proxy/oauth2-proxy/pull/2274) Upgrade golang.org/x/net to v0.17.0 (@pierluigilenoci) - [#2274](https://github.com/oauth2-proxy/oauth2-proxy/pull/2274) Upgrade golang.org/x/net to v0.17.0 (@pierluigilenoci)
- [#2282](https://github.com/oauth2-proxy/oauth2-proxy/pull/2282) Fixed checking Google Groups membership using Google Application Credentials (@kvanzuijlen) - [#2282](https://github.com/oauth2-proxy/oauth2-proxy/pull/2282) Fixed checking Google Groups membership using Google Application Credentials (@kvanzuijlen)
- [#2183](https://github.com/oauth2-proxy/oauth2-proxy/pull/2183) Allowing relative redirect url though an option
## Release Highlights ## Release Highlights
- 🐛 Several bugs have been squashed - 🐛 Several bugs have been squashed

View File

@ -164,6 +164,7 @@ An example [oauth2-proxy.cfg](https://github.com/oauth2-proxy/oauth2-proxy/blob/
| `--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, or X-ProxyUser-IP) | X-Real-IP | | `--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, or X-ProxyUser-IP) | X-Real-IP |
| `--redeem-url` | string | Token redemption endpoint | | | `--redeem-url` | string | Token redemption endpoint | |
| `--redirect-url` | string | the OAuth Redirect URL, e.g. `"https://internalapp.yourcompany.com/oauth2/callback"` | | | `--redirect-url` | string | the OAuth Redirect URL, e.g. `"https://internalapp.yourcompany.com/oauth2/callback"` | |
| `--relative-redirect-url` | bool | allow relative OAuth Redirect URL.` | |
| `--redis-cluster-connection-urls` | string \| list | List of Redis cluster connection URLs (e.g. `redis://HOST[:PORT]`). Used in conjunction with `--redis-use-cluster` | | | `--redis-cluster-connection-urls` | string \| list | List of Redis cluster connection URLs (e.g. `redis://HOST[:PORT]`). Used in conjunction with `--redis-use-cluster` | |
| `--redis-connection-url` | string | URL of redis server for redis session storage (e.g. `redis://HOST[:PORT]`) | | | `--redis-connection-url` | string | URL of redis server for redis session storage (e.g. `redis://HOST[:PORT]`) | |
| `--redis-insecure-skip-tls-verify` | bool | skip TLS verification when connecting to Redis | false | | `--redis-insecure-skip-tls-verify` | bool | skip TLS verification when connecting to Redis | false |

View File

@ -87,6 +87,7 @@ type OAuthProxy struct {
allowedRoutes []allowedRoute allowedRoutes []allowedRoute
apiRoutes []apiRoute apiRoutes []apiRoute
redirectURL *url.URL // the url to receive requests at redirectURL *url.URL // the url to receive requests at
relativeRedirectURL bool
whitelistDomains []string whitelistDomains []string
provider providers.Provider provider providers.Provider
sessionStore sessionsapi.SessionStore sessionStore sessionsapi.SessionStore
@ -230,6 +231,7 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
provider: provider, provider: provider,
sessionStore: sessionStore, sessionStore: sessionStore,
redirectURL: redirectURL, redirectURL: redirectURL,
relativeRedirectURL: opts.RelativeRedirectURL,
apiRoutes: apiRoutes, apiRoutes: apiRoutes,
allowedRoutes: allowedRoutes, allowedRoutes: allowedRoutes,
whitelistDomains: opts.WhitelistDomains, whitelistDomains: opts.WhitelistDomains,
@ -1045,7 +1047,7 @@ func prepareNoCacheMiddleware(next http.Handler) http.Handler {
// This is usually the OAuthProxy callback URL. // This is usually the OAuthProxy callback URL.
func (p *OAuthProxy) getOAuthRedirectURI(req *http.Request) string { func (p *OAuthProxy) getOAuthRedirectURI(req *http.Request) string {
// if `p.redirectURL` already has a host, return it // if `p.redirectURL` already has a host, return it
if p.redirectURL.Host != "" { if p.relativeRedirectURL || p.redirectURL.Host != "" {
return p.redirectURL.String() return p.redirectURL.String()
} }

View File

@ -3256,3 +3256,90 @@ func TestAuthOnlyAllowedEmails(t *testing.T) {
}) })
} }
} }
func TestGetOAuthRedirectURI(t *testing.T) {
tests := []struct {
name string
setupOpts func(*options.Options) *options.Options
req *http.Request
want string
}{
{
name: "redirect with https schema",
setupOpts: func(baseOpts *options.Options) *options.Options {
return baseOpts
},
req: &http.Request{
Host: "example",
URL: &url.URL{
Scheme: schemeHTTPS,
},
},
want: "https://example/oauth2/callback",
},
{
name: "redirect with http schema",
setupOpts: func(baseOpts *options.Options) *options.Options {
baseOpts.Cookie.Secure = false
return baseOpts
},
req: &http.Request{
Host: "example",
URL: &url.URL{
Scheme: schemeHTTP,
},
},
want: "http://example/oauth2/callback",
},
{
name: "relative redirect url",
setupOpts: func(baseOpts *options.Options) *options.Options {
baseOpts.RelativeRedirectURL = true
return baseOpts
},
req: &http.Request{},
want: "/oauth2/callback",
},
{
name: "proxy prefix",
setupOpts: func(baseOpts *options.Options) *options.Options {
baseOpts.ProxyPrefix = "/prefix"
return baseOpts
},
req: &http.Request{
Host: "example",
URL: &url.URL{
Scheme: schemeHTTP,
},
},
want: "https://example/prefix/callback",
},
{
name: "proxy prefix with relative redirect",
setupOpts: func(baseOpts *options.Options) *options.Options {
baseOpts.ProxyPrefix = "/prefix"
baseOpts.RelativeRedirectURL = true
return baseOpts
},
req: &http.Request{
Host: "example",
URL: &url.URL{
Scheme: schemeHTTP,
},
},
want: "/prefix/callback",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
baseOpts := baseTestOptions()
err := validation.Validate(baseOpts)
assert.NoError(t, err)
proxy, err := NewOAuthProxy(tt.setupOpts(baseOpts), func(string) bool { return true })
assert.NoError(t, err)
assert.Equalf(t, tt.want, proxy.getOAuthRedirectURI(tt.req), "getOAuthRedirectURI(%v)", tt.req)
})
}
}

View File

@ -18,15 +18,16 @@ type SignatureData struct {
// Options holds Configuration Options that can be set by Command Line Flag, // Options holds Configuration Options that can be set by Command Line Flag,
// or Config File // or Config File
type Options struct { type Options struct {
ProxyPrefix string `flag:"proxy-prefix" cfg:"proxy_prefix"` ProxyPrefix string `flag:"proxy-prefix" cfg:"proxy_prefix"`
PingPath string `flag:"ping-path" cfg:"ping_path"` PingPath string `flag:"ping-path" cfg:"ping_path"`
PingUserAgent string `flag:"ping-user-agent" cfg:"ping_user_agent"` PingUserAgent string `flag:"ping-user-agent" cfg:"ping_user_agent"`
ReadyPath string `flag:"ready-path" cfg:"ready_path"` ReadyPath string `flag:"ready-path" cfg:"ready_path"`
ReverseProxy bool `flag:"reverse-proxy" cfg:"reverse_proxy"` ReverseProxy bool `flag:"reverse-proxy" cfg:"reverse_proxy"`
RealClientIPHeader string `flag:"real-client-ip-header" cfg:"real_client_ip_header"` RealClientIPHeader string `flag:"real-client-ip-header" cfg:"real_client_ip_header"`
TrustedIPs []string `flag:"trusted-ip" cfg:"trusted_ips"` TrustedIPs []string `flag:"trusted-ip" cfg:"trusted_ips"`
ForceHTTPS bool `flag:"force-https" cfg:"force_https"` ForceHTTPS bool `flag:"force-https" cfg:"force_https"`
RawRedirectURL string `flag:"redirect-url" cfg:"redirect_url"` RawRedirectURL string `flag:"redirect-url" cfg:"redirect_url"`
RelativeRedirectURL bool `flag:"relative-redirect-url" cfg:"relative_redirect_url"`
AuthenticatedEmailsFile string `flag:"authenticated-emails-file" cfg:"authenticated_emails_file"` AuthenticatedEmailsFile string `flag:"authenticated-emails-file" cfg:"authenticated_emails_file"`
EmailDomains []string `flag:"email-domain" cfg:"email_domains"` EmailDomains []string `flag:"email-domain" cfg:"email_domains"`