Skip to content

Fix: add double token in authorization header #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ tmp

coverage.html
coverage.out
.vscode
8 changes: 5 additions & 3 deletions internal/server/handlerCategory.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,16 @@ func _categoryHandler(s *shared, req *http.Request, res *response) (*response, *

var config k8s.KubeConfig
if data.ProjectName != "" && data.WorkspaceName != "" && data.McpName != "" {
config, err = openmcp.GetControlPlaneKubeconfig(s.crateKube, data.ProjectName, data.WorkspaceName, data.McpName, data.Authorization, crateKubeconfig)
config, err = openmcp.GetControlPlaneKubeconfig(s.crateKube, data.ProjectName, data.WorkspaceName, data.McpName, data.CrateAuthorizationToken, crateKubeconfig)
if err != nil {
slog.Error("failed to get control plane api config", "err", err)
return nil, NewInternalServerError("failed to get control plane api config")
}
if data.Authorization != "" {
config.SetUserToken(data.Authorization)
if data.McpAuthorizationToken == "" {
slog.Error("MCP authorization token not provided")
return nil, NewBadRequestError("MCP authorization token not provided")
}
config.SetUserToken(data.McpAuthorizationToken)
} else {
slog.Error("either use %s: true or provide %s, %s and %s headers", useCrateClusterHeader, projectNameHeader, workspaceNameHeader, mcpName)
return nil, NewBadRequestError(
Expand Down
29 changes: 19 additions & 10 deletions internal/server/handlerMain.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ type ExtractedRequestData struct {
McpName string
ContextName string
UseCrateCluster bool
Authorization string
CrateAuthorizationToken string
McpAuthorizationToken string
Headers map[string][]string
JQ string
Category string
Expand Down Expand Up @@ -87,16 +88,18 @@ func mainHandler(s *shared, req *http.Request, res *response) (*response, *HttpE
var config k8s.KubeConfig
if data.UseCrateCluster {
config = crateKubeconfig
config.SetUserToken(data.Authorization)
config.SetUserToken(data.CrateAuthorizationToken)
} else if data.ProjectName != "" && data.WorkspaceName != "" && data.McpName != "" {
config, err = openmcp.GetControlPlaneKubeconfig(s.crateKube, data.ProjectName, data.WorkspaceName, data.McpName, data.Authorization, crateKubeconfig)
config, err = openmcp.GetControlPlaneKubeconfig(s.crateKube, data.ProjectName, data.WorkspaceName, data.McpName, data.CrateAuthorizationToken, crateKubeconfig)
if err != nil {
slog.Error("failed to get control plane api config", "err", err)
return nil, NewInternalServerError("failed to get control plane api config")
}
if data.Authorization != "" {
config.SetUserToken(data.Authorization)
if data.McpAuthorizationToken == "" {
slog.Error("MCP authorization token not provided")
return nil, NewBadRequestError("MCP authorization token not provided")
}
config.SetUserToken(data.McpAuthorizationToken)
} else {
slog.Error("either use %s: true or provide %s, %s and %s headers", useCrateClusterHeader, projectNameHeader, workspaceNameHeader, mcpName)
return nil, NewBadRequestError(
Expand Down Expand Up @@ -138,6 +141,15 @@ func mainHandler(s *shared, req *http.Request, res *response) (*response, *HttpE
}

func extractRequestData(r *http.Request) (ExtractedRequestData, error) {
if r.Header.Get(authorizationHeader) == "" {
return ExtractedRequestData{}, fmt.Errorf("%s header is required", authorizationHeader)
}

crateToken, mcpToken, err := parseAuthorizationHeaderWithDoubleTokens(r.Header.Get(authorizationHeader))
if err != nil {
return ExtractedRequestData{}, fmt.Errorf("invalid %s header: %w", authorizationHeader, err)
}

rd := ExtractedRequestData{
Path: r.URL.Path,
Query: r.URL.Query(),
Expand All @@ -150,7 +162,8 @@ func extractRequestData(r *http.Request) (ExtractedRequestData, error) {
WorkspaceName: r.Header.Get(workspaceNameHeader),
ContextName: r.Header.Get(contextHeader),
McpName: r.Header.Get(mcpName),
Authorization: r.Header.Get(authorizationHeader),
CrateAuthorizationToken: crateToken,
McpAuthorizationToken: mcpToken,
JQ: r.Header.Get(jqHeader),
Category: r.Header.Get(categoryHeader),
}
Expand All @@ -166,10 +179,6 @@ func extractRequestData(r *http.Request) (ExtractedRequestData, error) {
rd.UseCrateCluster = useCrateCluster
}

if rd.Authorization == "" {
return ExtractedRequestData{}, fmt.Errorf("%s header is required", authorizationHeader)
}

return rd, nil
}

Expand Down
19 changes: 19 additions & 0 deletions internal/server/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package server
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
Expand Down Expand Up @@ -103,3 +104,21 @@ func ParseJQ(inputJson []byte, inputJQ string) (string, error) {

return strings.Join(result[:], "\n"), nil
}

// parseAuthorizationHeaderWithDoubleTokens parses an authorization header that may contain two tokens separated by a comma.
// It returns the first token and the second token (if present). If the second token is absent, it returns an empty string for it.
// If the header is empty or contains more than two tokens, it returns an error.
func parseAuthorizationHeaderWithDoubleTokens(authHeader string) (string, string, error) {
if authHeader == "" {
return "", "", fmt.Errorf("authorization header is empty")
}

tokens := strings.Split(authHeader, ",")
if len(tokens) > 2 {
return "", "", fmt.Errorf("authorization header must contain two or less tokens separated by a space")
}
if len(tokens) == 1 {
return tokens[0], "", nil
}
return tokens[0], tokens[1], nil
}
41 changes: 41 additions & 0 deletions internal/server/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package server

import (
"testing"
)

func TestParseAuthorizationHeaderWithDoubleTokens(t *testing.T) {
tests := []struct {
authHeader string
token1 string
token2 string
expectErr bool
}{
{"token1,token2", "token1", "token2", false},
{"token1", "token1", "", false},
{"", "", "", true},
{"token1,token2,token3", "", "", true},
}

for _, test := range tests {
t.Run(test.authHeader, func(t *testing.T) {
token1, token2, err := parseAuthorizationHeaderWithDoubleTokens(test.authHeader)

if test.expectErr {
if err == nil {
t.Errorf("expected an error but got none")
}
} else {
if err != nil {
t.Errorf("expected no error but got: %v", err)
}
if token1 != test.token1 {
t.Errorf("expected token1 to be %q but got %q", test.token1, token1)
}
if token2 != test.token2 {
t.Errorf("expected token2 to be %q but got %q", test.token2, token2)
}
}
})
}
}
Loading