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:
fix(server): Allow Bearer token in server mode. Fixes #4400
Fixes https://github.com/argoproj/argo/issues/4400

Signed-off-by: Simon Behar <simbeh7@gmail.com>

Checklist:

* [ ] My organization is added to [USERS.md](https://github.com/argoproj/argo/blob/master/USERS.md).

<!--

Please leave your PR in draft if you don't need a review yet. 

To fix failing `CI / Codegen`, run `make codegen`. 

-->


Patch:
diff --git a/server/auth/gatekeeper.go b/server/auth/gatekeeper.go
index 55c135dc7..00403413a 100644
--- a/server/auth/gatekeeper.go
+++ b/server/auth/gatekeeper.go
@@ -131,7 +131,7 @@ func (s gatekeeper) getClients(ctx context.Context) (versioned.Interface, kubern
 	authorization := getAuthHeader(md)
 	mode, valid := s.Modes.GetMode(authorization)
 	if !valid {
-		return nil, nil, nil, status.Error(codes.Unauthenticated, "token not valid for requested mode")
+		return nil, nil, nil, status.Error(codes.Unauthenticated, "token not valid for running mode")
 	}
 	switch mode {
 	case Client:
diff --git a/server/auth/mode.go b/server/auth/mode.go
index 7e5e836f4..bd244527d 100644
--- a/server/auth/mode.go
+++ b/server/auth/mode.go
@@ -31,11 +31,14 @@ func (m Modes) Add(value string) error {
 }
 
 func (m Modes) GetMode(authorisation string) (Mode, bool) {
-	if strings.HasPrefix(authorisation, sso.Prefix) {
-		return SSO, m[SSO]
+	if m[SSO] && strings.HasPrefix(authorisation, sso.Prefix) {
+		return SSO, true
 	}
-	if strings.HasPrefix(authorisation, "Bearer ") || strings.HasPrefix(authorisation, "Basic ") {
-		return Client, m[Client]
+	if m[Client] && strings.HasPrefix(authorisation, "Bearer ") || strings.HasPrefix(authorisation, "Basic ") {
+		return Client, true
 	}
-	return Server, m[Server]
+	if m[Server] {
+		return Server, true
+	}
+	return "", false
 }


Test patch:
diff --git a/server/auth/mode_test.go b/server/auth/mode_test.go
index 2fe5bd9b6..2a55e0e9f 100644
--- a/server/auth/mode_test.go
+++ b/server/auth/mode_test.go
@@ -60,4 +60,16 @@ func TestModes_GetMode(t *testing.T) {
 			assert.Equal(t, SSO, mode)
 		}
 	})
+
+	m = Modes{
+		Client: false,
+		SSO:    false,
+		Server: true,
+	}
+	t.Run("Server and Auth", func(t *testing.T) {
+		mode, valid := m.GetMode("Bearer ")
+		if assert.True(t, valid) {
+			assert.Equal(t, Server, mode)
+		}
+	})
 }