Skip to content

Commit

Permalink
oauth store: use different keys for oauth credentials
Browse files Browse the repository at this point in the history
Signed-off-by: Laura Brehm <[email protected]>
  • Loading branch information
laurazard committed Jul 29, 2024
1 parent 3cafaa4 commit 0d948ee
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 71 deletions.
82 changes: 65 additions & 17 deletions cli/config/credentials/oauth_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,9 @@ func (o *oauthStore) Get(serverAddress string) (types.AuthConfig, error) {
tokenRes, err := o.parseToken(auth.Password)
// if the password is not a token, return the auth config as is
if err != nil {
//nolint:nilerr
return auth, nil
}

println(tokenRes.Claims.Expiry.Time().Local().String())

// if the access token is valid for less than minimumTokenLifetime, refresh it
if tokenRes.RefreshToken != "" && tokenRes.Claims.Expiry.Time().Before(time.Now().Add(minimumTokenLifetime)) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
Expand All @@ -77,7 +74,6 @@ func (o *oauthStore) Get(serverAddress string) (types.AuthConfig, error) {
return types.AuthConfig{
Username: tokenRes.Claims.Domain.Username,
Password: tokenRes.AccessToken,
Email: tokenRes.Claims.Domain.Email,
ServerAddress: defaultRegistry,
}, nil
}
Expand All @@ -86,25 +82,36 @@ func (o *oauthStore) Get(serverAddress string) (types.AuthConfig, error) {
// store contains credentials for the official registry, these are refreshed/processed
// according to the same rules as Get.
func (o *oauthStore) GetAll() (map[string]types.AuthConfig, error) {
// fetch all authconfigs from backing store
allAuths, err := o.backingStore.GetAll()
if err != nil {
return nil, err
}

if _, ok := allAuths[defaultRegistry]; !ok {
// if there are no oauth-type credentials for the default registry,
// we can return as-is
if _, ok := allAuths[defaultRegistry+accessTokenKey]; !ok {
return allAuths, nil
}

// if there is an oauth-type entry, then we need to parse it/refresh it
auth, err := o.Get(defaultRegistry)
if err != nil {
return nil, err
}
allAuths[defaultRegistry] = auth

// delete access/refresh-token specific entries since the caller
// doesn't care about those
delete(allAuths, defaultRegistry+accessTokenKey)
delete(allAuths, defaultRegistry+refreshTokenKey)

return allAuths, err
}

// Erase removes the credentials from the backing store, logging out of the
// tenant if running
// Erase removes the credentials from the backing store.
// If the address pertains to the default registry, and there are oauth-type
// credentials stored, it also revokes the refresh token with the tenant.
func (o *oauthStore) Erase(serverAddress string) error {
if serverAddress == defaultRegistry {
auth, err := o.backingStore.Get(defaultRegistry)
Expand All @@ -119,10 +126,41 @@ func (o *oauthStore) Erase(serverAddress string) error {
return o.backingStore.Erase(serverAddress)
}

// Store stores the provided credentials in the backing store, without any
// additional processing.
// Store stores the provided credentials in the backing store.
// If the provided credentials represent oauth-type credentials for the default
// registry, then those are stored as separate entries in the backing store.
// If there are basic auths and we're storing an oauth login, the basic auth
// entry is removed from the backing store, and vice versa.
func (o *oauthStore) Store(auth types.AuthConfig) error {
return o.backingStore.Store(auth)
if auth.ServerAddress != defaultRegistry {
return o.backingStore.Store(auth)
}

accessToken, refreshToken, err := oauth.SplitTokens(auth.Password)
if err != nil {
// not storing an oauth-type login, so just store the auth as-is
return errors.Join(
// first, remove oauth logins if we had any
o.backingStore.Erase(defaultRegistry+accessTokenKey),
o.backingStore.Erase(defaultRegistry+refreshTokenKey),
o.backingStore.Store(auth),
)
}

// erase basic auths before storing our oauth-type login
_ = o.backingStore.Erase(defaultRegistry)
return errors.Join(
o.backingStore.Store(types.AuthConfig{
Username: auth.Username,
Password: accessToken,
ServerAddress: defaultRegistry + accessTokenKey,
}),
o.backingStore.Store(types.AuthConfig{
Username: auth.Username,
Password: refreshToken,
ServerAddress: defaultRegistry + refreshTokenKey,
}),
)
}

func (o *oauthStore) parseToken(password string) (oauth.TokenResult, error) {
Expand All @@ -141,12 +179,22 @@ func (o *oauthStore) parseToken(password string) (oauth.TokenResult, error) {
}, nil
}

const (
accessTokenKey = "oauth/access-token"
refreshTokenKey = "oauth/refresh-token"
)

func (o *oauthStore) storeInBackingStore(tokenRes oauth.TokenResult) error {
auth := types.AuthConfig{
Username: tokenRes.Claims.Domain.Username,
Password: oauth.ConcatTokens(tokenRes.AccessToken, tokenRes.RefreshToken),
Email: tokenRes.Claims.Domain.Email,
ServerAddress: defaultRegistry,
}
return o.backingStore.Store(auth)
return errors.Join(
o.backingStore.Store(types.AuthConfig{
Username: tokenRes.Claims.Domain.Username,
Password: tokenRes.AccessToken,
ServerAddress: defaultRegistry + accessTokenKey,
}),
o.backingStore.Store(types.AuthConfig{
Username: tokenRes.Claims.Domain.Username,
Password: tokenRes.RefreshToken,
ServerAddress: defaultRegistry + refreshTokenKey,
}),
)
}
Loading

0 comments on commit 0d948ee

Please sign in to comment.