Skip to content

Commit 92505db

Browse files
Add workaround for multiple WWW-Auth schemes
Forgejo (and I guess Gitea), at least on Codeberg will specify both bearer and basic auth in the WWW-Authenticate header, which is a bit ambiguous to parse. For now, work around this by just handling the first scheme and ignoring any other parts of the header.
1 parent 117fa34 commit 92505db

File tree

3 files changed

+21
-1
lines changed

3 files changed

+21
-1
lines changed

internal/httputil/headers.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ func ParseLinkHeader(origin *url.URL, header string) ([]Link, error) {
7474
// ParseWWWAuthenticateHeader parses a Www-Authenticate header.
7575
// Returns the scheme and parameters.
7676
//
77+
// NOTE: Only returns the first scheme, any following scheme is ignored.
78+
//
7779
// SEE: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate.
7880
func ParseWWWAuthenticateHeader(header string) (string, map[string]string, error) {
7981
var scheme string
@@ -83,8 +85,9 @@ func ParseWWWAuthenticateHeader(header string) (string, map[string]string, error
8385
paramKey := ""
8486
paramValue := ""
8587
gotParamDelimiter := false
88+
loop:
8689
for i, c := range header {
87-
isAlpha := c >= 'a' && c <= 'z'
90+
isAlpha := (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'z')
8891
isNumeric := c >= '0' && c <= '0'
8992
isAlphaNumeric := isAlpha || isNumeric || c == '-'
9093
isEnd := i == len(header)-1
@@ -104,6 +107,12 @@ func ParseWWWAuthenticateHeader(header string) (string, map[string]string, error
104107
}
105108
}
106109
case "paramKey":
110+
// For now, only parse the first scheme
111+
if paramKey == "Bearer" || paramKey == "Basic" {
112+
state = "end"
113+
break loop
114+
}
115+
107116
// Consume optional whitespace after params delimiter
108117
if gotParamDelimiter && c == ' ' {
109118
continue

internal/httputil/headers_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,16 @@ func TestParseWWWAuthenticateHeader(t *testing.T) {
200200
},
201201
Error: false,
202202
},
203+
{
204+
Header: `Bearer realm="https://codeberg.org/v2/token",service="container_registry",scope="*",Basic realm="https://codeberg.org/v2",service="container_registry",scope="*"`,
205+
ExpectedScheme: "Bearer",
206+
ExpectedParams: map[string]string{
207+
"realm": "https://codeberg.org/v2/token",
208+
"service": "container_registry",
209+
"scope": "*",
210+
},
211+
Error: false,
212+
},
203213
{
204214
Header: `Basic realm="Dev" charset="ASCII" charset="UTF-8"`,
205215
Error: true,

internal/oci/client_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ func TestClientGetTags(t *testing.T) {
184184
"registry.k8s.io/kube-state-metrics/kube-state-metrics",
185185
"gcr.io/zenika-hub/alpine-chrome",
186186
"mongo",
187+
"codeberg.org/forgejo/forgejo:14.0.2-rootless",
187188
}
188189

189190
for _, reference := range references {

0 commit comments

Comments
 (0)