Move OIDC Token structs into a new oidctypes
package.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
parent
d64acbb5a9
commit
d32583dd7f
@ -20,6 +20,7 @@ import (
|
||||
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/filesession"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
)
|
||||
|
||||
//nolint: gochecknoinits
|
||||
@ -27,7 +28,7 @@ func init() {
|
||||
loginCmd.AddCommand(oidcLoginCommand(oidcclient.Login))
|
||||
}
|
||||
|
||||
func oidcLoginCommand(loginFunc func(issuer string, clientID string, opts ...oidcclient.Option) (*oidcclient.Token, error)) *cobra.Command {
|
||||
func oidcLoginCommand(loginFunc func(issuer string, clientID string, opts ...oidcclient.Option) (*oidctypes.Token, error)) *cobra.Command {
|
||||
var (
|
||||
cmd = cobra.Command{
|
||||
Args: cobra.NoArgs,
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
)
|
||||
|
||||
func TestLoginOIDCCommand(t *testing.T) {
|
||||
@ -92,12 +93,12 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
gotClientID string
|
||||
gotOptions []oidcclient.Option
|
||||
)
|
||||
cmd := oidcLoginCommand(func(issuer string, clientID string, opts ...oidcclient.Option) (*oidcclient.Token, error) {
|
||||
cmd := oidcLoginCommand(func(issuer string, clientID string, opts ...oidcclient.Option) (*oidctypes.Token, error) {
|
||||
gotIssuer = issuer
|
||||
gotClientID = clientID
|
||||
gotOptions = opts
|
||||
return &oidcclient.Token{
|
||||
IDToken: &oidcclient.IDToken{
|
||||
return &oidctypes.Token{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "test-id-token",
|
||||
Expiry: metav1.NewTime(time1),
|
||||
},
|
||||
|
@ -23,8 +23,8 @@ import (
|
||||
"go.pinniped.dev/internal/oidc"
|
||||
"go.pinniped.dev/internal/oidc/oidctestutil"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
"go.pinniped.dev/pkg/oidcclient/pkce"
|
||||
)
|
||||
|
||||
@ -651,8 +651,8 @@ func (u *upstreamOIDCIdentityProviderBuilder) Build() oidctestutil.TestUpstreamO
|
||||
UsernameClaim: u.usernameClaim,
|
||||
GroupsClaim: u.groupsClaim,
|
||||
Scopes: []string{"scope1", "scope2"},
|
||||
ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (oidcclient.Token, map[string]interface{}, error) {
|
||||
return oidcclient.Token{}, u.idToken, u.authcodeExchangeErr
|
||||
ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (oidctypes.Token, map[string]interface{}, error) {
|
||||
return oidctypes.Token{}, u.idToken, u.authcodeExchangeErr
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
"net/url"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
"go.pinniped.dev/pkg/oidcclient/pkce"
|
||||
)
|
||||
|
||||
@ -36,7 +36,7 @@ type TestUpstreamOIDCIdentityProvider struct {
|
||||
authcode string,
|
||||
pkceCodeVerifier pkce.Code,
|
||||
expectedIDTokenNonce nonce.Nonce,
|
||||
) (oidcclient.Token, map[string]interface{}, error)
|
||||
) (oidctypes.Token, map[string]interface{}, error)
|
||||
|
||||
exchangeAuthcodeAndValidateTokensCallCount int
|
||||
exchangeAuthcodeAndValidateTokensArgs []*ExchangeAuthcodeAndValidateTokenArgs
|
||||
@ -71,7 +71,7 @@ func (u *TestUpstreamOIDCIdentityProvider) ExchangeAuthcodeAndValidateTokens(
|
||||
authcode string,
|
||||
pkceCodeVerifier pkce.Code,
|
||||
expectedIDTokenNonce nonce.Nonce,
|
||||
) (oidcclient.Token, map[string]interface{}, error) {
|
||||
) (oidctypes.Token, map[string]interface{}, error) {
|
||||
if u.exchangeAuthcodeAndValidateTokensArgs == nil {
|
||||
u.exchangeAuthcodeAndValidateTokensArgs = make([]*ExchangeAuthcodeAndValidateTokenArgs, 0)
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
"net/url"
|
||||
"sync"
|
||||
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
"go.pinniped.dev/pkg/oidcclient/pkce"
|
||||
)
|
||||
|
||||
@ -40,7 +40,7 @@ type UpstreamOIDCIdentityProviderI interface {
|
||||
authcode string,
|
||||
pkceCodeVerifier pkce.Code,
|
||||
expectedIDTokenNonce nonce.Nonce,
|
||||
) (tokens oidcclient.Token, parsedIDTokenClaims map[string]interface{}, err error)
|
||||
) (tokens oidctypes.Token, parsedIDTokenClaims map[string]interface{}, err error)
|
||||
}
|
||||
|
||||
type DynamicUpstreamIDPProvider interface {
|
||||
|
@ -15,8 +15,8 @@ import (
|
||||
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/oidc/provider"
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
"go.pinniped.dev/pkg/oidcclient/pkce"
|
||||
)
|
||||
|
||||
@ -59,46 +59,46 @@ func (p *ProviderConfig) GetGroupsClaim() string {
|
||||
return p.GroupsClaim
|
||||
}
|
||||
|
||||
func (p *ProviderConfig) ExchangeAuthcodeAndValidateTokens(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (oidcclient.Token, map[string]interface{}, error) {
|
||||
func (p *ProviderConfig) ExchangeAuthcodeAndValidateTokens(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (oidctypes.Token, map[string]interface{}, error) {
|
||||
tok, err := p.Config.Exchange(ctx, authcode, pkceCodeVerifier.Verifier())
|
||||
if err != nil {
|
||||
return oidcclient.Token{}, nil, err
|
||||
return oidctypes.Token{}, nil, err
|
||||
}
|
||||
|
||||
idTok, hasIDTok := tok.Extra("id_token").(string)
|
||||
if !hasIDTok {
|
||||
return oidcclient.Token{}, nil, httperr.New(http.StatusBadRequest, "received response missing ID token")
|
||||
return oidctypes.Token{}, nil, httperr.New(http.StatusBadRequest, "received response missing ID token")
|
||||
}
|
||||
validated, err := p.Provider.Verifier(&oidc.Config{ClientID: p.GetClientID()}).Verify(ctx, idTok)
|
||||
if err != nil {
|
||||
return oidcclient.Token{}, nil, httperr.Wrap(http.StatusBadRequest, "received invalid ID token", err)
|
||||
return oidctypes.Token{}, nil, httperr.Wrap(http.StatusBadRequest, "received invalid ID token", err)
|
||||
}
|
||||
if validated.AccessTokenHash != "" {
|
||||
if err := validated.VerifyAccessToken(tok.AccessToken); err != nil {
|
||||
return oidcclient.Token{}, nil, httperr.Wrap(http.StatusBadRequest, "received invalid ID token", err)
|
||||
return oidctypes.Token{}, nil, httperr.Wrap(http.StatusBadRequest, "received invalid ID token", err)
|
||||
}
|
||||
}
|
||||
if expectedIDTokenNonce != "" {
|
||||
if err := expectedIDTokenNonce.Validate(validated); err != nil {
|
||||
return oidcclient.Token{}, nil, httperr.Wrap(http.StatusBadRequest, "received ID token with invalid nonce", err)
|
||||
return oidctypes.Token{}, nil, httperr.Wrap(http.StatusBadRequest, "received ID token with invalid nonce", err)
|
||||
}
|
||||
}
|
||||
|
||||
var validatedClaims map[string]interface{}
|
||||
if err := validated.Claims(&validatedClaims); err != nil {
|
||||
return oidcclient.Token{}, nil, httperr.Wrap(http.StatusInternalServerError, "could not unmarshal claims", err)
|
||||
return oidctypes.Token{}, nil, httperr.Wrap(http.StatusInternalServerError, "could not unmarshal claims", err)
|
||||
}
|
||||
|
||||
return oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
return oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: tok.AccessToken,
|
||||
Type: tok.TokenType,
|
||||
Expiry: metav1.NewTime(tok.Expiry),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: tok.RefreshToken,
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: idTok,
|
||||
Expiry: metav1.NewTime(validated.Expiry),
|
||||
},
|
||||
|
@ -19,8 +19,8 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"go.pinniped.dev/internal/mocks/mockkeyset"
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
)
|
||||
|
||||
func TestProviderConfig(t *testing.T) {
|
||||
@ -62,7 +62,7 @@ func TestProviderConfig(t *testing.T) {
|
||||
expectNonce nonce.Nonce
|
||||
returnIDTok string
|
||||
wantErr string
|
||||
wantToken oidcclient.Token
|
||||
wantToken oidctypes.Token
|
||||
wantClaims map[string]interface{}
|
||||
}{
|
||||
{
|
||||
@ -99,15 +99,15 @@ func TestProviderConfig(t *testing.T) {
|
||||
authCode: "valid",
|
||||
expectNonce: "",
|
||||
returnIDTok: invalidNonceIDToken,
|
||||
wantToken: oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
wantToken: oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "test-access-token",
|
||||
Expiry: metav1.Time{},
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token",
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: invalidNonceIDToken,
|
||||
Expiry: metav1.Time{},
|
||||
},
|
||||
@ -117,15 +117,15 @@ func TestProviderConfig(t *testing.T) {
|
||||
name: "valid",
|
||||
authCode: "valid",
|
||||
returnIDTok: validIDToken,
|
||||
wantToken: oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
wantToken: oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "test-access-token",
|
||||
Expiry: metav1.Time{},
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token",
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: validIDToken,
|
||||
Expiry: metav1.Time{},
|
||||
},
|
||||
@ -184,7 +184,7 @@ func TestProviderConfig(t *testing.T) {
|
||||
tok, claims, err := p.ExchangeAuthcodeAndValidateTokens(ctx, tt.authCode, "test-pkce", tt.expectNonce)
|
||||
if tt.wantErr != "" {
|
||||
require.EqualError(t, err, tt.wantErr)
|
||||
require.Equal(t, oidcclient.Token{}, tok)
|
||||
require.Equal(t, oidctypes.Token{}, tok)
|
||||
require.Nil(t, claims)
|
||||
return
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -48,7 +49,7 @@ type (
|
||||
Key oidcclient.SessionCacheKey `json:"key"`
|
||||
CreationTimestamp metav1.Time `json:"creationTimestamp"`
|
||||
LastUsedTimestamp metav1.Time `json:"lastUsedTimestamp"`
|
||||
Tokens oidcclient.Token `json:"tokens"`
|
||||
Tokens oidctypes.Token `json:"tokens"`
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
)
|
||||
|
||||
// validSession should be the same data as `testdata/valid.yaml`.
|
||||
@ -27,17 +28,17 @@ var validSession = sessionCache{
|
||||
},
|
||||
CreationTimestamp: metav1.NewTime(time.Date(2020, 10, 20, 18, 42, 7, 0, time.UTC).Local()),
|
||||
LastUsedTimestamp: metav1.NewTime(time.Date(2020, 10, 20, 18, 45, 31, 0, time.UTC).Local()),
|
||||
Tokens: oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
Tokens: oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "test-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(time.Date(2020, 10, 20, 19, 46, 30, 0, time.UTC).Local()),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "test-id-token",
|
||||
Expiry: metav1.NewTime(time.Date(2020, 10, 20, 19, 42, 07, 0, time.UTC).Local()),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token",
|
||||
},
|
||||
},
|
||||
@ -139,8 +140,8 @@ func TestNormalized(t *testing.T) {
|
||||
// ID token is empty, but not nil.
|
||||
{
|
||||
LastUsedTimestamp: metav1.NewTime(now),
|
||||
Tokens: oidcclient.Token{
|
||||
IDToken: &oidcclient.IDToken{
|
||||
Tokens: oidctypes.Token{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Minute)),
|
||||
},
|
||||
@ -149,8 +150,8 @@ func TestNormalized(t *testing.T) {
|
||||
// ID token is expired.
|
||||
{
|
||||
LastUsedTimestamp: metav1.NewTime(now),
|
||||
Tokens: oidcclient.Token{
|
||||
IDToken: &oidcclient.IDToken{
|
||||
Tokens: oidctypes.Token{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "test-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(-1 * time.Minute)),
|
||||
},
|
||||
@ -159,8 +160,8 @@ func TestNormalized(t *testing.T) {
|
||||
// Access token is empty, but not nil.
|
||||
{
|
||||
LastUsedTimestamp: metav1.NewTime(now),
|
||||
Tokens: oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
Tokens: oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Minute)),
|
||||
},
|
||||
@ -169,8 +170,8 @@ func TestNormalized(t *testing.T) {
|
||||
// Access token is expired.
|
||||
{
|
||||
LastUsedTimestamp: metav1.NewTime(now),
|
||||
Tokens: oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
Tokens: oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "test-access-token",
|
||||
Expiry: metav1.NewTime(now.Add(-1 * time.Minute)),
|
||||
},
|
||||
@ -179,8 +180,8 @@ func TestNormalized(t *testing.T) {
|
||||
// Refresh token is empty, but not nil.
|
||||
{
|
||||
LastUsedTimestamp: metav1.NewTime(now),
|
||||
Tokens: oidcclient.Token{
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
Tokens: oidctypes.Token{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "",
|
||||
},
|
||||
},
|
||||
@ -188,8 +189,8 @@ func TestNormalized(t *testing.T) {
|
||||
// Session has a refresh token but it hasn't been used in >90 days.
|
||||
{
|
||||
LastUsedTimestamp: metav1.NewTime(now.AddDate(-1, 0, 0)),
|
||||
Tokens: oidcclient.Token{
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
Tokens: oidctypes.Token{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token",
|
||||
},
|
||||
},
|
||||
@ -198,8 +199,8 @@ func TestNormalized(t *testing.T) {
|
||||
{
|
||||
CreationTimestamp: metav1.NewTime(now.Add(-1 * time.Hour)),
|
||||
LastUsedTimestamp: metav1.NewTime(now),
|
||||
Tokens: oidcclient.Token{
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
Tokens: oidctypes.Token{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token2",
|
||||
},
|
||||
},
|
||||
@ -207,8 +208,8 @@ func TestNormalized(t *testing.T) {
|
||||
{
|
||||
CreationTimestamp: metav1.NewTime(now.Add(-2 * time.Hour)),
|
||||
LastUsedTimestamp: metav1.NewTime(now),
|
||||
Tokens: oidcclient.Token{
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
Tokens: oidctypes.Token{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token1",
|
||||
},
|
||||
},
|
||||
@ -222,8 +223,8 @@ func TestNormalized(t *testing.T) {
|
||||
{
|
||||
CreationTimestamp: metav1.NewTime(now.Add(-2 * time.Hour)),
|
||||
LastUsedTimestamp: metav1.NewTime(now),
|
||||
Tokens: oidcclient.Token{
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
Tokens: oidctypes.Token{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token1",
|
||||
},
|
||||
},
|
||||
@ -231,8 +232,8 @@ func TestNormalized(t *testing.T) {
|
||||
{
|
||||
CreationTimestamp: metav1.NewTime(now.Add(-1 * time.Hour)),
|
||||
LastUsedTimestamp: metav1.NewTime(now),
|
||||
Tokens: oidcclient.Token{
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
Tokens: oidctypes.Token{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token2",
|
||||
},
|
||||
},
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -65,14 +66,14 @@ type Cache struct {
|
||||
}
|
||||
|
||||
// GetToken looks up the cached data for the given parameters. It may return nil if no valid matching session is cached.
|
||||
func (c *Cache) GetToken(key oidcclient.SessionCacheKey) *oidcclient.Token {
|
||||
func (c *Cache) GetToken(key oidcclient.SessionCacheKey) *oidctypes.Token {
|
||||
// If the cache file does not exist, exit immediately with no error log
|
||||
if _, err := os.Stat(c.path); errors.Is(err, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read the cache and lookup the matching entry. If one exists, update its last used timestamp and return it.
|
||||
var result *oidcclient.Token
|
||||
var result *oidctypes.Token
|
||||
c.withCache(func(cache *sessionCache) {
|
||||
if entry := cache.lookup(key); entry != nil {
|
||||
result = &entry.Tokens
|
||||
@ -84,7 +85,7 @@ func (c *Cache) GetToken(key oidcclient.SessionCacheKey) *oidcclient.Token {
|
||||
|
||||
// PutToken stores the provided token into the session cache under the given parameters. It does not return an error
|
||||
// but may silently fail to update the session cache.
|
||||
func (c *Cache) PutToken(key oidcclient.SessionCacheKey, token *oidcclient.Token) {
|
||||
func (c *Cache) PutToken(key oidcclient.SessionCacheKey, token *oidctypes.Token) {
|
||||
// Create the cache directory if it does not exist.
|
||||
if err := os.MkdirAll(filepath.Dir(c.path), 0700); err != nil && !errors.Is(err, os.ErrExist) {
|
||||
c.errReporter(fmt.Errorf("could not create session cache directory: %w", err))
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
@ -37,7 +38,7 @@ func TestGetToken(t *testing.T) {
|
||||
trylockFunc func(*testing.T) error
|
||||
unlockFunc func(*testing.T) error
|
||||
key oidcclient.SessionCacheKey
|
||||
want *oidcclient.Token
|
||||
want *oidctypes.Token
|
||||
wantErrors []string
|
||||
wantTestFile func(t *testing.T, tmp string)
|
||||
}{
|
||||
@ -98,17 +99,17 @@ func TestGetToken(t *testing.T) {
|
||||
},
|
||||
CreationTimestamp: metav1.NewTime(now.Add(-2 * time.Hour)),
|
||||
LastUsedTimestamp: metav1.NewTime(now.Add(-1 * time.Hour)),
|
||||
Tokens: oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
Tokens: oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "test-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour)),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "test-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour)),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token",
|
||||
},
|
||||
},
|
||||
@ -136,17 +137,17 @@ func TestGetToken(t *testing.T) {
|
||||
},
|
||||
CreationTimestamp: metav1.NewTime(now.Add(-2 * time.Hour)),
|
||||
LastUsedTimestamp: metav1.NewTime(now.Add(-1 * time.Hour)),
|
||||
Tokens: oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
Tokens: oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "test-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour)),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "test-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour)),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token",
|
||||
},
|
||||
},
|
||||
@ -160,17 +161,17 @@ func TestGetToken(t *testing.T) {
|
||||
RedirectURI: "http://localhost:0/callback",
|
||||
},
|
||||
wantErrors: []string{},
|
||||
want: &oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
want: &oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "test-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour).Local()),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "test-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour).Local()),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token",
|
||||
},
|
||||
},
|
||||
@ -218,7 +219,7 @@ func TestPutToken(t *testing.T) {
|
||||
name string
|
||||
makeTestFile func(t *testing.T, tmp string)
|
||||
key oidcclient.SessionCacheKey
|
||||
token *oidcclient.Token
|
||||
token *oidctypes.Token
|
||||
wantErrors []string
|
||||
wantTestFile func(t *testing.T, tmp string)
|
||||
}{
|
||||
@ -244,17 +245,17 @@ func TestPutToken(t *testing.T) {
|
||||
},
|
||||
CreationTimestamp: metav1.NewTime(now.Add(-2 * time.Hour)),
|
||||
LastUsedTimestamp: metav1.NewTime(now.Add(-1 * time.Hour)),
|
||||
Tokens: oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
Tokens: oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "old-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour)),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "old-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour)),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "old-refresh-token",
|
||||
},
|
||||
},
|
||||
@ -268,17 +269,17 @@ func TestPutToken(t *testing.T) {
|
||||
Scopes: []string{"email", "offline_access", "openid", "profile"},
|
||||
RedirectURI: "http://localhost:0/callback",
|
||||
},
|
||||
token: &oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
token: &oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "new-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "new-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "new-refresh-token",
|
||||
},
|
||||
},
|
||||
@ -287,17 +288,17 @@ func TestPutToken(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, cache.Sessions, 1)
|
||||
require.Less(t, time.Since(cache.Sessions[0].LastUsedTimestamp.Time).Nanoseconds(), (5 * time.Second).Nanoseconds())
|
||||
require.Equal(t, oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
require.Equal(t, oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "new-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "new-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "new-refresh-token",
|
||||
},
|
||||
}, cache.Sessions[0].Tokens)
|
||||
@ -316,17 +317,17 @@ func TestPutToken(t *testing.T) {
|
||||
},
|
||||
CreationTimestamp: metav1.NewTime(now.Add(-2 * time.Hour)),
|
||||
LastUsedTimestamp: metav1.NewTime(now.Add(-1 * time.Hour)),
|
||||
Tokens: oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
Tokens: oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "old-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour)),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "old-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(1 * time.Hour)),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "old-refresh-token",
|
||||
},
|
||||
},
|
||||
@ -340,17 +341,17 @@ func TestPutToken(t *testing.T) {
|
||||
Scopes: []string{"email", "offline_access", "openid", "profile"},
|
||||
RedirectURI: "http://localhost:0/callback",
|
||||
},
|
||||
token: &oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
token: &oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "new-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "new-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "new-refresh-token",
|
||||
},
|
||||
},
|
||||
@ -359,17 +360,17 @@ func TestPutToken(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, cache.Sessions, 2)
|
||||
require.Less(t, time.Since(cache.Sessions[1].LastUsedTimestamp.Time).Nanoseconds(), (5 * time.Second).Nanoseconds())
|
||||
require.Equal(t, oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
require.Equal(t, oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "new-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "new-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "new-refresh-token",
|
||||
},
|
||||
}, cache.Sessions[1].Tokens)
|
||||
@ -388,17 +389,17 @@ func TestPutToken(t *testing.T) {
|
||||
Scopes: []string{"email", "offline_access", "openid", "profile"},
|
||||
RedirectURI: "http://localhost:0/callback",
|
||||
},
|
||||
token: &oidcclient.Token{
|
||||
AccessToken: &oidcclient.AccessToken{
|
||||
token: &oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "new-access-token",
|
||||
Type: "Bearer",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
IDToken: &oidcclient.IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "new-id-token",
|
||||
Expiry: metav1.NewTime(now.Add(2 * time.Hour).Local()),
|
||||
},
|
||||
RefreshToken: &oidcclient.RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "new-refresh-token",
|
||||
},
|
||||
},
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"go.pinniped.dev/internal/httputil/httperr"
|
||||
"go.pinniped.dev/internal/httputil/securityheader"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
"go.pinniped.dev/pkg/oidcclient/pkce"
|
||||
"go.pinniped.dev/pkg/oidcclient/state"
|
||||
)
|
||||
@ -68,7 +69,7 @@ type handlerState struct {
|
||||
}
|
||||
|
||||
type callbackResult struct {
|
||||
token *Token
|
||||
token *oidctypes.Token
|
||||
err error
|
||||
}
|
||||
|
||||
@ -116,6 +117,19 @@ func WithBrowserOpen(openURL func(url string) error) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// SessionCacheKey contains the data used to select a valid session cache entry.
|
||||
type SessionCacheKey struct {
|
||||
Issuer string `json:"issuer"`
|
||||
ClientID string `json:"clientID"`
|
||||
Scopes []string `json:"scopes"`
|
||||
RedirectURI string `json:"redirect_uri"`
|
||||
}
|
||||
|
||||
type SessionCache interface {
|
||||
GetToken(SessionCacheKey) *oidctypes.Token
|
||||
PutToken(SessionCacheKey, *oidctypes.Token)
|
||||
}
|
||||
|
||||
// WithSessionCache sets the session cache backend for storing and retrieving previously-issued ID tokens and refresh tokens.
|
||||
func WithSessionCache(cache SessionCache) Option {
|
||||
return func(h *handlerState) error {
|
||||
@ -135,8 +149,8 @@ func WithClient(httpClient *http.Client) Option {
|
||||
// nopCache is a SessionCache that doesn't actually do anything.
|
||||
type nopCache struct{}
|
||||
|
||||
func (*nopCache) GetToken(SessionCacheKey) *Token { return nil }
|
||||
func (*nopCache) PutToken(SessionCacheKey, *Token) {}
|
||||
func (*nopCache) GetToken(SessionCacheKey) *oidctypes.Token { return nil }
|
||||
func (*nopCache) PutToken(SessionCacheKey, *oidctypes.Token) {}
|
||||
|
||||
type discoveryI interface {
|
||||
Endpoint() oauth2.Endpoint
|
||||
@ -144,7 +158,7 @@ type discoveryI interface {
|
||||
}
|
||||
|
||||
// Login performs an OAuth2/OIDC authorization code login using a localhost listener.
|
||||
func Login(issuer string, clientID string, opts ...Option) (*Token, error) {
|
||||
func Login(issuer string, clientID string, opts ...Option) (*oidctypes.Token, error) {
|
||||
h := handlerState{
|
||||
issuer: issuer,
|
||||
clientID: clientID,
|
||||
@ -274,7 +288,7 @@ func Login(issuer string, clientID string, opts ...Option) (*Token, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handlerState) handleRefresh(ctx context.Context, refreshToken *RefreshToken) (*Token, error) {
|
||||
func (h *handlerState) handleRefresh(ctx context.Context, refreshToken *oidctypes.RefreshToken) (*oidctypes.Token, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, refreshTimeout)
|
||||
defer cancel()
|
||||
refreshSource := h.oauth2Config.TokenSource(ctx, &oauth2.Token{RefreshToken: refreshToken.Token})
|
||||
@ -331,7 +345,7 @@ func (h *handlerState) handleAuthCodeCallback(w http.ResponseWriter, r *http.Req
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *handlerState) validateToken(ctx context.Context, tok *oauth2.Token, checkNonce bool) (*Token, error) {
|
||||
func (h *handlerState) validateToken(ctx context.Context, tok *oauth2.Token, checkNonce bool) (*oidctypes.Token, error) {
|
||||
idTok, hasIDTok := tok.Extra("id_token").(string)
|
||||
if !hasIDTok {
|
||||
return nil, httperr.New(http.StatusBadRequest, "received response missing ID token")
|
||||
@ -350,16 +364,16 @@ func (h *handlerState) validateToken(ctx context.Context, tok *oauth2.Token, che
|
||||
return nil, httperr.Wrap(http.StatusBadRequest, "received ID token with invalid nonce", err)
|
||||
}
|
||||
}
|
||||
return &Token{
|
||||
AccessToken: &AccessToken{
|
||||
return &oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: tok.AccessToken,
|
||||
Type: tok.TokenType,
|
||||
Expiry: metav1.NewTime(tok.Expiry),
|
||||
},
|
||||
RefreshToken: &RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: tok.RefreshToken,
|
||||
},
|
||||
IDToken: &IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: idTok,
|
||||
Expiry: metav1.NewTime(validated.Expiry),
|
||||
},
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"go.pinniped.dev/internal/mocks/mockkeyset"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||
"go.pinniped.dev/pkg/oidcclient/oidctypes"
|
||||
"go.pinniped.dev/pkg/oidcclient/pkce"
|
||||
"go.pinniped.dev/pkg/oidcclient/state"
|
||||
)
|
||||
@ -32,19 +33,19 @@ import (
|
||||
// mockSessionCache exists to avoid an import cycle if we generate mocks into another package.
|
||||
type mockSessionCache struct {
|
||||
t *testing.T
|
||||
getReturnsToken *Token
|
||||
getReturnsToken *oidctypes.Token
|
||||
sawGetKeys []SessionCacheKey
|
||||
sawPutKeys []SessionCacheKey
|
||||
sawPutTokens []*Token
|
||||
sawPutTokens []*oidctypes.Token
|
||||
}
|
||||
|
||||
func (m *mockSessionCache) GetToken(key SessionCacheKey) *Token {
|
||||
func (m *mockSessionCache) GetToken(key SessionCacheKey) *oidctypes.Token {
|
||||
m.t.Logf("saw mock session cache GetToken() with client ID %s", key.ClientID)
|
||||
m.sawGetKeys = append(m.sawGetKeys, key)
|
||||
return m.getReturnsToken
|
||||
}
|
||||
|
||||
func (m *mockSessionCache) PutToken(key SessionCacheKey, token *Token) {
|
||||
func (m *mockSessionCache) PutToken(key SessionCacheKey, token *oidctypes.Token) {
|
||||
m.t.Logf("saw mock session cache PutToken() with client ID %s and ID token %s", key.ClientID, token.IDToken.Token)
|
||||
m.sawPutKeys = append(m.sawPutKeys, key)
|
||||
m.sawPutTokens = append(m.sawPutTokens, token)
|
||||
@ -55,15 +56,15 @@ func TestLogin(t *testing.T) {
|
||||
time1Unix := int64(2075807775)
|
||||
require.Equal(t, time1Unix, time1.Add(2*time.Minute).Unix())
|
||||
|
||||
testToken := Token{
|
||||
AccessToken: &AccessToken{
|
||||
testToken := oidctypes.Token{
|
||||
AccessToken: &oidctypes.AccessToken{
|
||||
Token: "test-access-token",
|
||||
Expiry: metav1.NewTime(time1.Add(1 * time.Minute)),
|
||||
},
|
||||
RefreshToken: &RefreshToken{
|
||||
RefreshToken: &oidctypes.RefreshToken{
|
||||
Token: "test-refresh-token",
|
||||
},
|
||||
IDToken: &IDToken{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
// Test JWT generated with https://smallstep.com/docs/cli/crypto/jwt/ (using time1Unix from above):
|
||||
// step crypto keypair key.pub key.priv --kty RSA --no-password --insecure --force && echo '{}' | step crypto jwt sign --key key.priv --aud test-client-id --sub test-user --subtle --kid="test-kid" --jti="test-jti" --exp 2075807775
|
||||
Token: "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2lkIiwidHlwIjoiSldUIn0.eyJhdWQiOiJ0ZXN0LWNsaWVudC1pZCIsImV4cCI6MjA3NTgwNzc3NSwiaWF0IjoxNjAzMzk5NTY4LCJpc3MiOiJ0ZXN0LWlzc3VlciIsImp0aSI6InRlc3QtanRpIiwibmJmIjoxNjAzMzk5NTY4LCJzdWIiOiJ0ZXN0LXVzZXIifQ.CdwUWQb6xELeFlC4u84K4rzks7YiDJiXxIo_SaRvCHBijxtil812RBRfPuAyYKJlGwFx1g-JYvkUg69X5NmvmLXkaOdHIKUAT7Nqa7yqd1xOAP9IlFj9qZM3Q7s8gWWW9da-_ryagzN4fyGfNfYeGhzIriSMaVpuBGz1eg6f-6VuuulnoiOpl8A0l50u0MdRjjsxRHuiR2loIhUxoIQQ9xN8w53UiP0R1uz8_uV0_K93RSq37aPjsnCXRLwUUb3azkRVe6B9EUW1ihthQ-KfRaU1iq2rY1m5UqNzf0NqDXCrN5SF-GVxOhKXJTsN4-PABfJBjqxg6dGUGeIa2JhFcA",
|
||||
@ -145,7 +146,7 @@ func TestLogin(t *testing.T) {
|
||||
issuer string
|
||||
clientID string
|
||||
wantErr string
|
||||
wantToken *Token
|
||||
wantToken *oidctypes.Token
|
||||
}{
|
||||
{
|
||||
name: "option error",
|
||||
@ -192,8 +193,8 @@ func TestLogin(t *testing.T) {
|
||||
clientID: "test-client-id",
|
||||
opt: func(t *testing.T) Option {
|
||||
return func(h *handlerState) error {
|
||||
cache := &mockSessionCache{t: t, getReturnsToken: &Token{
|
||||
IDToken: &IDToken{
|
||||
cache := &mockSessionCache{t: t, getReturnsToken: &oidctypes.Token{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "test-id-token",
|
||||
Expiry: metav1.NewTime(time.Now()), // less than Now() + minIDTokenValidity
|
||||
},
|
||||
@ -247,12 +248,12 @@ func TestLogin(t *testing.T) {
|
||||
clientID: "test-client-id",
|
||||
opt: func(t *testing.T) Option {
|
||||
return func(h *handlerState) error {
|
||||
cache := &mockSessionCache{t: t, getReturnsToken: &Token{
|
||||
IDToken: &IDToken{
|
||||
cache := &mockSessionCache{t: t, getReturnsToken: &oidctypes.Token{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "expired-test-id-token",
|
||||
Expiry: metav1.Now(), // less than Now() + minIDTokenValidity
|
||||
},
|
||||
RefreshToken: &RefreshToken{Token: "test-refresh-token"},
|
||||
RefreshToken: &oidctypes.RefreshToken{Token: "test-refresh-token"},
|
||||
}}
|
||||
t.Cleanup(func() {
|
||||
cacheKey := SessionCacheKey{
|
||||
@ -284,12 +285,12 @@ func TestLogin(t *testing.T) {
|
||||
clientID: "test-client-id",
|
||||
opt: func(t *testing.T) Option {
|
||||
return func(h *handlerState) error {
|
||||
cache := &mockSessionCache{t: t, getReturnsToken: &Token{
|
||||
IDToken: &IDToken{
|
||||
cache := &mockSessionCache{t: t, getReturnsToken: &oidctypes.Token{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "expired-test-id-token",
|
||||
Expiry: metav1.Now(), // less than Now() + minIDTokenValidity
|
||||
},
|
||||
RefreshToken: &RefreshToken{Token: "test-refresh-token-returning-invalid-id-token"},
|
||||
RefreshToken: &oidctypes.RefreshToken{Token: "test-refresh-token-returning-invalid-id-token"},
|
||||
}}
|
||||
t.Cleanup(func() {
|
||||
require.Empty(t, cache.sawPutKeys)
|
||||
@ -314,12 +315,12 @@ func TestLogin(t *testing.T) {
|
||||
clientID: "not-the-test-client-id",
|
||||
opt: func(t *testing.T) Option {
|
||||
return func(h *handlerState) error {
|
||||
cache := &mockSessionCache{t: t, getReturnsToken: &Token{
|
||||
IDToken: &IDToken{
|
||||
cache := &mockSessionCache{t: t, getReturnsToken: &oidctypes.Token{
|
||||
IDToken: &oidctypes.IDToken{
|
||||
Token: "expired-test-id-token",
|
||||
Expiry: metav1.Now(), // less than Now() + minIDTokenValidity
|
||||
},
|
||||
RefreshToken: &RefreshToken{Token: "test-refresh-token"},
|
||||
RefreshToken: &oidctypes.RefreshToken{Token: "test-refresh-token"},
|
||||
}}
|
||||
t.Cleanup(func() {
|
||||
require.Empty(t, cache.sawPutKeys)
|
||||
@ -414,7 +415,7 @@ func TestLogin(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
require.Equal(t, []SessionCacheKey{cacheKey}, cache.sawGetKeys)
|
||||
require.Equal(t, []SessionCacheKey{cacheKey}, cache.sawPutKeys)
|
||||
require.Equal(t, []*Token{&testToken}, cache.sawPutTokens)
|
||||
require.Equal(t, []*oidctypes.Token{&testToken}, cache.sawPutTokens)
|
||||
})
|
||||
require.NoError(t, WithSessionCache(cache)(h))
|
||||
require.NoError(t, WithClient(&http.Client{Timeout: 10 * time.Second})(h))
|
||||
|
@ -1,11 +1,10 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidcclient
|
||||
// Package oidctypes provides core data types for OIDC token structures.
|
||||
package oidctypes
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
import v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
// AccessToken is an OAuth2 access token.
|
||||
type AccessToken struct {
|
||||
@ -16,7 +15,7 @@ type AccessToken struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
|
||||
// Expiry is the optional expiration time of the access token.
|
||||
Expiry metav1.Time `json:"expiryTimestamp,omitempty"`
|
||||
Expiry v1.Time `json:"expiryTimestamp,omitempty"`
|
||||
}
|
||||
|
||||
// RefreshToken is an OAuth2 refresh token.
|
||||
@ -31,7 +30,7 @@ type IDToken struct {
|
||||
Token string `json:"token"`
|
||||
|
||||
// Expiry is the optional expiration time of the ID token.
|
||||
Expiry metav1.Time `json:"expiryTimestamp,omitempty"`
|
||||
Expiry v1.Time `json:"expiryTimestamp,omitempty"`
|
||||
}
|
||||
|
||||
// Token contains the elements of an OIDC session.
|
||||
@ -47,16 +46,3 @@ type Token struct {
|
||||
// IDToken is an OpenID Connect ID token.
|
||||
IDToken *IDToken `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// SessionCacheKey contains the data used to select a valid session cache entry.
|
||||
type SessionCacheKey struct {
|
||||
Issuer string `json:"issuer"`
|
||||
ClientID string `json:"clientID"`
|
||||
Scopes []string `json:"scopes"`
|
||||
RedirectURI string `json:"redirect_uri"`
|
||||
}
|
||||
|
||||
type SessionCache interface {
|
||||
GetToken(SessionCacheKey) *Token
|
||||
PutToken(SessionCacheKey, *Token)
|
||||
}
|
Loading…
Reference in New Issue
Block a user