@@ -68,6 +68,10 @@ type allowedRoute struct {
68 pathRegex *regexp.Regexp
68 pathRegex *regexp.Regexp
71+type apiRoute struct {
72+ pathRegex *regexp.Regexp
71// OAuthProxy is the main authentication proxy
75// OAuthProxy is the main authentication proxy
72type OAuthProxy struct {
76type OAuthProxy struct {
73 CookieOptions *options.Cookie
77 CookieOptions *options.Cookie
@@ -76,6 +80,7 @@ type OAuthProxy struct {
76 SignInPath string
80 SignInPath string
78 allowedRoutes []allowedRoute
82 allowedRoutes []allowedRoute
79 redirectURL *url.URL // the url to receive requests at
84 redirectURL *url.URL // the url to receive requests at
80 whitelistDomains []string
85 whitelistDomains []string
81 provider providers.Provider
86 provider providers.Provider
@@ -176,6 +181,11 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
176 return nil, err
181 return nil, err
184+ apiRoutes, err := buildAPIRoutes(opts)
179 preAuthChain, err := buildPreAuthChain(opts)
189 preAuthChain, err := buildPreAuthChain(opts)
180 if err != nil {
190 if err != nil {
181 return nil, fmt.Errorf("could not build pre-auth chain: %v", err)
191 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
202 provider: provider,
212 provider: provider,
203 sessionStore: sessionStore,
213 sessionStore: sessionStore,
204 redirectURL: redirectURL,
214 redirectURL: redirectURL,
215+ apiRoutes: apiRoutes,
205 allowedRoutes: allowedRoutes,
216 allowedRoutes: allowedRoutes,
206 whitelistDomains: opts.WhitelistDomains,
217 whitelistDomains: opts.WhitelistDomains,
207 skipAuthPreflight: opts.SkipAuthPreflight,
218 skipAuthPreflight: opts.SkipAuthPreflight,
@@ -473,6 +484,24 @@ func buildRoutesAllowlist(opts *options.Options) ([]allowedRoute, error) {
473 return routes, nil
484 return routes, nil
487+// buildAPIRoutes builds an []apiRoute from ApiRoutes option
488+func buildAPIRoutes(opts *options.Options) ([]apiRoute, error) {
489+ routes := make([]apiRoute, 0, len(opts.APIRoutes))
491+ for _, path := range opts.APIRoutes {
492+ compiledRegex, err := regexp.Compile(path)
496+ logger.Printf("API route - Path: %s", path)
497+ routes = append(routes, apiRoute{
498+ pathRegex: compiledRegex,
476// ClearSessionCookie creates a cookie to unset the user's authentication cookie
505// ClearSessionCookie creates a cookie to unset the user's authentication cookie
477// stored in the user's session
506// stored in the user's session
478func (p *OAuthProxy) ClearSessionCookie(rw http.ResponseWriter, req *http.Request) error {
507func (p *OAuthProxy) ClearSessionCookie(rw http.ResponseWriter, req *http.Request) error {
@@ -543,6 +572,15 @@ func (p *OAuthProxy) isAllowedRoute(req *http.Request) bool {
543 return false
572 return false
575+func (p *OAuthProxy) isAPIPath(req *http.Request) bool {
576+ for _, route := range p.apiRoutes {
577+ if route.pathRegex.MatchString(req.URL.Path) {
546// isTrustedIP is used to check if a request comes from a trusted client IP address.
584// isTrustedIP is used to check if a request comes from a trusted client IP address.
547func (p *OAuthProxy) isTrustedIP(req *http.Request) bool {
585func (p *OAuthProxy) isTrustedIP(req *http.Request) bool {
548 if p.trustedIPs == nil {
586 if p.trustedIPs == nil {
@@ -911,7 +949,7 @@ func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) {
911 p.headersChain.Then(p.upstreamProxy).ServeHTTP(rw, req)
949 p.headersChain.Then(p.upstreamProxy).ServeHTTP(rw, req)
912 case ErrNeedsLogin:
950 case ErrNeedsLogin:
913 // we need to send the user to a login screen
951 // we need to send the user to a login screen
914− if p.forceJSONErrors || isAjax(req) {
952+ if p.forceJSONErrors || isAjax(req) || p.isAPIPath(req) {
915 logger.Printf("No valid authentication in request. Access Denied.")
953 logger.Printf("No valid authentication in request. Access Denied.")
916 // no point redirecting an AJAX request
954 // no point redirecting an AJAX request
917 p.errorJSON(rw, http.StatusUnauthorized)
955 p.errorJSON(rw, http.StatusUnauthorized)