1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2025-06-15 00:15:00 +02:00

Add API route config (#1760)

* 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>
This commit is contained in:
Segfault16
2022-09-11 17:09:32 +02:00
committed by GitHub
parent b82593b9cc
commit 965fab422d
9 changed files with 188 additions and 17 deletions

View File

@ -68,6 +68,10 @@ type allowedRoute struct {
pathRegex *regexp.Regexp
}
type apiRoute struct {
pathRegex *regexp.Regexp
}
// OAuthProxy is the main authentication proxy
type OAuthProxy struct {
CookieOptions *options.Cookie
@ -76,6 +80,7 @@ type OAuthProxy struct {
SignInPath string
allowedRoutes []allowedRoute
apiRoutes []apiRoute
redirectURL *url.URL // the url to receive requests at
whitelistDomains []string
provider providers.Provider
@ -176,6 +181,11 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
return nil, err
}
apiRoutes, err := buildAPIRoutes(opts)
if err != nil {
return nil, err
}
preAuthChain, err := buildPreAuthChain(opts)
if err != nil {
return nil, fmt.Errorf("could not build pre-auth chain: %v", err)
@ -202,6 +212,7 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
provider: provider,
sessionStore: sessionStore,
redirectURL: redirectURL,
apiRoutes: apiRoutes,
allowedRoutes: allowedRoutes,
whitelistDomains: opts.WhitelistDomains,
skipAuthPreflight: opts.SkipAuthPreflight,
@ -473,6 +484,24 @@ func buildRoutesAllowlist(opts *options.Options) ([]allowedRoute, error) {
return routes, nil
}
// buildAPIRoutes builds an []apiRoute from ApiRoutes option
func buildAPIRoutes(opts *options.Options) ([]apiRoute, error) {
routes := make([]apiRoute, 0, len(opts.APIRoutes))
for _, path := range opts.APIRoutes {
compiledRegex, err := regexp.Compile(path)
if err != nil {
return nil, err
}
logger.Printf("API route - Path: %s", path)
routes = append(routes, apiRoute{
pathRegex: compiledRegex,
})
}
return routes, nil
}
// ClearSessionCookie creates a cookie to unset the user's authentication cookie
// stored in the user's session
func (p *OAuthProxy) ClearSessionCookie(rw http.ResponseWriter, req *http.Request) error {
@ -543,6 +572,15 @@ func (p *OAuthProxy) isAllowedRoute(req *http.Request) bool {
return false
}
func (p *OAuthProxy) isAPIPath(req *http.Request) bool {
for _, route := range p.apiRoutes {
if route.pathRegex.MatchString(req.URL.Path) {
return true
}
}
return false
}
// isTrustedIP is used to check if a request comes from a trusted client IP address.
func (p *OAuthProxy) isTrustedIP(req *http.Request) bool {
if p.trustedIPs == nil {
@ -911,7 +949,7 @@ func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) {
p.headersChain.Then(p.upstreamProxy).ServeHTTP(rw, req)
case ErrNeedsLogin:
// we need to send the user to a login screen
if p.forceJSONErrors || isAjax(req) {
if p.forceJSONErrors || isAjax(req) || p.isAPIPath(req) {
logger.Printf("No valid authentication in request. Access Denied.")
// no point redirecting an AJAX request
p.errorJSON(rw, http.StatusUnauthorized)