Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions backend/server/api/middlewares.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,22 @@ func getBasicAuthUserInfo(c *gin.Context, basicRes context.BasicRes) (*common.Us

func OAuth2ProxyAuthentication(basicRes context.BasicRes) gin.HandlerFunc {
logger := basicRes.GetLogger()
forwardedUserSecret := strings.TrimSpace(basicRes.GetConfigReader().GetString("FORWARDED_USER_SECRET"))
cfg := basicRes.GetConfigReader()
forwardedUserSecret := strings.TrimSpace(cfg.GetString("FORWARDED_USER_SECRET"))
// A Basic header is only an identity nginx (config-ui) has already verified
// against ADMIN_USER/ADMIN_PASS; the lake never checks the password. With
// AUTH_ENABLED the lake is the authenticator (session cookie, API key, or
// forwarded headers with the shared secret), so an unverified Basic header
// must not become a user, or any username:password passes RequireAuth.
trustBasicAuth := !(cfg.IsSet("AUTH_ENABLED") && cfg.GetBool("AUTH_ENABLED"))
return func(c *gin.Context) {
_, exist := c.Get(common.USER)
if !exist {
user, err := getOAuthUserInfo(c, forwardedUserSecret)
if err != nil {
logger.Warn(err, "rejected forwarded user headers")
}
if user == nil || user.Name == "" {
if (user == nil || user.Name == "") && trustBasicAuth {
// fetch with basic auth header
user, err = getBasicAuthUserInfo(c, basicRes)
if err != nil {
Expand Down
59 changes: 59 additions & 0 deletions backend/server/api/middlewares_basicauth_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package api

import (
"encoding/base64"
"testing"

"github.com/spf13/viper"
)

func basicAuthHeader(username, password string) map[string]string {
return map[string]string{
"Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+password)),
}
}

func TestOAuth2ProxyAuthenticationIgnoresBasicAuthWhenAuthEnabled(t *testing.T) {
cfg := viper.New()
cfg.Set("AUTH_ENABLED", true)
router := newProxyAuthRouterWithConfig(cfg)
body := performProxyAuthRequest(t, router, basicAuthHeader("anyone", "anything"))
if body.Authenticated {
t.Fatalf("expected Basic auth header to be ignored with AUTH_ENABLED=true, got %+v", body)
}
}

func TestOAuth2ProxyAuthenticationTrustsBasicAuthWhenAuthDisabled(t *testing.T) {
cases := map[string]func(*viper.Viper){
"AUTH_ENABLED unset": func(*viper.Viper) {},
"AUTH_ENABLED explicit": func(cfg *viper.Viper) { cfg.Set("AUTH_ENABLED", false) },
}
for name, configure := range cases {
t.Run(name, func(t *testing.T) {
cfg := viper.New()
configure(cfg)
router := newProxyAuthRouterWithConfig(cfg)
body := performProxyAuthRequest(t, router, basicAuthHeader("admin", "secret"))
if !body.Authenticated || body.Name != "admin" {
t.Fatalf("expected Basic auth user to be kept without AUTH_ENABLED, got %+v", body)
}
})
}
}
6 changes: 5 additions & 1 deletion backend/server/api/middlewares_forwardsecret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,13 @@ type proxyAuthResponse struct {
}

func newProxyAuthRouter(secret string) *gin.Engine {
gin.SetMode(gin.TestMode)
cfg := viper.New()
cfg.Set("FORWARDED_USER_SECRET", secret)
return newProxyAuthRouterWithConfig(cfg)
}

func newProxyAuthRouterWithConfig(cfg *viper.Viper) *gin.Engine {
gin.SetMode(gin.TestMode)
basicRes := &proxyAuthTestBasicRes{
cfg: cfg,
logger: logruslog.Global,
Expand Down