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