diff --git a/internal/api/api.go b/internal/api/api.go index c2758ca..02efa7a 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -121,7 +121,12 @@ func (api *API) SetupRoutes() { bindErr := c.BindUri(&proxy) // Handle error - if api.handleError(c, "Failed to bind URI", bindErr) { + if bindErr != nil { + log.Error().Err(bindErr).Msg("Failed to bind URI") + c.JSON(400, gin.H{ + "status": 400, + "message": "Bad Request", + }) return } @@ -130,6 +135,9 @@ func (api *API) SetupRoutes() { // Get user context userContext := api.Hooks.UseUserContext(c) + // Check if using basic auth + _, _, basicAuth := c.Request.BasicAuth() + // Get headers uri := c.Request.Header.Get("X-Forwarded-Uri") proto := c.Request.Header.Get("X-Forwarded-Proto") @@ -144,8 +152,8 @@ func (api *API) SetupRoutes() { // Check if there was an error if appAllowedErr != nil { - // Return 501 if nginx is the proxy or if the request is using an Authorization header - if proxy.Proxy == "nginx" || c.GetHeader("Authorization") != "" { + // Return 501 if nginx is the proxy or if the request is using basic auth + if proxy.Proxy == "nginx" || basicAuth { log.Error().Err(appAllowedErr).Msg("Failed to check if app is allowed") c.JSON(501, gin.H{ "status": 501, @@ -166,36 +174,24 @@ func (api *API) SetupRoutes() { if !appAllowed { log.Warn().Str("username", userContext.Username).Str("host", host).Msg("User not allowed") + // Return 401 if nginx is the proxy or if the request is using an Authorization header + if proxy.Proxy == "nginx" || basicAuth { + c.Header("WWW-Authenticate", "Basic realm=\"tinyauth\"") + c.JSON(401, gin.H{ + "status": 401, + "message": "Unauthorized", + }) + return + } + // Build query queries, queryErr := query.Values(types.UnauthorizedQuery{ Username: userContext.Username, Resource: strings.Split(host, ".")[0], }) - // Check if there was an error - if queryErr != nil { - // Return 501 if nginx is the proxy or if the request is using an Authorization header - if proxy.Proxy == "nginx" || c.GetHeader("Authorization") != "" { - log.Error().Err(queryErr).Msg("Failed to build query") - c.JSON(501, gin.H{ - "status": 501, - "message": "Internal Server Error", - }) - return - } - - // Return the internal server error page - if api.handleError(c, "Failed to build query", queryErr) { - return - } - } - - // Return 401 if nginx is the proxy or if the request is using an Authorization header - if proxy.Proxy == "nginx" || c.GetHeader("Authorization") != "" { - c.JSON(401, gin.H{ - "status": 401, - "message": "Unauthorized", - }) + // Handle error (no need to check for nginx/headers since we are sure we are using caddy/traefik) + if api.handleError(c, "Failed to build query", queryErr) { return } @@ -220,7 +216,8 @@ func (api *API) SetupRoutes() { log.Debug().Msg("Unauthorized") // Return 401 if nginx is the proxy or if the request is using an Authorization header - if proxy.Proxy == "nginx" || c.GetHeader("Authorization") != "" { + if proxy.Proxy == "nginx" || basicAuth { + c.Header("WWW-Authenticate", "Basic realm=\"tinyauth\"") c.JSON(401, gin.H{ "status": 401, "message": "Unauthorized", @@ -233,13 +230,13 @@ func (api *API) SetupRoutes() { RedirectURI: fmt.Sprintf("%s://%s%s", proto, host, uri), }) - log.Debug().Interface("redirect_uri", fmt.Sprintf("%s://%s%s", proto, host, uri)).Msg("Redirecting to login") - // Handle error (no need to check for nginx/headers since we are sure we are using caddy/traefik) if api.handleError(c, "Failed to build query", queryErr) { return } + log.Debug().Interface("redirect_uri", fmt.Sprintf("%s://%s%s", proto, host, uri)).Msg("Redirecting to login") + // Redirect to login c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/?%s", api.Config.AppURL, queries.Encode())) }) @@ -338,6 +335,7 @@ func (api *API) SetupRoutes() { // We are not logged in so return unauthorized if !userContext.IsLoggedIn { log.Debug().Msg("Unauthorized") + c.Header("WWW-Authenticate", "Basic realm=\"tinyauth\"") c.JSON(200, gin.H{ "status": 200, "message": "Unauthorized", diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 273c9ba..1566b3f 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -211,38 +211,18 @@ func (auth *Auth) ResourceAllowed(context types.UserContext, host string) (bool, return true, nil } -func (auth *Auth) GetBasicAuth(c *gin.Context) types.User { +func (auth *Auth) GetBasicAuth(c *gin.Context) *types.User { // Get the Authorization header - header := c.GetHeader("Authorization") + username, password, ok := c.Request.BasicAuth() - // If the header is empty, return an empty user - if header == "" { - return types.User{} - } - - // Split the header - headerSplit := strings.Split(header, " ") - - if len(headerSplit) != 2 { - return types.User{} - } - - // Check if the header is Basic - if headerSplit[0] != "Basic" { - return types.User{} - } - - // Split the credentials - credentials := strings.Split(headerSplit[1], ":") - - // If the credentials are not in the correct format, return an empty user - if len(credentials) != 2 { - return types.User{} + // If not ok, return an empty user + if !ok { + return nil } // Return the user - return types.User{ - Username: credentials[0], - Password: credentials[1], + return &types.User{ + Username: username, + Password: password, } } diff --git a/internal/hooks/hooks.go b/internal/hooks/hooks.go index cdbf852..b8f4e48 100644 --- a/internal/hooks/hooks.go +++ b/internal/hooks/hooks.go @@ -27,7 +27,7 @@ func (hooks *Hooks) UseUserContext(c *gin.Context) types.UserContext { basic := hooks.Auth.GetBasicAuth(c) // Check if basic auth is set - if basic.Username != "" { + if basic != nil { log.Debug().Msg("Got basic auth") // Check if user exists and password is correct