Use PinnipedSession type instead of fosite's DefaultSesssion type
This will allow us to store custom data inside the fosite session storage for all downstream OIDC sessions. Signed-off-by: Margo Crawford <margaretc@vmware.com>
This commit is contained in:
parent
6e41c10584
commit
c6f1d29538
@ -10,7 +10,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/oauth2"
|
"github.com/ory/fosite/handler/oauth2"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
|
|
||||||
@ -18,6 +17,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/crud"
|
"go.pinniped.dev/internal/crud"
|
||||||
"go.pinniped.dev/internal/fositestorage"
|
"go.pinniped.dev/internal/fositestorage"
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -26,7 +26,7 @@ const (
|
|||||||
ErrInvalidAccessTokenRequestVersion = constable.Error("access token request data has wrong version")
|
ErrInvalidAccessTokenRequestVersion = constable.Error("access token request data has wrong version")
|
||||||
ErrInvalidAccessTokenRequestData = constable.Error("access token request data must be present")
|
ErrInvalidAccessTokenRequestData = constable.Error("access token request data must be present")
|
||||||
|
|
||||||
accessTokenStorageVersion = "1"
|
accessTokenStorageVersion = "2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RevocationStorage interface {
|
type RevocationStorage interface {
|
||||||
@ -110,7 +110,7 @@ func newValidEmptyAccessTokenSession() *session {
|
|||||||
return &session{
|
return &session{
|
||||||
Request: &fosite.Request{
|
Request: &fosite.Request{
|
||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@ -22,6 +21,8 @@ import (
|
|||||||
coretesting "k8s.io/client-go/testing"
|
coretesting "k8s.io/client-go/testing"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const namespace = "test-ns"
|
const namespace = "test-ns"
|
||||||
@ -51,7 +52,7 @@ func TestAccessTokenStorage(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}},"requestedAudience":null,"grantedAudience":null},"version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/access-token",
|
Type: "storage.pinniped.dev/access-token",
|
||||||
@ -87,13 +88,7 @@ func TestAccessTokenStorage(t *testing.T) {
|
|||||||
RequestedScope: nil,
|
RequestedScope: nil,
|
||||||
GrantedScope: nil,
|
GrantedScope: nil,
|
||||||
Form: url.Values{"key": []string{"val"}},
|
Form: url.Values{"key": []string{"val"}},
|
||||||
Session: &openid.DefaultSession{
|
Session: testutil.NewFakePinnipedSession(),
|
||||||
Claims: nil,
|
|
||||||
Headers: nil,
|
|
||||||
ExpiresAt: nil,
|
|
||||||
Username: "snorlax",
|
|
||||||
Subject: "panda",
|
|
||||||
},
|
|
||||||
RequestedAudience: nil,
|
RequestedAudience: nil,
|
||||||
GrantedAudience: nil,
|
GrantedAudience: nil,
|
||||||
}
|
}
|
||||||
@ -107,6 +102,7 @@ func TestAccessTokenStorage(t *testing.T) {
|
|||||||
err = storage.DeleteAccessTokenSession(ctx, "fancy-signature")
|
err = storage.DeleteAccessTokenSession(ctx, "fancy-signature")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testutil.LogActualJSONFromCreateAction(t, client, 0) // makes it easier to update expected values when needed
|
||||||
require.Equal(t, wantActions, client.Actions())
|
require.Equal(t, wantActions, client.Actions())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +121,7 @@ func TestAccessTokenStorageRevocation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}},"requestedAudience":null,"grantedAudience":null},"version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/access-token",
|
Type: "storage.pinniped.dev/access-token",
|
||||||
@ -152,10 +148,7 @@ func TestAccessTokenStorageRevocation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Form: url.Values{"key": []string{"val"}},
|
Form: url.Values{"key": []string{"val"}},
|
||||||
Session: &openid.DefaultSession{
|
Session: testutil.NewFakePinnipedSession(),
|
||||||
Username: "snorlax",
|
|
||||||
Subject: "panda",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
err := storage.CreateAccessTokenSession(ctx, "fancy-signature", request)
|
err := storage.CreateAccessTokenSession(ctx, "fancy-signature", request)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -164,6 +157,7 @@ func TestAccessTokenStorageRevocation(t *testing.T) {
|
|||||||
err = storage.RevokeAccessToken(ctx, "abcd-1")
|
err = storage.RevokeAccessToken(ctx, "abcd-1")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testutil.LogActualJSONFromCreateAction(t, client, 0) // makes it easier to update expected values when needed
|
||||||
require.Equal(t, wantActions, client.Actions())
|
require.Equal(t, wantActions, client.Actions())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +184,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"not-the-right-version"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"not-the-right-version"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/access-token",
|
Type: "storage.pinniped.dev/access-token",
|
||||||
@ -200,7 +194,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
|
|
||||||
_, err = storage.GetAccessTokenSession(ctx, "fancy-signature", nil)
|
_, err = storage.GetAccessTokenSession(ctx, "fancy-signature", nil)
|
||||||
|
|
||||||
require.EqualError(t, err, "access token request data has wrong version: access token session for fancy-signature has version not-the-right-version instead of 1")
|
require.EqualError(t, err, "access token request data has wrong version: access token session for fancy-signature has version not-the-right-version instead of 2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNilSessionRequest(t *testing.T) {
|
func TestNilSessionRequest(t *testing.T) {
|
||||||
@ -218,7 +212,7 @@ func TestNilSessionRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"1"}`),
|
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/access-token",
|
Type: "storage.pinniped.dev/access-token",
|
||||||
@ -246,10 +240,10 @@ func TestCreateWithWrongRequesterDataTypes(t *testing.T) {
|
|||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
}
|
}
|
||||||
err := storage.CreateAccessTokenSession(ctx, "signature-doesnt-matter", request)
|
err := storage.CreateAccessTokenSession(ctx, "signature-doesnt-matter", request)
|
||||||
require.EqualError(t, err, "requester's session must be of type openid.DefaultSession")
|
require.EqualError(t, err, "requester's session must be of type PinnipedSession")
|
||||||
|
|
||||||
request = &fosite.Request{
|
request = &fosite.Request{
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
Client: nil,
|
Client: nil,
|
||||||
}
|
}
|
||||||
err = storage.CreateAccessTokenSession(ctx, "signature-doesnt-matter", request)
|
err = storage.CreateAccessTokenSession(ctx, "signature-doesnt-matter", request)
|
||||||
@ -261,7 +255,7 @@ func TestCreateWithoutRequesterID(t *testing.T) {
|
|||||||
|
|
||||||
request := &fosite.Request{
|
request := &fosite.Request{
|
||||||
ID: "", // empty ID
|
ID: "", // empty ID
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
}
|
}
|
||||||
err := storage.CreateAccessTokenSession(ctx, "signature-doesnt-matter", request)
|
err := storage.CreateAccessTokenSession(ctx, "signature-doesnt-matter", request)
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/oauth2"
|
"github.com/ory/fosite/handler/oauth2"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
|
|
||||||
@ -19,6 +18,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/crud"
|
"go.pinniped.dev/internal/crud"
|
||||||
"go.pinniped.dev/internal/fositestorage"
|
"go.pinniped.dev/internal/fositestorage"
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -27,7 +27,7 @@ const (
|
|||||||
ErrInvalidAuthorizeRequestData = constable.Error("authorization request data must be present")
|
ErrInvalidAuthorizeRequestData = constable.Error("authorization request data must be present")
|
||||||
ErrInvalidAuthorizeRequestVersion = constable.Error("authorization request data has wrong version")
|
ErrInvalidAuthorizeRequestVersion = constable.Error("authorization request data has wrong version")
|
||||||
|
|
||||||
authorizeCodeStorageVersion = "1"
|
authorizeCodeStorageVersion = "2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ oauth2.AuthorizeCodeStorage = &authorizeCodeStorage{}
|
var _ oauth2.AuthorizeCodeStorage = &authorizeCodeStorage{}
|
||||||
@ -139,7 +139,7 @@ func NewValidEmptyAuthorizeCodeSession() *AuthorizeCodeSession {
|
|||||||
return &AuthorizeCodeSession{
|
return &AuthorizeCodeSession{
|
||||||
Request: &fosite.Request{
|
Request: &fosite.Request{
|
||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
|||||||
"redirect_uris": [
|
"redirect_uris": [
|
||||||
"ǖ枭kʍ切厦ȳ箦;¥ʊXĝ奨誷傥祩d",
|
"ǖ枭kʍ切厦ȳ箦;¥ʊXĝ奨誷傥祩d",
|
||||||
"zŇZ",
|
"zŇZ",
|
||||||
"優蒼ĊɌț訫DŽǽeʀO2ƚ&N"
|
"優蒼ĊɌț訫DŽǽeʀO2ƚ\u0026N"
|
||||||
],
|
],
|
||||||
"grant_types": [
|
"grant_types": [
|
||||||
"唐W6ɻ橩斚薛ɑƐ"
|
"唐W6ɻ橩斚薛ɑƐ"
|
||||||
@ -189,7 +189,7 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
|||||||
"ǔŭe[u@阽羂ŷ-Ĵ½輢OÅ濲喾H"
|
"ǔŭe[u@阽羂ŷ-Ĵ½輢OÅ濲喾H"
|
||||||
],
|
],
|
||||||
"scopes": [
|
"scopes": [
|
||||||
"G螩歐湡ƙı唡ɸğƎ&胢輢Ƈĵƚ"
|
"G螩歐湡ƙı唡ɸğƎ\u0026胢輢Ƈĵƚ"
|
||||||
],
|
],
|
||||||
"audience": [
|
"audience": [
|
||||||
"ě"
|
"ě"
|
||||||
@ -234,7 +234,7 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"token_endpoint_auth_method": "ƿʥǟȒ伉<x¹T鼓c吏",
|
"token_endpoint_auth_method": "ƿʥǟȒ伉\u003cx¹T鼓c吏",
|
||||||
"request_uris": [
|
"request_uris": [
|
||||||
"Ć捘j]=谅ʑɑɮ$Ól4Ȟ",
|
"Ć捘j]=谅ʑɑɮ$Ól4Ȟ",
|
||||||
",Q7钎漡臧n"
|
",Q7钎漡臧n"
|
||||||
@ -252,78 +252,89 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
|||||||
"form": {
|
"form": {
|
||||||
"褾攚ŝlĆ厦駳骪l拁乖¡J¿Ƈ妔": [
|
"褾攚ŝlĆ厦駳骪l拁乖¡J¿Ƈ妔": [
|
||||||
"懧¥ɂĵ~Čyʊ恀c\"NJřðȿ/",
|
"懧¥ɂĵ~Čyʊ恀c\"NJřðȿ/",
|
||||||
"裢?霃谥vƘ:ƿ/濔Aʉ<",
|
"裢?霃谥vƘ:ƿ/濔Aʉ\u003c",
|
||||||
"ȭ$奍囀Dž悷鵱民撲ʓeŘ嬀j¤"
|
"ȭ$奍囀Dž悷鵱民撲ʓeŘ嬀j¤"
|
||||||
],
|
],
|
||||||
"诞": [
|
"诞": [
|
||||||
"狲N<Cq罉ZPſĝEK郊©l",
|
"狲N\u003cCq罉ZPſĝEK郊©l",
|
||||||
"餚LJ/ɷȑ潠[ĝU噤'pX ",
|
"餚LJ/ɷȑ潠[ĝU噤'pX ",
|
||||||
"Y妶ǵ!ȁu狍ɶȳsčɦƦ诱"
|
"Y妶ǵ!ȁu狍ɶȳsčɦƦ诱"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"session": {
|
"session": {
|
||||||
|
"fosite": {
|
||||||
"Claims": {
|
"Claims": {
|
||||||
"JTI": "攬林Ñz焁糳¿o>Q鱙翑ȲŻ",
|
"JTI": "u妔隤ʑƍš駎竪0ɔ闏À1",
|
||||||
"Issuer": "锰劝旣樎Ȱ鍌#ȳńƩŴȭ",
|
"Issuer": "麤ã桒嘞\\摗Ǘū稖咾鎅ǸÖ绝TF",
|
||||||
"Subject": "绝TFNJĆw宵ɚeY48珎²",
|
"Subject": "巽ēđų蓼tùZ蛆鬣a\"ÙǞ0觢Û±",
|
||||||
"Audience": [
|
"Audience": [
|
||||||
"éã越|j¦鲶H股ƲLŋZ-{5£踉4"
|
"H股ƲL",
|
||||||
|
"肟v\u0026đehpƧ",
|
||||||
|
"5^驜Ŗ~ů崧軒q腟u尿"
|
||||||
],
|
],
|
||||||
"Nonce": "5^驜Ŗ~ů崧軒q腟u尿",
|
"Nonce": "ğ",
|
||||||
"ExpiresAt": "2065-11-30T13:47:03.613000626Z",
|
"ExpiresAt": "2016-11-22T21:33:58.460521133Z",
|
||||||
"IssuedAt": "1976-02-22T09:57:20.479850437Z",
|
"IssuedAt": "1990-07-25T23:42:07.055978334Z",
|
||||||
"RequestedAt": "2016-04-13T04:18:53.648949323Z",
|
"RequestedAt": "1971-01-30T00:23:36.377684025Z",
|
||||||
"AuthTime": "2098-07-12T04:38:54.034043015Z",
|
"AuthTime": "2088-11-09T12:09:14.051840239Z",
|
||||||
"AccessTokenHash": "嫯R",
|
"AccessTokenHash": "蕖¤'+ʣȍ瓁U4鞀",
|
||||||
"AuthenticationContextClassReference": "¤'+ʣ",
|
"AuthenticationContextClassReference": "ʏÑęN\u003c_z",
|
||||||
"AuthenticationMethodsReference": "L&ɽ艄ʬʏ",
|
"AuthenticationMethodsReference": "ț髄A",
|
||||||
"CodeHash": "ğǫ\\aȊ4ț髄Al",
|
"CodeHash": "4磔_袻vÓG-壧丵礴鋈k蟵pAɂʅ",
|
||||||
"Extra": {
|
"Extra": {
|
||||||
"PƢ曰": {
|
"#\u0026PƢ曰l騌蘙螤\\阏Đ镴Ƥm蔻ǭ\\鿞": 1677215584,
|
||||||
"ĸŴB岺Ð嫹Sx镯荫ő": [
|
"Y\u0026鶡萷ɵ啜s攦Ɩïdnǔ": {
|
||||||
843216989
|
",t猟i\u0026\u0026Q@ǤǟǗǪ飘ȱF?Ƈ": {
|
||||||
],
|
"~劰û橸ɽ銐ƭ?}H": null,
|
||||||
"疂ư墫ɓ": {
|
"癑勦e骲v0H晦XŘO溪V蔓": {
|
||||||
"\\BRë_g\"ʎ啴SƇMǃļ": {
|
"碼Ǫ": false
|
||||||
"ʦ4": false
|
|
||||||
},
|
|
||||||
"鶡萷ɵ啜s攦": null
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"曓蓳n匟鯘磹*金爃鶴滱ůĮǐ_c3#": 2520197933
|
"钻煐ɨəÅDČ{Ȩʦ4撎": [
|
||||||
|
3684968178
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Headers": {
|
"Headers": {
|
||||||
"Extra": {
|
"Extra": {
|
||||||
"寱ĊƑ÷Ƒ螞费Ďğ~劰û橸ɽ銐ƭ?}": {
|
"ĊdŘ鸨EJ毕懴řĬń戹": {
|
||||||
"ȜʁɁ;Bd謺錳4帳ŅǃĊd": {
|
"诳DT=3骜Ǹ,": {
|
||||||
"翢砜Fȏl鐉诳DT=3骜": {
|
"\u003e": {
|
||||||
"ų厷ɁOƪ穋嶿鳈恱va|载ǰɱ汶C": false
|
"ǰ": false
|
||||||
},
|
},
|
||||||
"鸨EJ毕懴řĬń戹%c": null
|
"ɁOƪ穋嶿鳈恱va": null
|
||||||
},
|
},
|
||||||
"室癑勦e骲v0H晦XŘO溪V蔓Ȍ+~ē": [
|
"豑觳翢砜Fȏl": [
|
||||||
954647573
|
927958776
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"麈ƵDǀ\\郂üţ垂": 1572524915
|
"埅ȜʁɁ;Bd謺錳4帳Ņ": 388005986
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ExpiresAt": {
|
"ExpiresAt": {
|
||||||
"'=ĸ闒NȢȰ.醋fʜ": "2031-10-18T22:07:34.950803105Z",
|
"C]ɲ'=ĸ闒NȢȰ.醋": "1970-07-19T18:03:29.902062193Z",
|
||||||
"ɦüHêQ仏1őƖ2Ė暮唍ǞʜƢú4": "2049-05-13T15:27:20.968432454Z"
|
"fɤȆʪ融ƆuŤn": "2064-01-24T20:34:16.593152073Z",
|
||||||
|
"爣縗ɦüHêQ仏1ő": "2102-03-17T06:24:40.256846902Z"
|
||||||
},
|
},
|
||||||
"Username": "+韁臯氃妪婝rȤ\"h丬鎒ơ娻}ɼƟȥE",
|
"Username": "韁臯氃妪婝rȤ\"h丬鎒ơ娻}ɼƟ",
|
||||||
"Subject": "龳ǽÙ龦O亾EW莛8嘶×姮c恭企"
|
"Subject": "闺髉龳ǽÙ龦O亾EW莛8嘶×"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"providerUID": "鵮碡ʯiŬŽ非Ĝ眧Ĭ葜SŦ餧Ĭ倏4",
|
||||||
|
"providerName": "nŐǛ3",
|
||||||
|
"providerType": "闣ʬ橳(ý綃ʃʚƟ覣k眐4Ĉt",
|
||||||
|
"oidc": {
|
||||||
|
"upstreamRefreshToken": "嵽痊w©Ź榨Q|ôɵt毇妬"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"requestedAudience": [
|
"requestedAudience": [
|
||||||
"邖ɐ5檄¬",
|
"6鉢緋uƴŤȱʀļÂ?墖\u003cƬb獭潜Ʃ饾"
|
||||||
"Ĭ葜SŦ餧Ĭ倏4ĵ嶼仒篻ɥ闣ʬ橳(ý綃"
|
|
||||||
],
|
],
|
||||||
"grantedAudience": [
|
"grantedAudience": [
|
||||||
"ʚƟ覣k眐4ĈtC嵽痊w©Ź榨Q|ô",
|
"|鬌R蜚蠣麹概÷驣7Ʀ澉1æɽ誮rʨ鷞"
|
||||||
"猊Ia瓕巈環_ɑ彨ƍ蛊ʚ£:設虝2"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"version": "1"
|
"version": "2"
|
||||||
}`
|
}`
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
fuzz "github.com/google/gofuzz"
|
fuzz "github.com/google/gofuzz"
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/oauth2"
|
"github.com/ory/fosite/handler/oauth2"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/square/go-jose.v2"
|
"gopkg.in/square/go-jose.v2"
|
||||||
@ -34,6 +33,8 @@ import (
|
|||||||
|
|
||||||
"go.pinniped.dev/internal/fositestorage"
|
"go.pinniped.dev/internal/fositestorage"
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const namespace = "test-ns"
|
const namespace = "test-ns"
|
||||||
@ -62,7 +63,7 @@ func TestAuthorizationCodeStorage(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"active":true,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
|
"pinniped-storage-data": []byte(`{"active":true,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}},"requestedAudience":null,"grantedAudience":null},"version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/authcode",
|
Type: "storage.pinniped.dev/authcode",
|
||||||
@ -81,7 +82,7 @@ func TestAuthorizationCodeStorage(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"active":false,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
|
"pinniped-storage-data": []byte(`{"active":false,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}},"requestedAudience":null,"grantedAudience":null},"version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/authcode",
|
Type: "storage.pinniped.dev/authcode",
|
||||||
@ -116,13 +117,7 @@ func TestAuthorizationCodeStorage(t *testing.T) {
|
|||||||
RequestedScope: nil,
|
RequestedScope: nil,
|
||||||
GrantedScope: nil,
|
GrantedScope: nil,
|
||||||
Form: url.Values{"key": []string{"val"}},
|
Form: url.Values{"key": []string{"val"}},
|
||||||
Session: &openid.DefaultSession{
|
Session: testutil.NewFakePinnipedSession(),
|
||||||
Claims: nil,
|
|
||||||
Headers: nil,
|
|
||||||
ExpiresAt: nil,
|
|
||||||
Username: "snorlax",
|
|
||||||
Subject: "panda",
|
|
||||||
},
|
|
||||||
RequestedAudience: nil,
|
RequestedAudience: nil,
|
||||||
GrantedAudience: nil,
|
GrantedAudience: nil,
|
||||||
}
|
}
|
||||||
@ -136,6 +131,8 @@ func TestAuthorizationCodeStorage(t *testing.T) {
|
|||||||
err = storage.InvalidateAuthorizeCodeSession(ctx, "fancy-signature")
|
err = storage.InvalidateAuthorizeCodeSession(ctx, "fancy-signature")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testutil.LogActualJSONFromCreateAction(t, client, 0) // makes it easier to update expected values when needed
|
||||||
|
testutil.LogActualJSONFromUpdateAction(t, client, 3) // makes it easier to update expected values when needed
|
||||||
require.Equal(t, wantActions, client.Actions())
|
require.Equal(t, wantActions, client.Actions())
|
||||||
|
|
||||||
// Doing a Get on an invalidated session should still return the session, but also return an error.
|
// Doing a Get on an invalidated session should still return the session, but also return an error.
|
||||||
@ -173,7 +170,7 @@ func TestInvalidateWhenConflictOnUpdateHappens(t *testing.T) {
|
|||||||
request := &fosite.Request{
|
request := &fosite.Request{
|
||||||
ID: "some-request-id",
|
ID: "some-request-id",
|
||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
Session: &openid.DefaultSession{},
|
Session: testutil.NewFakePinnipedSession(),
|
||||||
}
|
}
|
||||||
err := storage.CreateAuthorizeCodeSession(ctx, "fancy-signature", request)
|
err := storage.CreateAuthorizeCodeSession(ctx, "fancy-signature", request)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -193,7 +190,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"not-the-right-version", "active": true}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"not-the-right-version","active": true}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/authcode",
|
Type: "storage.pinniped.dev/authcode",
|
||||||
@ -203,7 +200,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
|
|
||||||
_, err = storage.GetAuthorizeCodeSession(ctx, "fancy-signature", nil)
|
_, err = storage.GetAuthorizeCodeSession(ctx, "fancy-signature", nil)
|
||||||
|
|
||||||
require.EqualError(t, err, "authorization request data has wrong version: authorization code session for fancy-signature has version not-the-right-version instead of 1")
|
require.EqualError(t, err, "authorization request data has wrong version: authorization code session for fancy-signature has version not-the-right-version instead of 2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNilSessionRequest(t *testing.T) {
|
func TestNilSessionRequest(t *testing.T) {
|
||||||
@ -218,7 +215,7 @@ func TestNilSessionRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value", "version":"1", "active": true}`),
|
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value", "version":"2", "active": true}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/authcode",
|
Type: "storage.pinniped.dev/authcode",
|
||||||
@ -246,10 +243,10 @@ func TestCreateWithWrongRequesterDataTypes(t *testing.T) {
|
|||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
}
|
}
|
||||||
err := storage.CreateAuthorizeCodeSession(ctx, "signature-doesnt-matter", request)
|
err := storage.CreateAuthorizeCodeSession(ctx, "signature-doesnt-matter", request)
|
||||||
require.EqualError(t, err, "requester's session must be of type openid.DefaultSession")
|
require.EqualError(t, err, "requester's session must be of type PinnipedSession")
|
||||||
|
|
||||||
request = &fosite.Request{
|
request = &fosite.Request{
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
Client: nil,
|
Client: nil,
|
||||||
}
|
}
|
||||||
err = storage.CreateAuthorizeCodeSession(ctx, "signature-doesnt-matter", request)
|
err = storage.CreateAuthorizeCodeSession(ctx, "signature-doesnt-matter", request)
|
||||||
@ -274,7 +271,7 @@ func TestFuzzAndJSONNewValidEmptyAuthorizeCodeSession(t *testing.T) {
|
|||||||
|
|
||||||
// checked above
|
// checked above
|
||||||
defaultClient := validSession.Request.Client.(*clientregistry.Client)
|
defaultClient := validSession.Request.Client.(*clientregistry.Client)
|
||||||
defaultSession := validSession.Request.Session.(*openid.DefaultSession)
|
pinnipedSession := validSession.Request.Session.(*psession.PinnipedSession)
|
||||||
|
|
||||||
// makes it easier to use a raw string
|
// makes it easier to use a raw string
|
||||||
replacer := strings.NewReplacer("`", "a")
|
replacer := strings.NewReplacer("`", "a")
|
||||||
@ -297,12 +294,12 @@ func TestFuzzAndJSONNewValidEmptyAuthorizeCodeSession(t *testing.T) {
|
|||||||
*fc = defaultClient
|
*fc = defaultClient
|
||||||
},
|
},
|
||||||
func(fs *fosite.Session, c fuzz.Continue) {
|
func(fs *fosite.Session, c fuzz.Continue) {
|
||||||
c.Fuzz(defaultSession)
|
c.Fuzz(pinnipedSession)
|
||||||
*fs = defaultSession
|
*fs = pinnipedSession
|
||||||
},
|
},
|
||||||
|
|
||||||
// these types contain an interface{} that we need to handle
|
// these types contain an interface{} that we need to handle
|
||||||
// this is safe because we explicitly provide the openid.DefaultSession concrete type
|
// this is safe because we explicitly provide the PinnipedSession concrete type
|
||||||
func(value *map[string]interface{}, c fuzz.Continue) {
|
func(value *map[string]interface{}, c fuzz.Continue) {
|
||||||
// cover all the JSON data types just in case
|
// cover all the JSON data types just in case
|
||||||
*value = map[string]interface{}{
|
*value = map[string]interface{}{
|
||||||
@ -382,7 +379,7 @@ func TestFuzzAndJSONNewValidEmptyAuthorizeCodeSession(t *testing.T) {
|
|||||||
|
|
||||||
// set these to match CreateAuthorizeCodeSession so that .JSONEq works
|
// set these to match CreateAuthorizeCodeSession so that .JSONEq works
|
||||||
validSession.Active = true
|
validSession.Active = true
|
||||||
validSession.Version = "1"
|
validSession.Version = "2"
|
||||||
|
|
||||||
validSessionJSONBytes, err := json.MarshalIndent(validSession, "", "\t")
|
validSessionJSONBytes, err := json.MarshalIndent(validSession, "", "\t")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -5,16 +5,16 @@ package fositestorage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
|
|
||||||
"go.pinniped.dev/internal/constable"
|
"go.pinniped.dev/internal/constable"
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ErrInvalidRequestType = constable.Error("requester must be of type fosite.Request")
|
ErrInvalidRequestType = constable.Error("requester must be of type fosite.Request")
|
||||||
ErrInvalidClientType = constable.Error("requester's client must be of type clientregistry.Client")
|
ErrInvalidClientType = constable.Error("requester's client must be of type clientregistry.Client")
|
||||||
ErrInvalidSessionType = constable.Error("requester's session must be of type openid.DefaultSession")
|
ErrInvalidSessionType = constable.Error("requester's session must be of type PinnipedSession")
|
||||||
StorageRequestIDLabelName = "storage.pinniped.dev/request-id" //nolint:gosec // this is not a credential
|
StorageRequestIDLabelName = "storage.pinniped.dev/request-id" //nolint:gosec // this is not a credential
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ func ValidateAndExtractAuthorizeRequest(requester fosite.Requester) (*fosite.Req
|
|||||||
if !ok2 {
|
if !ok2 {
|
||||||
return nil, ErrInvalidClientType
|
return nil, ErrInvalidClientType
|
||||||
}
|
}
|
||||||
_, ok3 := request.Session.(*openid.DefaultSession)
|
_, ok3 := request.Session.(*psession.PinnipedSession)
|
||||||
if !ok3 {
|
if !ok3 {
|
||||||
return nil, ErrInvalidSessionType
|
return nil, ErrInvalidSessionType
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/crud"
|
"go.pinniped.dev/internal/crud"
|
||||||
"go.pinniped.dev/internal/fositestorage"
|
"go.pinniped.dev/internal/fositestorage"
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -27,7 +28,7 @@ const (
|
|||||||
ErrInvalidOIDCRequestData = constable.Error("oidc request data must be present")
|
ErrInvalidOIDCRequestData = constable.Error("oidc request data must be present")
|
||||||
ErrMalformedAuthorizationCode = constable.Error("malformed authorization code")
|
ErrMalformedAuthorizationCode = constable.Error("malformed authorization code")
|
||||||
|
|
||||||
oidcStorageVersion = "1"
|
oidcStorageVersion = "2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ openid.OpenIDConnectRequestStorage = &openIDConnectRequestStorage{}
|
var _ openid.OpenIDConnectRequestStorage = &openIDConnectRequestStorage{}
|
||||||
@ -112,7 +113,7 @@ func newValidEmptyOIDCSession() *session {
|
|||||||
return &session{
|
return &session{
|
||||||
Request: &fosite.Request{
|
Request: &fosite.Request{
|
||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@ import (
|
|||||||
coretesting "k8s.io/client-go/testing"
|
coretesting "k8s.io/client-go/testing"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const namespace = "test-ns"
|
const namespace = "test-ns"
|
||||||
@ -50,7 +52,7 @@ func TestOpenIdConnectStorage(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}},"requestedAudience":null,"grantedAudience":null},"version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/oidc",
|
Type: "storage.pinniped.dev/oidc",
|
||||||
@ -87,13 +89,7 @@ func TestOpenIdConnectStorage(t *testing.T) {
|
|||||||
RequestedScope: nil,
|
RequestedScope: nil,
|
||||||
GrantedScope: nil,
|
GrantedScope: nil,
|
||||||
Form: url.Values{"key": []string{"val"}},
|
Form: url.Values{"key": []string{"val"}},
|
||||||
Session: &openid.DefaultSession{
|
Session: testutil.NewFakePinnipedSession(),
|
||||||
Claims: nil,
|
|
||||||
Headers: nil,
|
|
||||||
ExpiresAt: nil,
|
|
||||||
Username: "snorlax",
|
|
||||||
Subject: "panda",
|
|
||||||
},
|
|
||||||
RequestedAudience: nil,
|
RequestedAudience: nil,
|
||||||
GrantedAudience: nil,
|
GrantedAudience: nil,
|
||||||
}
|
}
|
||||||
@ -107,6 +103,7 @@ func TestOpenIdConnectStorage(t *testing.T) {
|
|||||||
err = storage.DeleteOpenIDConnectSession(ctx, "fancy-code.fancy-signature")
|
err = storage.DeleteOpenIDConnectSession(ctx, "fancy-code.fancy-signature")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testutil.LogActualJSONFromCreateAction(t, client, 0) // makes it easier to update expected values when needed
|
||||||
require.Equal(t, wantActions, client.Actions())
|
require.Equal(t, wantActions, client.Actions())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +127,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"not-the-right-version"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"not-the-right-version"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/oidc",
|
Type: "storage.pinniped.dev/oidc",
|
||||||
@ -140,7 +137,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
|
|
||||||
_, err = storage.GetOpenIDConnectSession(ctx, "fancy-code.fancy-signature", nil)
|
_, err = storage.GetOpenIDConnectSession(ctx, "fancy-code.fancy-signature", nil)
|
||||||
|
|
||||||
require.EqualError(t, err, "oidc request data has wrong version: oidc session for fancy-signature has version not-the-right-version instead of 1")
|
require.EqualError(t, err, "oidc request data has wrong version: oidc session for fancy-signature has version not-the-right-version instead of 2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNilSessionRequest(t *testing.T) {
|
func TestNilSessionRequest(t *testing.T) {
|
||||||
@ -155,7 +152,7 @@ func TestNilSessionRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"1"}`),
|
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/oidc",
|
Type: "storage.pinniped.dev/oidc",
|
||||||
@ -183,10 +180,10 @@ func TestCreateWithWrongRequesterDataTypes(t *testing.T) {
|
|||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
}
|
}
|
||||||
err := storage.CreateOpenIDConnectSession(ctx, "authcode.signature-doesnt-matter", request)
|
err := storage.CreateOpenIDConnectSession(ctx, "authcode.signature-doesnt-matter", request)
|
||||||
require.EqualError(t, err, "requester's session must be of type openid.DefaultSession")
|
require.EqualError(t, err, "requester's session must be of type PinnipedSession")
|
||||||
|
|
||||||
request = &fosite.Request{
|
request = &fosite.Request{
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
Client: nil,
|
Client: nil,
|
||||||
}
|
}
|
||||||
err = storage.CreateOpenIDConnectSession(ctx, "authcode.signature-doesnt-matter", request)
|
err = storage.CreateOpenIDConnectSession(ctx, "authcode.signature-doesnt-matter", request)
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
"github.com/ory/fosite/handler/pkce"
|
"github.com/ory/fosite/handler/pkce"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
@ -18,6 +17,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/crud"
|
"go.pinniped.dev/internal/crud"
|
||||||
"go.pinniped.dev/internal/fositestorage"
|
"go.pinniped.dev/internal/fositestorage"
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -26,7 +26,7 @@ const (
|
|||||||
ErrInvalidPKCERequestVersion = constable.Error("pkce request data has wrong version")
|
ErrInvalidPKCERequestVersion = constable.Error("pkce request data has wrong version")
|
||||||
ErrInvalidPKCERequestData = constable.Error("pkce request data must be present")
|
ErrInvalidPKCERequestData = constable.Error("pkce request data must be present")
|
||||||
|
|
||||||
pkceStorageVersion = "1"
|
pkceStorageVersion = "2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ pkce.PKCERequestStorage = &pkceStorage{}
|
var _ pkce.PKCERequestStorage = &pkceStorage{}
|
||||||
@ -96,7 +96,7 @@ func newValidEmptyPKCESession() *session {
|
|||||||
return &session{
|
return &session{
|
||||||
Request: &fosite.Request{
|
Request: &fosite.Request{
|
||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
"github.com/ory/fosite/handler/pkce"
|
"github.com/ory/fosite/handler/pkce"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -23,6 +22,8 @@ import (
|
|||||||
coretesting "k8s.io/client-go/testing"
|
coretesting "k8s.io/client-go/testing"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const namespace = "test-ns"
|
const namespace = "test-ns"
|
||||||
@ -51,7 +52,7 @@ func TestPKCEStorage(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}},"requestedAudience":null,"grantedAudience":null},"version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/pkce",
|
Type: "storage.pinniped.dev/pkce",
|
||||||
@ -88,13 +89,7 @@ func TestPKCEStorage(t *testing.T) {
|
|||||||
RequestedScope: nil,
|
RequestedScope: nil,
|
||||||
GrantedScope: nil,
|
GrantedScope: nil,
|
||||||
Form: url.Values{"key": []string{"val"}},
|
Form: url.Values{"key": []string{"val"}},
|
||||||
Session: &openid.DefaultSession{
|
Session: testutil.NewFakePinnipedSession(),
|
||||||
Claims: nil,
|
|
||||||
Headers: nil,
|
|
||||||
ExpiresAt: nil,
|
|
||||||
Username: "snorlax",
|
|
||||||
Subject: "panda",
|
|
||||||
},
|
|
||||||
RequestedAudience: nil,
|
RequestedAudience: nil,
|
||||||
GrantedAudience: nil,
|
GrantedAudience: nil,
|
||||||
}
|
}
|
||||||
@ -108,6 +103,7 @@ func TestPKCEStorage(t *testing.T) {
|
|||||||
err = storage.DeletePKCERequestSession(ctx, "fancy-signature")
|
err = storage.DeletePKCERequestSession(ctx, "fancy-signature")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testutil.LogActualJSONFromCreateAction(t, client, 0) // makes it easier to update expected values when needed
|
||||||
require.Equal(t, wantActions, client.Actions())
|
require.Equal(t, wantActions, client.Actions())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +130,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"not-the-right-version"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"not-the-right-version"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/pkce",
|
Type: "storage.pinniped.dev/pkce",
|
||||||
@ -144,7 +140,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
|
|
||||||
_, err = storage.GetPKCERequestSession(ctx, "fancy-signature", nil)
|
_, err = storage.GetPKCERequestSession(ctx, "fancy-signature", nil)
|
||||||
|
|
||||||
require.EqualError(t, err, "pkce request data has wrong version: pkce session for fancy-signature has version not-the-right-version instead of 1")
|
require.EqualError(t, err, "pkce request data has wrong version: pkce session for fancy-signature has version not-the-right-version instead of 2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNilSessionRequest(t *testing.T) {
|
func TestNilSessionRequest(t *testing.T) {
|
||||||
@ -162,7 +158,7 @@ func TestNilSessionRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"1"}`),
|
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/pkce",
|
Type: "storage.pinniped.dev/pkce",
|
||||||
@ -190,10 +186,10 @@ func TestCreateWithWrongRequesterDataTypes(t *testing.T) {
|
|||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
}
|
}
|
||||||
err := storage.CreatePKCERequestSession(ctx, "signature-doesnt-matter", request)
|
err := storage.CreatePKCERequestSession(ctx, "signature-doesnt-matter", request)
|
||||||
require.EqualError(t, err, "requester's session must be of type openid.DefaultSession")
|
require.EqualError(t, err, "requester's session must be of type PinnipedSession")
|
||||||
|
|
||||||
request = &fosite.Request{
|
request = &fosite.Request{
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
Client: nil,
|
Client: nil,
|
||||||
}
|
}
|
||||||
err = storage.CreatePKCERequestSession(ctx, "signature-doesnt-matter", request)
|
err = storage.CreatePKCERequestSession(ctx, "signature-doesnt-matter", request)
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/oauth2"
|
"github.com/ory/fosite/handler/oauth2"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
|
|
||||||
@ -18,6 +17,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/crud"
|
"go.pinniped.dev/internal/crud"
|
||||||
"go.pinniped.dev/internal/fositestorage"
|
"go.pinniped.dev/internal/fositestorage"
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -26,7 +26,7 @@ const (
|
|||||||
ErrInvalidRefreshTokenRequestVersion = constable.Error("refresh token request data has wrong version")
|
ErrInvalidRefreshTokenRequestVersion = constable.Error("refresh token request data has wrong version")
|
||||||
ErrInvalidRefreshTokenRequestData = constable.Error("refresh token request data must be present")
|
ErrInvalidRefreshTokenRequestData = constable.Error("refresh token request data must be present")
|
||||||
|
|
||||||
refreshTokenStorageVersion = "1"
|
refreshTokenStorageVersion = "2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RevocationStorage interface {
|
type RevocationStorage interface {
|
||||||
@ -110,7 +110,7 @@ func newValidEmptyRefreshTokenSession() *session {
|
|||||||
return &session{
|
return &session{
|
||||||
Request: &fosite.Request{
|
Request: &fosite.Request{
|
||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@ -22,6 +21,8 @@ import (
|
|||||||
coretesting "k8s.io/client-go/testing"
|
coretesting "k8s.io/client-go/testing"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
|
"go.pinniped.dev/internal/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const namespace = "test-ns"
|
const namespace = "test-ns"
|
||||||
@ -50,7 +51,7 @@ func TestRefreshTokenStorage(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}},"requestedAudience":null,"grantedAudience":null},"version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/refresh-token",
|
Type: "storage.pinniped.dev/refresh-token",
|
||||||
@ -87,13 +88,7 @@ func TestRefreshTokenStorage(t *testing.T) {
|
|||||||
RequestedScope: nil,
|
RequestedScope: nil,
|
||||||
GrantedScope: nil,
|
GrantedScope: nil,
|
||||||
Form: url.Values{"key": []string{"val"}},
|
Form: url.Values{"key": []string{"val"}},
|
||||||
Session: &openid.DefaultSession{
|
Session: testutil.NewFakePinnipedSession(),
|
||||||
Claims: nil,
|
|
||||||
Headers: nil,
|
|
||||||
ExpiresAt: nil,
|
|
||||||
Username: "snorlax",
|
|
||||||
Subject: "panda",
|
|
||||||
},
|
|
||||||
RequestedAudience: nil,
|
RequestedAudience: nil,
|
||||||
GrantedAudience: nil,
|
GrantedAudience: nil,
|
||||||
}
|
}
|
||||||
@ -107,6 +102,7 @@ func TestRefreshTokenStorage(t *testing.T) {
|
|||||||
err = storage.DeleteRefreshTokenSession(ctx, "fancy-signature")
|
err = storage.DeleteRefreshTokenSession(ctx, "fancy-signature")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testutil.LogActualJSONFromCreateAction(t, client, 0) // makes it easier to update expected values when needed
|
||||||
require.Equal(t, wantActions, client.Actions())
|
require.Equal(t, wantActions, client.Actions())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +121,7 @@ func TestRefreshTokenStorageRevocation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}},"requestedAudience":null,"grantedAudience":null},"version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/refresh-token",
|
Type: "storage.pinniped.dev/refresh-token",
|
||||||
@ -152,10 +148,7 @@ func TestRefreshTokenStorageRevocation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Form: url.Values{"key": []string{"val"}},
|
Form: url.Values{"key": []string{"val"}},
|
||||||
Session: &openid.DefaultSession{
|
Session: testutil.NewFakePinnipedSession(),
|
||||||
Username: "snorlax",
|
|
||||||
Subject: "panda",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
err := storage.CreateRefreshTokenSession(ctx, "fancy-signature", request)
|
err := storage.CreateRefreshTokenSession(ctx, "fancy-signature", request)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -164,6 +157,7 @@ func TestRefreshTokenStorageRevocation(t *testing.T) {
|
|||||||
err = storage.RevokeRefreshToken(ctx, "abcd-1")
|
err = storage.RevokeRefreshToken(ctx, "abcd-1")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testutil.LogActualJSONFromCreateAction(t, client, 0) // makes it easier to update expected values when needed
|
||||||
require.Equal(t, wantActions, client.Actions())
|
require.Equal(t, wantActions, client.Actions())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +184,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"not-the-right-version"}`),
|
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"not-the-right-version"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/refresh-token",
|
Type: "storage.pinniped.dev/refresh-token",
|
||||||
@ -200,7 +194,7 @@ func TestWrongVersion(t *testing.T) {
|
|||||||
|
|
||||||
_, err = storage.GetRefreshTokenSession(ctx, "fancy-signature", nil)
|
_, err = storage.GetRefreshTokenSession(ctx, "fancy-signature", nil)
|
||||||
|
|
||||||
require.EqualError(t, err, "refresh token request data has wrong version: refresh token session for fancy-signature has version not-the-right-version instead of 1")
|
require.EqualError(t, err, "refresh token request data has wrong version: refresh token session for fancy-signature has version not-the-right-version instead of 2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNilSessionRequest(t *testing.T) {
|
func TestNilSessionRequest(t *testing.T) {
|
||||||
@ -218,7 +212,7 @@ func TestNilSessionRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"1"}`),
|
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"2"}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
},
|
},
|
||||||
Type: "storage.pinniped.dev/refresh-token",
|
Type: "storage.pinniped.dev/refresh-token",
|
||||||
@ -246,10 +240,10 @@ func TestCreateWithWrongRequesterDataTypes(t *testing.T) {
|
|||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
}
|
}
|
||||||
err := storage.CreateRefreshTokenSession(ctx, "signature-doesnt-matter", request)
|
err := storage.CreateRefreshTokenSession(ctx, "signature-doesnt-matter", request)
|
||||||
require.EqualError(t, err, "requester's session must be of type openid.DefaultSession")
|
require.EqualError(t, err, "requester's session must be of type PinnipedSession")
|
||||||
|
|
||||||
request = &fosite.Request{
|
request = &fosite.Request{
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
Client: nil,
|
Client: nil,
|
||||||
}
|
}
|
||||||
err = storage.CreateRefreshTokenSession(ctx, "signature-doesnt-matter", request)
|
err = storage.CreateRefreshTokenSession(ctx, "signature-doesnt-matter", request)
|
||||||
@ -261,7 +255,7 @@ func TestCreateWithoutRequesterID(t *testing.T) {
|
|||||||
|
|
||||||
request := &fosite.Request{
|
request := &fosite.Request{
|
||||||
ID: "", // empty ID
|
ID: "", // empty ID
|
||||||
Session: &openid.DefaultSession{},
|
Session: &psession.PinnipedSession{},
|
||||||
Client: &clientregistry.Client{},
|
Client: &clientregistry.Client{},
|
||||||
}
|
}
|
||||||
err := storage.CreateRefreshTokenSession(ctx, "signature-doesnt-matter", request)
|
err := storage.CreateRefreshTokenSession(ctx, "signature-doesnt-matter", request)
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/oidc/downstreamsession"
|
"go.pinniped.dev/internal/oidc/downstreamsession"
|
||||||
"go.pinniped.dev/internal/oidc/provider"
|
"go.pinniped.dev/internal/oidc/provider"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||||
"go.pinniped.dev/pkg/oidcclient/pkce"
|
"go.pinniped.dev/pkg/oidcclient/pkce"
|
||||||
)
|
)
|
||||||
@ -173,13 +174,15 @@ func handleAuthRequestForOIDCUpstreamAuthcodeGrant(
|
|||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
_, err := oauthHelper.NewAuthorizeResponse(r.Context(), authorizeRequester, &openid.DefaultSession{
|
_, err := oauthHelper.NewAuthorizeResponse(r.Context(), authorizeRequester, &psession.PinnipedSession{
|
||||||
|
Fosite: &openid.DefaultSession{
|
||||||
Claims: &jwt.IDTokenClaims{
|
Claims: &jwt.IDTokenClaims{
|
||||||
// Temporary claim values to allow `NewAuthorizeResponse` to perform other OIDC validations.
|
// Temporary claim values to allow `NewAuthorizeResponse` to perform other OIDC validations.
|
||||||
Subject: "none",
|
Subject: "none",
|
||||||
AuthTime: now,
|
AuthTime: now,
|
||||||
RequestedAt: now,
|
RequestedAt: now,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester, err)
|
return writeAuthorizeError(w, oauthHelper, authorizeRequester, err)
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/oidc"
|
"go.pinniped.dev/internal/oidc"
|
||||||
"go.pinniped.dev/internal/oidc/provider"
|
"go.pinniped.dev/internal/oidc/provider"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -35,19 +36,21 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// MakeDownstreamSession creates a downstream OIDC session.
|
// MakeDownstreamSession creates a downstream OIDC session.
|
||||||
func MakeDownstreamSession(subject string, username string, groups []string) *openid.DefaultSession {
|
func MakeDownstreamSession(subject string, username string, groups []string) *psession.PinnipedSession {
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
openIDSession := &openid.DefaultSession{
|
openIDSession := &psession.PinnipedSession{
|
||||||
|
Fosite: &openid.DefaultSession{
|
||||||
Claims: &jwt.IDTokenClaims{
|
Claims: &jwt.IDTokenClaims{
|
||||||
Subject: subject,
|
Subject: subject,
|
||||||
RequestedAt: now,
|
RequestedAt: now,
|
||||||
AuthTime: now,
|
AuthTime: now,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if groups == nil {
|
if groups == nil {
|
||||||
groups = []string{}
|
groups = []string{}
|
||||||
}
|
}
|
||||||
openIDSession.Claims.Extra = map[string]interface{}{
|
openIDSession.IDTokenClaims().Extra = map[string]interface{}{
|
||||||
oidc.DownstreamUsernameClaim: username,
|
oidc.DownstreamUsernameClaim: username,
|
||||||
oidc.DownstreamGroupsClaim: groups,
|
oidc.DownstreamGroupsClaim: groups,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package token provides a handler for the OIDC token endpoint.
|
// Package token provides a handler for the OIDC token endpoint.
|
||||||
@ -8,19 +8,19 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
|
|
||||||
"go.pinniped.dev/internal/httputil/httperr"
|
"go.pinniped.dev/internal/httputil/httperr"
|
||||||
"go.pinniped.dev/internal/oidc"
|
"go.pinniped.dev/internal/oidc"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewHandler(
|
func NewHandler(
|
||||||
oauthHelper fosite.OAuth2Provider,
|
oauthHelper fosite.OAuth2Provider,
|
||||||
) http.Handler {
|
) http.Handler {
|
||||||
return httperr.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
return httperr.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
||||||
var session openid.DefaultSession
|
session := psession.NewPinnipedSession()
|
||||||
accessRequest, err := oauthHelper.NewAccessRequest(r.Context(), r, &session)
|
accessRequest, err := oauthHelper.NewAccessRequest(r.Context(), r, session)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
plog.Info("token request error", oidc.FositeErrorForLog(err)...)
|
plog.Info("token request error", oidc.FositeErrorForLog(err)...)
|
||||||
oauthHelper.WriteAccessError(w, accessRequest, err)
|
oauthHelper.WriteAccessError(w, accessRequest, err)
|
||||||
|
@ -46,6 +46,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
"go.pinniped.dev/internal/oidc"
|
"go.pinniped.dev/internal/oidc"
|
||||||
"go.pinniped.dev/internal/oidc/jwks"
|
"go.pinniped.dev/internal/oidc/jwks"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
"go.pinniped.dev/internal/testutil"
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/internal/testutil/oidctestutil"
|
"go.pinniped.dev/internal/testutil/oidctestutil"
|
||||||
)
|
)
|
||||||
@ -58,7 +59,6 @@ const (
|
|||||||
goodNonce = "some-nonce-value-with-enough-bytes-to-exceed-min-allowed"
|
goodNonce = "some-nonce-value-with-enough-bytes-to-exceed-min-allowed"
|
||||||
goodSubject = "https://issuer?sub=some-subject"
|
goodSubject = "https://issuer?sub=some-subject"
|
||||||
goodUsername = "some-username"
|
goodUsername = "some-username"
|
||||||
goodGroups = "group1,groups2"
|
|
||||||
|
|
||||||
hmacSecret = "this needs to be at least 32 characters to meet entropy requirements"
|
hmacSecret = "this needs to be at least 32 characters to meet entropy requirements"
|
||||||
|
|
||||||
@ -72,6 +72,8 @@ const (
|
|||||||
var (
|
var (
|
||||||
goodAuthTime = time.Date(1, 2, 3, 4, 5, 6, 7, time.UTC)
|
goodAuthTime = time.Date(1, 2, 3, 4, 5, 6, 7, time.UTC)
|
||||||
goodRequestedAtTime = time.Date(7, 6, 5, 4, 3, 2, 1, time.UTC)
|
goodRequestedAtTime = time.Date(7, 6, 5, 4, 3, 2, 1, time.UTC)
|
||||||
|
goodGroups = []string{"group1", "groups2"}
|
||||||
|
expectedGoodGroups = []interface{}{"group1", "groups2"}
|
||||||
|
|
||||||
hmacSecretFunc = func() []byte {
|
hmacSecretFunc = func() []byte {
|
||||||
return []byte(hmacSecret)
|
return []byte(hmacSecret)
|
||||||
@ -813,7 +815,7 @@ func TestTokenExchange(t *testing.T) {
|
|||||||
require.Equal(t, goodSubject, tokenClaims["sub"])
|
require.Equal(t, goodSubject, tokenClaims["sub"])
|
||||||
require.Equal(t, goodIssuer, tokenClaims["iss"])
|
require.Equal(t, goodIssuer, tokenClaims["iss"])
|
||||||
require.Equal(t, goodUsername, tokenClaims["username"])
|
require.Equal(t, goodUsername, tokenClaims["username"])
|
||||||
require.Equal(t, goodGroups, tokenClaims["groups"])
|
require.Equal(t, expectedGoodGroups, tokenClaims["groups"])
|
||||||
|
|
||||||
// Also assert that some are the same as the original downstream ID token.
|
// Also assert that some are the same as the original downstream ID token.
|
||||||
requireClaimsAreEqual(t, "iss", claimsOfFirstIDToken, tokenClaims) // issuer
|
requireClaimsAreEqual(t, "iss", claimsOfFirstIDToken, tokenClaims) // issuer
|
||||||
@ -1358,7 +1360,8 @@ func makeOauthHelperWithNilPrivateJWTSigningKey(
|
|||||||
func simulateAuthEndpointHavingAlreadyRun(t *testing.T, authRequest *http.Request, oauthHelper fosite.OAuth2Provider) fosite.AuthorizeResponder {
|
func simulateAuthEndpointHavingAlreadyRun(t *testing.T, authRequest *http.Request, oauthHelper fosite.OAuth2Provider) fosite.AuthorizeResponder {
|
||||||
// We only set the fields in the session that Fosite wants us to set.
|
// We only set the fields in the session that Fosite wants us to set.
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
session := &openid.DefaultSession{
|
session := &psession.PinnipedSession{
|
||||||
|
Fosite: &openid.DefaultSession{
|
||||||
Claims: &jwt.IDTokenClaims{
|
Claims: &jwt.IDTokenClaims{
|
||||||
Subject: goodSubject,
|
Subject: goodSubject,
|
||||||
RequestedAt: goodRequestedAtTime,
|
RequestedAt: goodRequestedAtTime,
|
||||||
@ -1370,6 +1373,12 @@ func simulateAuthEndpointHavingAlreadyRun(t *testing.T, authRequest *http.Reques
|
|||||||
},
|
},
|
||||||
Subject: "", // not used, note that callback_handler.go does not set this
|
Subject: "", // not used, note that callback_handler.go does not set this
|
||||||
Username: "", // not used, note that callback_handler.go does not set this
|
Username: "", // not used, note that callback_handler.go does not set this
|
||||||
|
},
|
||||||
|
Custom: &psession.PinnipedSessionData{
|
||||||
|
OIDC: &psession.OIDCSessionData{
|
||||||
|
UpstreamRefreshToken: "starting-fake-refresh-token",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
authRequester, err := oauthHelper.NewAuthorizeRequest(ctx, authRequest)
|
authRequester, err := oauthHelper.NewAuthorizeRequest(ctx, authRequest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -1588,19 +1597,19 @@ func requireValidStoredRequest(
|
|||||||
require.Equal(t, wantRequestForm, request.GetRequestForm()) // Fosite stores access token request without form
|
require.Equal(t, wantRequestForm, request.GetRequestForm()) // Fosite stores access token request without form
|
||||||
|
|
||||||
// Cast session to the type we think it should be.
|
// Cast session to the type we think it should be.
|
||||||
session, ok := request.GetSession().(*openid.DefaultSession)
|
session, ok := request.GetSession().(*psession.PinnipedSession)
|
||||||
require.Truef(t, ok, "could not cast %T to %T", request.GetSession(), &openid.DefaultSession{})
|
require.Truef(t, ok, "could not cast %T to %T", request.GetSession(), &psession.PinnipedSession{})
|
||||||
|
|
||||||
// Assert that the session claims are what we think they should be, but only if we are doing OIDC.
|
// Assert that the session claims are what we think they should be, but only if we are doing OIDC.
|
||||||
if contains(wantGrantedScopes, "openid") {
|
if contains(wantGrantedScopes, "openid") {
|
||||||
claims := session.Claims
|
claims := session.Fosite.Claims
|
||||||
require.Empty(t, claims.JTI) // When claims.JTI is empty, Fosite will generate a UUID for this field.
|
require.Empty(t, claims.JTI) // When claims.JTI is empty, Fosite will generate a UUID for this field.
|
||||||
require.Equal(t, goodSubject, claims.Subject)
|
require.Equal(t, goodSubject, claims.Subject)
|
||||||
|
|
||||||
// Our custom claims from the authorize endpoint should still be set.
|
// Our custom claims from the authorize endpoint should still be set.
|
||||||
require.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"username": goodUsername,
|
"username": goodUsername,
|
||||||
"groups": goodGroups,
|
"groups": expectedGoodGroups,
|
||||||
}, claims.Extra)
|
}, claims.Extra)
|
||||||
|
|
||||||
// We are in charge of setting these fields. For the purpose of testing, we ensure that the
|
// We are in charge of setting these fields. For the purpose of testing, we ensure that the
|
||||||
@ -1610,7 +1619,7 @@ func requireValidStoredRequest(
|
|||||||
|
|
||||||
// These fields will all be given good defaults by fosite at runtime and we only need to use them
|
// These fields will all be given good defaults by fosite at runtime and we only need to use them
|
||||||
// if we want to override the default behaviors. We currently don't need to override these defaults,
|
// if we want to override the default behaviors. We currently don't need to override these defaults,
|
||||||
// so they do not end up being stored. Fosite sets its defaults at runtime in openid.DefaultSession's
|
// so they do not end up being stored. Fosite sets its defaults at runtime in openid.DefaultStrategy's
|
||||||
// GenerateIDToken() method.
|
// GenerateIDToken() method.
|
||||||
require.Empty(t, claims.Issuer)
|
require.Empty(t, claims.Issuer)
|
||||||
require.Empty(t, claims.Audience)
|
require.Empty(t, claims.Audience)
|
||||||
@ -1630,11 +1639,11 @@ func requireValidStoredRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assert that the session headers are what we think they should be.
|
// Assert that the session headers are what we think they should be.
|
||||||
headers := session.Headers
|
headers := session.Fosite.Headers
|
||||||
require.Empty(t, headers)
|
require.Empty(t, headers)
|
||||||
|
|
||||||
// Assert that the token expirations are what we think they should be.
|
// Assert that the token expirations are what we think they should be.
|
||||||
authCodeExpiresAt, ok := session.ExpiresAt[fosite.AuthorizeCode]
|
authCodeExpiresAt, ok := session.Fosite.ExpiresAt[fosite.AuthorizeCode]
|
||||||
require.True(t, ok, "expected session to hold expiration time for auth code")
|
require.True(t, ok, "expected session to hold expiration time for auth code")
|
||||||
testutil.RequireTimeInDelta(
|
testutil.RequireTimeInDelta(
|
||||||
t,
|
t,
|
||||||
@ -1644,7 +1653,7 @@ func requireValidStoredRequest(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// OpenID Connect sessions do not store access token expiration information.
|
// OpenID Connect sessions do not store access token expiration information.
|
||||||
accessTokenExpiresAt, ok := session.ExpiresAt[fosite.AccessToken]
|
accessTokenExpiresAt, ok := session.Fosite.ExpiresAt[fosite.AccessToken]
|
||||||
if wantAccessTokenExpiresAt {
|
if wantAccessTokenExpiresAt {
|
||||||
require.True(t, ok, "expected session to hold expiration time for access token")
|
require.True(t, ok, "expected session to hold expiration time for access token")
|
||||||
testutil.RequireTimeInDelta(
|
testutil.RequireTimeInDelta(
|
||||||
@ -1658,8 +1667,8 @@ func requireValidStoredRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We don't use these, so they should be empty.
|
// We don't use these, so they should be empty.
|
||||||
require.Empty(t, session.Username)
|
require.Empty(t, session.Fosite.Username)
|
||||||
require.Empty(t, session.Subject)
|
require.Empty(t, session.Fosite.Subject)
|
||||||
}
|
}
|
||||||
|
|
||||||
func requireGarbageCollectTimeInDelta(t *testing.T, tokenString string, typeLabel string, secrets v1.SecretInterface, wantExpirationTime time.Time, deltaTime time.Duration) {
|
func requireGarbageCollectTimeInDelta(t *testing.T, tokenString string, typeLabel string, secrets v1.SecretInterface, wantExpirationTime time.Time, deltaTime time.Duration) {
|
||||||
@ -1709,7 +1718,7 @@ func requireValidIDToken(
|
|||||||
IssuedAt int64 `json:"iat"`
|
IssuedAt int64 `json:"iat"`
|
||||||
RequestedAt int64 `json:"rat"`
|
RequestedAt int64 `json:"rat"`
|
||||||
AuthTime int64 `json:"auth_time"`
|
AuthTime int64 `json:"auth_time"`
|
||||||
Groups string `json:"groups"`
|
Groups []string `json:"groups"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
99
internal/psession/pinniped_session.go
Normal file
99
internal/psession/pinniped_session.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package psession
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/mohae/deepcopy"
|
||||||
|
"github.com/ory/fosite"
|
||||||
|
"github.com/ory/fosite/handler/openid"
|
||||||
|
"github.com/ory/fosite/token/jwt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PinnipedSession is a session container which includes the fosite standard stuff plus custom Pinniped stuff.
|
||||||
|
type PinnipedSession struct {
|
||||||
|
// Delegate most things to the standard fosite OpenID JWT session.
|
||||||
|
Fosite *openid.DefaultSession `json:"fosite,omitempty"`
|
||||||
|
|
||||||
|
// Custom Pinniped extensions to the session data.
|
||||||
|
Custom *PinnipedSessionData `json:"custom,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ openid.Session = &PinnipedSession{}
|
||||||
|
|
||||||
|
// PinnipedSessionData is the custom session data needed by Pinniped. It should be treated as a union type,
|
||||||
|
// where the value of ProviderType decides which other fields to use.
|
||||||
|
type PinnipedSessionData struct {
|
||||||
|
// The Kubernetes resource UID of the identity provider CRD for the upstream IDP used to start this session.
|
||||||
|
// This should be validated again upon downstream refresh to make sure that we are not refreshing against
|
||||||
|
// a different identity provider CRD which just happens to have the same name.
|
||||||
|
// This implies that when a user deletes an identity provider CRD, then the sessions that were started
|
||||||
|
// using that identity provider will not be able to perform any more downstream refreshes.
|
||||||
|
ProviderUID string `json:"providerUID"`
|
||||||
|
|
||||||
|
// The Kubernetes resource name of the identity provider CRD for the upstream IDP used to start this session.
|
||||||
|
// Used during a downstream refresh to decide which upstream to refresh.
|
||||||
|
// Also used to decide which of the pointer types below should be used.
|
||||||
|
ProviderName string `json:"providerName"`
|
||||||
|
|
||||||
|
// The type of the identity provider for the upstream IDP used to start this session.
|
||||||
|
// Used during a downstream refresh to decide which upstream to refresh.
|
||||||
|
ProviderType string `json:"providerType"`
|
||||||
|
|
||||||
|
// Only used when ProviderType == "oidc".
|
||||||
|
OIDC *OIDCSessionData `json:"oidc,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// OIDCSessionData is the additional data needed by Pinniped when the upstream IDP is an OIDC provider.
|
||||||
|
type OIDCSessionData struct {
|
||||||
|
UpstreamRefreshToken string `json:"upstreamRefreshToken"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPinnipedSession returns a new empty session.
|
||||||
|
func NewPinnipedSession() *PinnipedSession {
|
||||||
|
return &PinnipedSession{
|
||||||
|
Fosite: &openid.DefaultSession{
|
||||||
|
Claims: &jwt.IDTokenClaims{},
|
||||||
|
Headers: &jwt.Headers{},
|
||||||
|
},
|
||||||
|
Custom: &PinnipedSessionData{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PinnipedSession) Clone() fosite.Session {
|
||||||
|
// Implementation copied from openid.DefaultSession's clone method.
|
||||||
|
if s == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return deepcopy.Copy(s).(fosite.Session)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PinnipedSession) SetExpiresAt(key fosite.TokenType, exp time.Time) {
|
||||||
|
s.Fosite.SetExpiresAt(key, exp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PinnipedSession) GetExpiresAt(key fosite.TokenType) time.Time {
|
||||||
|
return s.Fosite.GetExpiresAt(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PinnipedSession) GetUsername() string {
|
||||||
|
return s.Fosite.GetUsername()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PinnipedSession) SetSubject(subject string) {
|
||||||
|
s.Fosite.SetSubject(subject)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PinnipedSession) GetSubject() string {
|
||||||
|
return s.Fosite.GetSubject()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PinnipedSession) IDTokenHeaders() *jwt.Headers {
|
||||||
|
return s.Fosite.IDTokenHeaders()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PinnipedSession) IDTokenClaims() *jwt.IDTokenClaims {
|
||||||
|
return s.Fosite.IDTokenClaims()
|
||||||
|
}
|
@ -16,7 +16,6 @@ import (
|
|||||||
|
|
||||||
coreosoidc "github.com/coreos/go-oidc/v3/oidc"
|
coreosoidc "github.com/coreos/go-oidc/v3/oidc"
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/openid"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"gopkg.in/square/go-jose.v2"
|
"gopkg.in/square/go-jose.v2"
|
||||||
@ -31,6 +30,7 @@ import (
|
|||||||
pkce2 "go.pinniped.dev/internal/fositestorage/pkce"
|
pkce2 "go.pinniped.dev/internal/fositestorage/pkce"
|
||||||
"go.pinniped.dev/internal/fositestoragei"
|
"go.pinniped.dev/internal/fositestoragei"
|
||||||
"go.pinniped.dev/internal/oidc/provider"
|
"go.pinniped.dev/internal/oidc/provider"
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
"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/oidctypes"
|
||||||
@ -563,7 +563,7 @@ func validateAuthcodeStorage(
|
|||||||
wantDownstreamRequestedScopes []string,
|
wantDownstreamRequestedScopes []string,
|
||||||
wantDownstreamClientID string,
|
wantDownstreamClientID string,
|
||||||
wantDownstreamRedirectURI string,
|
wantDownstreamRedirectURI string,
|
||||||
) (*fosite.Request, *openid.DefaultSession) {
|
) (*fosite.Request, *psession.PinnipedSession) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -591,16 +591,16 @@ func validateAuthcodeStorage(
|
|||||||
testutil.RequireTimeInDelta(t, time.Now(), storedRequestFromAuthcode.RequestedAt, timeComparisonFudgeFactor)
|
testutil.RequireTimeInDelta(t, time.Now(), storedRequestFromAuthcode.RequestedAt, timeComparisonFudgeFactor)
|
||||||
|
|
||||||
// We're not using these fields yet, so confirm that we did not set them (for now).
|
// We're not using these fields yet, so confirm that we did not set them (for now).
|
||||||
require.Empty(t, storedSessionFromAuthcode.Subject)
|
require.Empty(t, storedSessionFromAuthcode.Fosite.Subject)
|
||||||
require.Empty(t, storedSessionFromAuthcode.Username)
|
require.Empty(t, storedSessionFromAuthcode.Fosite.Username)
|
||||||
require.Empty(t, storedSessionFromAuthcode.Headers)
|
require.Empty(t, storedSessionFromAuthcode.Fosite.Headers)
|
||||||
|
|
||||||
// The authcode that we are issuing should be good for the length of time that we declare in the fosite config.
|
// The authcode that we are issuing should be good for the length of time that we declare in the fosite config.
|
||||||
testutil.RequireTimeInDelta(t, time.Now().Add(authCodeExpirationSeconds*time.Second), storedSessionFromAuthcode.ExpiresAt[fosite.AuthorizeCode], timeComparisonFudgeFactor)
|
testutil.RequireTimeInDelta(t, time.Now().Add(authCodeExpirationSeconds*time.Second), storedSessionFromAuthcode.Fosite.ExpiresAt[fosite.AuthorizeCode], timeComparisonFudgeFactor)
|
||||||
require.Len(t, storedSessionFromAuthcode.ExpiresAt, 1)
|
require.Len(t, storedSessionFromAuthcode.Fosite.ExpiresAt, 1)
|
||||||
|
|
||||||
// Now confirm the ID token claims.
|
// Now confirm the ID token claims.
|
||||||
actualClaims := storedSessionFromAuthcode.Claims
|
actualClaims := storedSessionFromAuthcode.Fosite.Claims
|
||||||
|
|
||||||
// Check the user's identity, which are put into the downstream ID token's subject, username and groups claims.
|
// Check the user's identity, which are put into the downstream ID token's subject, username and groups claims.
|
||||||
require.Equal(t, wantDownstreamIDTokenSubject, actualClaims.Subject)
|
require.Equal(t, wantDownstreamIDTokenSubject, actualClaims.Subject)
|
||||||
@ -642,7 +642,7 @@ func validatePKCEStorage(
|
|||||||
oauthStore fositestoragei.AllFositeStorage,
|
oauthStore fositestoragei.AllFositeStorage,
|
||||||
storeKey string,
|
storeKey string,
|
||||||
storedRequestFromAuthcode *fosite.Request,
|
storedRequestFromAuthcode *fosite.Request,
|
||||||
storedSessionFromAuthcode *openid.DefaultSession,
|
storedSessionFromAuthcode *psession.PinnipedSession,
|
||||||
wantDownstreamPKCEChallenge, wantDownstreamPKCEChallengeMethod string,
|
wantDownstreamPKCEChallenge, wantDownstreamPKCEChallengeMethod string,
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
@ -667,7 +667,7 @@ func validateIDSessionStorage(
|
|||||||
oauthStore fositestoragei.AllFositeStorage,
|
oauthStore fositestoragei.AllFositeStorage,
|
||||||
storeKey string,
|
storeKey string,
|
||||||
storedRequestFromAuthcode *fosite.Request,
|
storedRequestFromAuthcode *fosite.Request,
|
||||||
storedSessionFromAuthcode *openid.DefaultSession,
|
storedSessionFromAuthcode *psession.PinnipedSession,
|
||||||
wantDownstreamNonce string,
|
wantDownstreamNonce string,
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
@ -686,13 +686,13 @@ func validateIDSessionStorage(
|
|||||||
require.Equal(t, wantDownstreamNonce, storedRequestFromIDSession.Form.Get("nonce"))
|
require.Equal(t, wantDownstreamNonce, storedRequestFromIDSession.Form.Get("nonce"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func castStoredAuthorizeRequest(t *testing.T, storedAuthorizeRequest fosite.Requester) (*fosite.Request, *openid.DefaultSession) {
|
func castStoredAuthorizeRequest(t *testing.T, storedAuthorizeRequest fosite.Requester) (*fosite.Request, *psession.PinnipedSession) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
storedRequest, ok := storedAuthorizeRequest.(*fosite.Request)
|
storedRequest, ok := storedAuthorizeRequest.(*fosite.Request)
|
||||||
require.Truef(t, ok, "could not cast %T to %T", storedAuthorizeRequest, &fosite.Request{})
|
require.Truef(t, ok, "could not cast %T to %T", storedAuthorizeRequest, &fosite.Request{})
|
||||||
storedSession, ok := storedAuthorizeRequest.GetSession().(*openid.DefaultSession)
|
storedSession, ok := storedAuthorizeRequest.GetSession().(*psession.PinnipedSession)
|
||||||
require.Truef(t, ok, "could not cast %T to %T", storedAuthorizeRequest.GetSession(), &openid.DefaultSession{})
|
require.Truef(t, ok, "could not cast %T to %T", storedAuthorizeRequest.GetSession(), &psession.PinnipedSession{})
|
||||||
|
|
||||||
return storedRequest, storedSession
|
return storedRequest, storedSession
|
||||||
}
|
}
|
||||||
|
43
internal/testutil/psession.go
Normal file
43
internal/testutil/psession.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ory/fosite/handler/openid"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
testing2 "k8s.io/client-go/testing"
|
||||||
|
|
||||||
|
"go.pinniped.dev/internal/psession"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewFakePinnipedSession() *psession.PinnipedSession {
|
||||||
|
return &psession.PinnipedSession{
|
||||||
|
Fosite: &openid.DefaultSession{
|
||||||
|
Claims: nil,
|
||||||
|
Headers: nil,
|
||||||
|
ExpiresAt: nil,
|
||||||
|
Username: "snorlax",
|
||||||
|
Subject: "panda",
|
||||||
|
},
|
||||||
|
Custom: &psession.PinnipedSessionData{
|
||||||
|
ProviderUID: "fake-provider-uid",
|
||||||
|
ProviderType: "fake-provider-type",
|
||||||
|
ProviderName: "fake-provider-name",
|
||||||
|
OIDC: &psession.OIDCSessionData{
|
||||||
|
UpstreamRefreshToken: "fake-upstream-refresh-token",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogActualJSONFromCreateAction(t *testing.T, client *fake.Clientset, actionIndex int) {
|
||||||
|
t.Log("actual value of CreateAction secret data", string(client.Actions()[actionIndex].(testing2.CreateActionImpl).Object.(*v1.Secret).Data["pinniped-storage-data"]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogActualJSONFromUpdateAction(t *testing.T, client *fake.Clientset, actionIndex int) {
|
||||||
|
t.Log("actual value of UpdateAction secret data", string(client.Actions()[actionIndex].(testing2.UpdateActionImpl).Object.(*v1.Secret).Data["pinniped-storage-data"]))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user