Repository: argoproj/argo (go)

Issue:
auth-mode server fails when Authorization header is passed.
## Summary 

We have argo server behind a reverse proxy that does github SSO.. Upgrading from argo 2.8 to 2.11, using `--auth-mode server` broke the UI. /api/v1/version was returned
```json
{"code":16,"message":"no valid authentication methods found for mode client"}
```
## Diagnostics
The error is caused because our reverse proxy adds an authorization header.

To recreate:
- run argo server with auth-mode server
- port-forward to argo-ui
- This works `curl http://localhost:2746/api/v1/version`
- This fails `curl -H "Authorization: Bearer 1234"  http://localhost:2746/api/v1/version`

This was tracked down to:
https://github.com/argoproj/argo/blob/f9b65c52321d6e49d7fbc78f69d18e7d1ee442ad/server/auth/gatekeeper.go#L117-L118

when only auth-mode server is active, authorization and cookie headers should be ignored.

What Kubernetes provider are you using? 
GKE

What version of Argo Workflows are you running? 

2.11.8


---
<!-- Issue Author: Don't delete this message to encourage other users to support your issue! -->
**Message from the maintainers**:

Impacted by this bug? Give it a 👍. We prioritise the issues with the most 👍.


Pull request description:
fix(server): Only try to use auth-mode if enabled. Fixes #4400
Signed-off-by: Alex Collins <alex_collins@intuit.com>
Fixes #4400

Checklist:

* [x] Either (a) I've created an [enhancement proposal](https://github.com/argoproj/argo/issues/new/choose) and discussed it with the community, (b) this is a bug fix, or (c) this is a chore.
* [ x] The title of the PR is (a) [conventional](https://www.conventionalcommits.org/en/v1.0.0/), (b) states what changed, and (c) suffixes the related issues number. E.g. `"fix(controller): Updates such and such. Fixes #1234"`.  
* [x] My organization is added to [USERS.md](https://github.com/argoproj/argo/blob/master/USERS.md).
* [x] I've signed the CLA.
* [x] I have written unit and/or e2e tests for my change. PRs without these are unlikely to be merged.
* [x] My builds are green. Try syncing with master if they are not. 


Patch:
diff --git a/server/auth/gatekeeper.go b/server/auth/gatekeeper.go
index 8b83bff77..c59426786 100644
--- a/server/auth/gatekeeper.go
+++ b/server/auth/gatekeeper.go
@@ -129,13 +129,10 @@ func getAuthHeader(md metadata.MD) string {
 func (s gatekeeper) getClients(ctx context.Context) (versioned.Interface, kubernetes.Interface, *types.Claims, error) {
 	md, _ := metadata.FromIncomingContext(ctx)
 	authorization := getAuthHeader(md)
-	mode, err := GetMode(authorization)
+	mode, err := s.Modes.GetMode(authorization)
 	if err != nil {
 		return nil, nil, nil, status.Error(codes.InvalidArgument, err.Error())
 	}
-	if !s.Modes[mode] {
-		return nil, nil, nil, status.Errorf(codes.Unauthenticated, "client auth-mode is %v, but that mode is disabled", mode)
-	}
 	switch mode {
 	case Client:
 		restConfig, wfClient, kubeClient, err := s.clientForAuthorization(authorization)
diff --git a/server/auth/mode.go b/server/auth/mode.go
index 25301e7c9..a481ddaf2 100644
--- a/server/auth/mode.go
+++ b/server/auth/mode.go
@@ -30,15 +30,15 @@ func (m Modes) Add(value string) error {
 	return nil
 }
 
-func GetMode(authorisation string) (Mode, error) {
-	if authorisation == "" {
-		return Server, nil
-	}
-	if strings.HasPrefix(authorisation, sso.Prefix) {
+func (m Modes) GetMode(authorisation string) (Mode, error) {
+	if strings.HasPrefix(authorisation, sso.Prefix) && m[SSO] {
 		return SSO, nil
 	}
-	if strings.HasPrefix(authorisation, "Bearer ") || strings.HasPrefix(authorisation, "Basic ") {
+	if (strings.HasPrefix(authorisation, "Bearer ") || strings.HasPrefix(authorisation, "Basic ")) && m[Client] {
 		return Client, nil
 	}
+	if m[Server] {
+		return Server, nil
+	}
 	return "", errors.New("unrecognized token")
 }


Test patch:
diff --git a/server/auth/mode_test.go b/server/auth/mode_test.go
index bc5349308..140fc211f 100644
--- a/server/auth/mode_test.go
+++ b/server/auth/mode_test.go
@@ -37,20 +37,25 @@ func TestModes_Add(t *testing.T) {
 	})
 }
 func TestModes_GetMode(t *testing.T) {
+	m := Modes{
+		Client: true,
+		SSO:    true,
+		Server: true,
+	}
 	t.Run("Client", func(t *testing.T) {
-		mode, err := GetMode("Bearer ")
+		mode, err := m.GetMode("Bearer ")
 		if assert.NoError(t, err) {
 			assert.Equal(t, Client, mode)
 		}
 	})
 	t.Run("Server", func(t *testing.T) {
-		mode, err := GetMode("")
+		mode, err := m.GetMode("")
 		if assert.NoError(t, err) {
 			assert.Equal(t, Server, mode)
 		}
 	})
 	t.Run("SSO", func(t *testing.T) {
-		mode, err := GetMode("Bearer v2:")
+		mode, err := m.GetMode("Bearer v2:")
 		if assert.NoError(t, err) {
 			assert.Equal(t, SSO, mode)
 		}