mirror of
https://github.com/regclient/regclient.git
synced 2025-04-18 22:44:00 +03:00
Fix: Allow authentication with a token
This fixes a regression caused by PR #893. Signed-off-by: Brandon Mitchell <git@bmitch.net>
This commit is contained in:
parent
2dc14baefb
commit
0cd8674a8b
@ -624,9 +624,10 @@ func (b *bearerHandler) GenerateAuth() (string, error) {
|
||||
return fmt.Sprintf("Bearer %s", b.token.Token), nil
|
||||
}
|
||||
|
||||
// attempt to post if a refresh token is available
|
||||
if b.token.RefreshToken != "" {
|
||||
if err := b.tryPost(); err == nil {
|
||||
// attempt to post if a refresh token is available or token auth is being used
|
||||
cred := b.credsFn(b.host)
|
||||
if b.token.RefreshToken != "" || cred.Token != "" {
|
||||
if err := b.tryPost(cred); err == nil {
|
||||
return fmt.Sprintf("Bearer %s", b.token.Token), nil
|
||||
} else if err != ErrUnauthorized {
|
||||
return "", fmt.Errorf("failed to request auth token (post): %w%.0w", err, errs.ErrHTTPUnauthorized)
|
||||
@ -634,7 +635,7 @@ func (b *bearerHandler) GenerateAuth() (string, error) {
|
||||
}
|
||||
|
||||
// attempt a get (with basic auth if user/pass available)
|
||||
if err := b.tryGet(); err == nil {
|
||||
if err := b.tryGet(cred); err == nil {
|
||||
return fmt.Sprintf("Bearer %s", b.token.Token), nil
|
||||
} else if err != ErrUnauthorized {
|
||||
return "", fmt.Errorf("failed to request auth token (get): %w%.0w", err, errs.ErrHTTPUnauthorized)
|
||||
@ -655,8 +656,7 @@ func (b *bearerHandler) isExpired() bool {
|
||||
}
|
||||
|
||||
// tryGet requests a new token with a GET request
|
||||
func (b *bearerHandler) tryGet() error {
|
||||
cred := b.credsFn(b.host)
|
||||
func (b *bearerHandler) tryGet(cred Cred) error {
|
||||
req, err := http.NewRequest("GET", b.realm, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -691,8 +691,7 @@ func (b *bearerHandler) tryGet() error {
|
||||
}
|
||||
|
||||
// tryPost requests a new token via a POST request
|
||||
func (b *bearerHandler) tryPost() error {
|
||||
cred := b.credsFn(b.host)
|
||||
func (b *bearerHandler) tryPost(cred Cred) error {
|
||||
form := url.Values{}
|
||||
if len(b.scopes) > 0 {
|
||||
form.Set("scope", strings.Join(b.scopes, " "))
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@ -653,3 +654,75 @@ func TestBearer(t *testing.T) {
|
||||
t.Errorf("token5 (rerun) is already expired")
|
||||
}
|
||||
}
|
||||
|
||||
// TestBearerToken verifies a login with a token in the credential with a bearer request goes to POST.
|
||||
func TestBearerToken(t *testing.T) {
|
||||
t.Parallel()
|
||||
useragent := "regclient/test"
|
||||
user := "user"
|
||||
token := "testtoken"
|
||||
tokenResp, _ := json.Marshal(bearerToken{
|
||||
Token: token,
|
||||
ExpiresIn: 900,
|
||||
IssuedAt: time.Now(),
|
||||
Scope: "repository:reponame:pull",
|
||||
RefreshToken: token,
|
||||
})
|
||||
tokenForm := url.Values{}
|
||||
tokenForm.Set("scope", "repository:reponame:pull")
|
||||
tokenForm.Set("service", "test")
|
||||
tokenForm.Set("client_id", useragent)
|
||||
tokenForm.Set("grant_type", "refresh_token")
|
||||
tokenForm.Set("refresh_token", token)
|
||||
tokenBody := tokenForm.Encode()
|
||||
rrs := []reqresp.ReqResp{
|
||||
{
|
||||
ReqEntry: reqresp.ReqEntry{
|
||||
Name: "req token",
|
||||
Method: "POST",
|
||||
Path: "/tokens",
|
||||
Body: []byte(tokenBody),
|
||||
},
|
||||
RespEntry: reqresp.RespEntry{
|
||||
Status: 200,
|
||||
Body: tokenResp,
|
||||
},
|
||||
},
|
||||
}
|
||||
ts := httptest.NewServer(reqresp.NewHandler(t, rrs))
|
||||
defer ts.Close()
|
||||
tsURL, _ := url.Parse(ts.URL)
|
||||
tsHost := tsURL.Host
|
||||
bearer := NewBearerHandler(&http.Client{}, useragent, tsHost,
|
||||
func(h string) Cred { return Cred{User: user, Token: token} },
|
||||
slog.New(slog.NewTextHandler(io.Discard, &slog.HandlerOptions{})),
|
||||
).(*bearerHandler)
|
||||
|
||||
// handle token1, verify expired token gets current time and isn't expired
|
||||
err := bearer.AddScope("repository:reponame:pull")
|
||||
if err != nil {
|
||||
t.Errorf("failed adding scope: %v", err)
|
||||
}
|
||||
c, err := parseAuthHeader(
|
||||
`Bearer realm="` + tsURL.String() +
|
||||
`/tokens",service="test"` +
|
||||
`,scope="repository:reponame:pull"`)
|
||||
if err != nil {
|
||||
t.Errorf("failed on parse challenge: %v", err)
|
||||
}
|
||||
err = bearer.ProcessChallenge(c[0])
|
||||
if err != nil {
|
||||
t.Errorf("failed on response to token: %v", err)
|
||||
}
|
||||
resp, err := bearer.GenerateAuth()
|
||||
if err != nil {
|
||||
t.Errorf("failed to generate auth response: %v", err)
|
||||
}
|
||||
bearerResp := fmt.Sprintf("Bearer %s", token)
|
||||
if resp != bearerResp {
|
||||
t.Errorf("token1 is invalid, expected %s, received %s", "Bearer token1", resp)
|
||||
}
|
||||
if bearer.isExpired() {
|
||||
t.Errorf("token1 is already expired")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user