mirror of
https://github.com/genuinetools/reg.git
synced 2024-05-13 09:48:33 -04:00
support 'access_token' for compatibility with OAuth 2.0 https://docs.docker.com/registry/spec/auth/token/#requesting-a-token (#124)
This commit is contained in:
parent
478c4dadc6
commit
83c621c4a7
|
@ -40,7 +40,18 @@ func (t *TokenTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
}
|
||||
|
||||
type authToken struct {
|
||||
Token string `json:"token"`
|
||||
Token string `json:"token"`
|
||||
AccessToken string `json:"access_token"`
|
||||
}
|
||||
|
||||
func (t authToken) String() (string, error) {
|
||||
if t.Token != "" {
|
||||
return t.Token, nil
|
||||
}
|
||||
if t.AccessToken != "" {
|
||||
return t.AccessToken, nil
|
||||
}
|
||||
return "", errors.New("auth token cannot be empty")
|
||||
}
|
||||
|
||||
func (t *TokenTransport) authAndRetry(authService *authService, req *http.Request) (*http.Response, error) {
|
||||
|
@ -81,7 +92,8 @@ func (t *TokenTransport) auth(authService *authService) (string, *http.Response,
|
|||
return "", nil, err
|
||||
}
|
||||
|
||||
return authToken.Token, nil, nil
|
||||
token, err := authToken.String()
|
||||
return token, nil, err
|
||||
}
|
||||
|
||||
func (t *TokenTransport) retry(req *http.Request, token string) (*http.Response, error) {
|
||||
|
@ -187,11 +199,7 @@ func (r *Registry) Token(url string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
if authToken.Token == "" {
|
||||
return "", errors.New("Auth token cannot be empty")
|
||||
}
|
||||
|
||||
return authToken.Token, nil
|
||||
return authToken.String()
|
||||
}
|
||||
|
||||
// Headers returns the authorization headers for a specific uri.
|
||||
|
|
|
@ -3,6 +3,7 @@ package registry
|
|||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
|
@ -36,3 +37,57 @@ func TestErrBasicAuth(t *testing.T) {
|
|||
t.Fatalf("expected empty token, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var authURI string
|
||||
|
||||
func oauthFlow(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(r.URL.Path, "/oauth2/accesstoken") {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{"access_token":"abcdef1234"}`))
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.URL.Path, "/oauth2/token") {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{"token":"abcdef1234"}`))
|
||||
return
|
||||
}
|
||||
auth := r.Header.Get("authorization")
|
||||
if !strings.HasPrefix(auth, "Bearer") {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
if authURI != "" {
|
||||
w.Header().Set("www-authenticate", `Bearer realm="`+authURI+`/oauth2/token",service="my.endpoint.here"`)
|
||||
}
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte(`{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}`))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func TestBothTokenAndAccessTokenWork(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(oauthFlow))
|
||||
defer ts.Close()
|
||||
|
||||
for _, which := range []string{"token", "accesstoken"} {
|
||||
authURI = ts.URL + "/oauth2/" + which + "?service=my.endpoint.here"
|
||||
authConfig := types.AuthConfig{
|
||||
Username: "abc",
|
||||
Password: "123",
|
||||
ServerAddress: ts.URL,
|
||||
}
|
||||
authConfig.Email = "me@email.com"
|
||||
r, err := New(authConfig, Opt{Insecure: true, Debug: true})
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error creating client, got %v", err)
|
||||
}
|
||||
token, err := r.Token(ts.URL)
|
||||
if err != nil {
|
||||
t.Fatalf("err getting token from url: %v err: %v", ts.URL, err)
|
||||
}
|
||||
if token == "" {
|
||||
t.Fatalf("error got empty token")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue