Skip to content

Commit 64b34b4

Browse files
authored
Merge pull request #253 from githubnext/go-logger/auth-header-enhancement-aa4fd5e3c5f180f1
2 parents e5816eb + 62fea10 commit 64b34b4

2 files changed

Lines changed: 76 additions & 1 deletion

File tree

internal/auth/header.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,31 @@ package auth
1616
import (
1717
"errors"
1818
"strings"
19+
20+
"github.com/githubnext/gh-aw-mcpg/internal/logger"
1921
)
2022

23+
var log = logger.New("auth:header")
24+
2125
var (
2226
// ErrMissingAuthHeader is returned when the Authorization header is missing
2327
ErrMissingAuthHeader = errors.New("missing Authorization header")
2428
// ErrInvalidAuthHeader is returned when the Authorization header format is invalid
2529
ErrInvalidAuthHeader = errors.New("invalid Authorization header format")
2630
)
2731

32+
// sanitizeForLogging returns a sanitized version of the input string for safe logging.
33+
// It shows only the first 4 characters followed by "..." to prevent exposing sensitive data.
34+
// For strings with 4 or fewer characters, it returns only "...".
35+
func sanitizeForLogging(input string) string {
36+
if len(input) > 4 {
37+
return input[:4] + "..."
38+
} else if len(input) > 0 {
39+
return "..."
40+
}
41+
return ""
42+
}
43+
2844
// ParseAuthHeader parses the Authorization header and extracts the API key and agent ID.
2945
// Per MCP spec 7.1, the Authorization header should contain the API key directly
3046
// without any Bearer prefix or other scheme.
@@ -38,33 +54,45 @@ var (
3854
// - agentID: The extracted agent/session identifier
3955
// - error: ErrMissingAuthHeader if header is empty, nil otherwise
4056
func ParseAuthHeader(authHeader string) (apiKey string, agentID string, error error) {
57+
log.Printf("Parsing auth header: sanitized=%s, length=%d", sanitizeForLogging(authHeader), len(authHeader))
58+
4159
if authHeader == "" {
60+
log.Print("Auth header missing, returning error")
4261
return "", "", ErrMissingAuthHeader
4362
}
4463

4564
// Handle "Bearer <token>" format (backward compatibility)
4665
if strings.HasPrefix(authHeader, "Bearer ") {
66+
log.Print("Detected Bearer token format (backward compatibility)")
4767
token := strings.TrimPrefix(authHeader, "Bearer ")
4868
return token, token, nil
4969
}
5070

5171
// Handle "Agent <agent-id>" format
5272
if strings.HasPrefix(authHeader, "Agent ") {
73+
log.Print("Detected Agent ID format")
5374
agentIDValue := strings.TrimPrefix(authHeader, "Agent ")
5475
return agentIDValue, agentIDValue, nil
5576
}
5677

5778
// Per MCP spec 7.1: Authorization header contains API key directly
5879
// Use the entire header value as both API key and agent/session ID
80+
log.Print("Using plain API key format (MCP spec 7.1)")
5981
return authHeader, authHeader, nil
6082
}
6183

6284
// ValidateAPIKey checks if the provided API key matches the expected key.
6385
// Returns true if they match, false otherwise.
6486
func ValidateAPIKey(provided, expected string) bool {
87+
log.Printf("Validating API key: expected_configured=%t", expected != "")
88+
6589
if expected == "" {
6690
// No API key configured, authentication is disabled
91+
log.Print("No API key configured, authentication disabled")
6792
return true
6893
}
69-
return provided == expected
94+
95+
matches := provided == expected
96+
log.Printf("API key validation result: matches=%t", matches)
97+
return matches
7098
}

internal/auth/header_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,53 @@ import (
44
"testing"
55
)
66

7+
func TestSanitizeForLogging(t *testing.T) {
8+
tests := []struct {
9+
name string
10+
input string
11+
want string
12+
}{
13+
{
14+
name: "Empty string",
15+
input: "",
16+
want: "",
17+
},
18+
{
19+
name: "Single character",
20+
input: "a",
21+
want: "...",
22+
},
23+
{
24+
name: "Four characters",
25+
input: "abcd",
26+
want: "...",
27+
},
28+
{
29+
name: "Five characters",
30+
input: "abcde",
31+
want: "abcd...",
32+
},
33+
{
34+
name: "Long string",
35+
input: "my-secret-api-key-12345",
36+
want: "my-s...",
37+
},
38+
{
39+
name: "API key with Bearer prefix",
40+
input: "Bearer my-token-123",
41+
want: "Bear...",
42+
},
43+
}
44+
45+
for _, tt := range tests {
46+
t.Run(tt.name, func(t *testing.T) {
47+
if got := sanitizeForLogging(tt.input); got != tt.want {
48+
t.Errorf("sanitizeForLogging() = %v, want %v", got, tt.want)
49+
}
50+
})
51+
}
52+
}
53+
754
func TestParseAuthHeader(t *testing.T) {
855
tests := []struct {
956
name string

0 commit comments

Comments
 (0)