reg/registry/authchallenge.go
Chris Smith 0ff43808ca Add more useful error for bad credentials. (#51)
* Add more useful error for bad credentials.

The www-authenticate: basic response currently gets caught by
the token transport, which fails to parse it and spits out
a rather oblique "malformed auth challenge header" error.

Make the token transport ignore basic auth types, and make
the error transport handle a 401 response.

* Format authchallenge.go correctly.
2017-12-11 10:42:19 -05:00

59 lines
1.2 KiB
Go

package registry
import (
"fmt"
"net/http"
"net/url"
"regexp"
)
var (
authChallengeRegex = regexp.MustCompile(
`^\s*Bearer\s+realm="([^"]+)",service="([^"]+)"\s*$`)
basicRegex = regexp.MustCompile(`^\s*Basic\s+.*$`)
challengeRegex = regexp.MustCompile(
`^\s*Bearer\s+realm="([^"]+)",service="([^"]+)",scope="([^"]+)"\s*$`)
scopeSeparatorRegex = regexp.MustCompile(`\s+`)
)
func parseAuthHeader(header http.Header) (*authService, error) {
ch, err := parseChallenge(header.Get("www-authenticate"))
if err != nil {
return nil, err
}
return ch, nil
}
func parseChallenge(challengeHeader string) (*authService, error) {
if basicRegex.MatchString(challengeHeader) {
return nil, nil
}
match := challengeRegex.FindAllStringSubmatch(challengeHeader, -1)
if len(match) != 1 {
match = authChallengeRegex.FindAllStringSubmatch(challengeHeader, -1)
if len(match) != 1 {
return nil, fmt.Errorf("malformed auth challenge header: '%s'", challengeHeader)
}
}
parsedRealm, err := url.Parse(match[0][1])
if err != nil {
return nil, err
}
a := &authService{
Realm: parsedRealm,
Service: match[0][2],
}
if len(match[0]) >= 4 {
a.Scope = scopeSeparatorRegex.Split(match[0][3], -1)
}
return a, nil
}