From 5dbf05c31d5d344f7d4c8b665bdae6038a5a41e5 Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Wed, 17 Apr 2024 09:42:15 -0700 Subject: [PATCH] Update the session storage versions due to new ID token lifetime field --- .../garbage_collector_test.go | 33 ++++++------- .../fositestorage/accesstoken/accesstoken.go | 3 +- .../accesstoken/accesstoken_test.go | 43 +++++++++-------- .../authorizationcode/authorizationcode.go | 5 +- .../authorizationcode_test.go | 47 ++++++++++++------- .../openidconnect/openidconnect.go | 3 +- .../openidconnect/openidconnect_test.go | 21 +++++---- internal/fositestorage/pkce/pkce.go | 3 +- internal/fositestorage/pkce/pkce_test.go | 21 +++++---- .../refreshtoken/refreshtoken.go | 3 +- .../refreshtoken/refreshtoken_test.go | 46 ++++++++++-------- test/integration/supervisor_storage_test.go | 2 +- 12 files changed, 134 insertions(+), 96 deletions(-) diff --git a/internal/controller/supervisorstorage/garbage_collector_test.go b/internal/controller/supervisorstorage/garbage_collector_test.go index a52312567..c020ba92e 100644 --- a/internal/controller/supervisorstorage/garbage_collector_test.go +++ b/internal/controller/supervisorstorage/garbage_collector_test.go @@ -121,7 +121,8 @@ func TestGarbageCollectorControllerSync(t *testing.T) { spec.Run(t, "Sync", func(t *testing.T, when spec.G, it spec.S) { const ( - installedInNamespace = "some-namespace" + installedInNamespace = "some-namespace" + currentSessionStorageVersion = "7" // update this when you update the storage version in the production code ) var ( @@ -265,7 +266,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there are valid, expired authcode secrets which contain upstream refresh tokens", func() { it.Before(func() { activeOIDCAuthcodeSession := &authorizationcode.Session{ - Version: "6", + Version: currentSessionStorageVersion, Active: true, Request: &fosite.Request{ ID: "request-id-1", @@ -310,7 +311,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { r.NoError(kubeClient.Tracker().Add(activeOIDCAuthcodeSessionSecret)) inactiveOIDCAuthcodeSession := &authorizationcode.Session{ - Version: "6", + Version: currentSessionStorageVersion, Active: false, Request: &fosite.Request{ ID: "request-id-2", @@ -389,7 +390,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there are valid, expired authcode secrets which contain upstream access tokens", func() { it.Before(func() { activeOIDCAuthcodeSession := &authorizationcode.Session{ - Version: "6", + Version: currentSessionStorageVersion, Active: true, Request: &fosite.Request{ ID: "request-id-1", @@ -434,7 +435,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { r.NoError(kubeClient.Tracker().Add(activeOIDCAuthcodeSessionSecret)) inactiveOIDCAuthcodeSession := &authorizationcode.Session{ - Version: "6", + Version: currentSessionStorageVersion, Active: false, Request: &fosite.Request{ ID: "request-id-2", @@ -513,7 +514,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there is an invalid, expired authcode secret", func() { it.Before(func() { invalidOIDCAuthcodeSession := &authorizationcode.Session{ - Version: "6", + Version: currentSessionStorageVersion, Active: true, Request: &fosite.Request{ ID: "", // it is invalid for there to be a missing request ID @@ -582,7 +583,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there is a valid, expired authcode secret but its upstream name does not match any existing upstream", func() { it.Before(func() { wrongProviderNameOIDCAuthcodeSession := &authorizationcode.Session{ - Version: "6", + Version: currentSessionStorageVersion, Active: true, Request: &fosite.Request{ ID: "request-id-1", @@ -653,7 +654,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there is a valid, expired authcode secret but its upstream UID does not match any existing upstream", func() { it.Before(func() { wrongProviderNameOIDCAuthcodeSession := &authorizationcode.Session{ - Version: "6", + Version: currentSessionStorageVersion, Active: true, Request: &fosite.Request{ ID: "request-id-1", @@ -724,7 +725,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there is a valid, recently expired authcode secret but the upstream revocation fails", func() { it.Before(func() { activeOIDCAuthcodeSession := &authorizationcode.Session{ - Version: "6", + Version: currentSessionStorageVersion, Active: true, Request: &fosite.Request{ ID: "request-id-1", @@ -829,7 +830,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there is a valid, long-since expired authcode secret but the upstream revocation fails", func() { it.Before(func() { activeOIDCAuthcodeSession := &authorizationcode.Session{ - Version: "6", + Version: currentSessionStorageVersion, Active: true, Request: &fosite.Request{ ID: "request-id-1", @@ -908,7 +909,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there are valid, expired access token secrets which contain upstream refresh tokens", func() { it.Before(func() { offlineAccessGrantedOIDCAccessTokenSession := &accesstoken.Session{ - Version: "6", + Version: currentSessionStorageVersion, Request: &fosite.Request{ GrantedScope: fosite.Arguments{"scope1", "scope2", "offline_access"}, ID: "request-id-1", @@ -953,7 +954,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { r.NoError(kubeClient.Tracker().Add(offlineAccessGrantedOIDCAccessTokenSessionSecret)) offlineAccessNotGrantedOIDCAccessTokenSession := &accesstoken.Session{ - Version: "6", + Version: currentSessionStorageVersion, Request: &fosite.Request{ GrantedScope: fosite.Arguments{"scope1", "scope2"}, ID: "request-id-2", @@ -1032,7 +1033,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there are valid, expired access token secrets which contain upstream access tokens", func() { it.Before(func() { offlineAccessGrantedOIDCAccessTokenSession := &accesstoken.Session{ - Version: "6", + Version: currentSessionStorageVersion, Request: &fosite.Request{ GrantedScope: fosite.Arguments{"scope1", "scope2", "offline_access"}, ID: "request-id-1", @@ -1077,7 +1078,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { r.NoError(kubeClient.Tracker().Add(offlineAccessGrantedOIDCAccessTokenSessionSecret)) offlineAccessNotGrantedOIDCAccessTokenSession := &accesstoken.Session{ - Version: "6", + Version: currentSessionStorageVersion, Request: &fosite.Request{ GrantedScope: fosite.Arguments{"scope1", "scope2"}, ID: "request-id-2", @@ -1156,7 +1157,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there are valid, expired refresh secrets which contain upstream refresh tokens", func() { it.Before(func() { oidcRefreshSession := &refreshtoken.Session{ - Version: "6", + Version: currentSessionStorageVersion, Request: &fosite.Request{ ID: "request-id-1", Client: &clientregistry.Client{}, @@ -1233,7 +1234,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { when("there are valid, expired refresh secrets which contain upstream access tokens", func() { it.Before(func() { oidcRefreshSession := &refreshtoken.Session{ - Version: "6", + Version: currentSessionStorageVersion, Request: &fosite.Request{ ID: "request-id-1", Client: &clientregistry.Client{}, diff --git a/internal/fositestorage/accesstoken/accesstoken.go b/internal/fositestorage/accesstoken/accesstoken.go index 247273c42..c67b9cab7 100644 --- a/internal/fositestorage/accesstoken/accesstoken.go +++ b/internal/fositestorage/accesstoken/accesstoken.go @@ -34,7 +34,8 @@ const ( // Version 4 is when fosite added json tags to their openid.DefaultSession struct. // Version 5 is when we added the UpstreamUsername and UpstreamGroups fields to psession.CustomSessionData. // Version 6 is when we upgraded fosite in Dec 2023. - accessTokenStorageVersion = "6" + // Version 7 is when OIDCClients were given configurable ID token lifetimes. + accessTokenStorageVersion = "7" ) type RevocationStorage interface { diff --git a/internal/fositestorage/accesstoken/accesstoken_test.go b/internal/fositestorage/accesstoken/accesstoken_test.go index a36e09f80..522c24c90 100644 --- a/internal/fositestorage/accesstoken/accesstoken_test.go +++ b/internal/fositestorage/accesstoken/accesstoken_test.go @@ -28,18 +28,23 @@ import ( "go.pinniped.dev/internal/testutil" ) -const namespace = "test-ns" +const ( + namespace = "test-ns" + expectedVersion = "7" // update this when you update the storage version in the production code +) -var fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) -var lifetime = time.Minute * 10 -var fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) -var lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } +var ( + fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) + lifetime = time.Minute * 10 + fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) + lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } -var secretsGVR = schema.GroupVersionResource{ - Group: "", - Version: "v1", - Resource: "secrets", -} + secretsGVR = schema.GroupVersionResource{ + Group: "", + Version: "v1", + Resource: "secrets", + } +) func TestAccessTokenStorage(t *testing.T) { wantActions := []coretesting.Action{ @@ -56,7 +61,7 @@ func TestAccessTokenStorage(t *testing.T) { }, }, 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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"6"}`), + "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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/access-token", @@ -137,7 +142,7 @@ func TestAccessTokenStorageRevocation(t *testing.T) { }, }, 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":"","IDTokenLifetimeConfiguration":0},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"6"}`), + "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":"","IDTokenLifetimeConfiguration":0},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/access-token", @@ -210,7 +215,7 @@ func TestWrongVersion(t *testing.T) { _, 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 6") + 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 "+expectedVersion) } func TestNilSessionRequest(t *testing.T) { @@ -228,7 +233,7 @@ func TestNilSessionRequest(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"6"}`), + "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/access-token", @@ -315,13 +320,13 @@ func TestReadFromSecret(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"id_token_claims":{"jti": "xyz"},"headers":{"extra":{"myheader": "foo"}},"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"6","active": true}`), + "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"id_token_claims":{"jti": "xyz"},"headers":{"extra":{"myheader": "foo"}},"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"` + expectedVersion + `","active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/access-token", }, wantSession: &Session{ - Version: "6", + Version: expectedVersion, Request: &fosite.Request{ ID: "abcd-1", Client: &clientregistry.Client{}, @@ -358,7 +363,7 @@ func TestReadFromSecret(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"6","active": true}`), + "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"` + expectedVersion + `","active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/not-access-token", @@ -381,7 +386,7 @@ func TestReadFromSecret(t *testing.T) { }, Type: "storage.pinniped.dev/access-token", }, - wantErr: "access token request data has wrong version: access token session has version wrong-version-here instead of 6", + wantErr: "access token request data has wrong version: access token session has version wrong-version-here instead of " + expectedVersion, }, { name: "missing request", @@ -394,7 +399,7 @@ func TestReadFromSecret(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"version":"6","active": true}`), + "pinniped-storage-data": []byte(`{"version":"` + expectedVersion + `","active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/access-token", diff --git a/internal/fositestorage/authorizationcode/authorizationcode.go b/internal/fositestorage/authorizationcode/authorizationcode.go index 11ad6d999..f1187ec83 100644 --- a/internal/fositestorage/authorizationcode/authorizationcode.go +++ b/internal/fositestorage/authorizationcode/authorizationcode.go @@ -35,7 +35,8 @@ const ( // Version 4 is when fosite added json tags to their openid.DefaultSession struct. // Version 5 is when we added the UpstreamUsername and UpstreamGroups fields to psession.CustomSessionData. // Version 6 is when we upgraded fosite in Dec 2023. - authorizeCodeStorageVersion = "6" + // Version 7 is when OIDCClients were given configurable ID token lifetimes. + authorizeCodeStorageVersion = "7" ) var _ oauth2.AuthorizeCodeStorage = &authorizeCodeStorage{} @@ -393,5 +394,5 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{ "筫MN\u0026錝D肁Ŷɽ蔒PR}Ųʓl{" ] }, - "version": "6" + "version": "7" }` diff --git a/internal/fositestorage/authorizationcode/authorizationcode_test.go b/internal/fositestorage/authorizationcode/authorizationcode_test.go index a057062f2..568393f32 100644 --- a/internal/fositestorage/authorizationcode/authorizationcode_test.go +++ b/internal/fositestorage/authorizationcode/authorizationcode_test.go @@ -41,12 +41,17 @@ import ( "go.pinniped.dev/internal/testutil" ) -const namespace = "test-ns" +const ( + namespace = "test-ns" + expectedVersion = "7" // update this when you update the storage version in the production code +) -var fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) -var lifetime = time.Minute * 10 -var fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) -var lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } +var ( + fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) + lifetime = time.Minute * 10 + fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) + lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } +) func TestAuthorizationCodeStorage(t *testing.T) { secretsGVR := schema.GroupVersionResource{ @@ -68,7 +73,7 @@ func TestAuthorizationCodeStorage(t *testing.T) { }, }, 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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"6"}`), + "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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/authcode", @@ -88,7 +93,7 @@ func TestAuthorizationCodeStorage(t *testing.T) { }, }, 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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"6"}`), + "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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/authcode", @@ -218,7 +223,7 @@ func TestWrongVersion(t *testing.T) { _, 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 6") + require.EqualError(t, err, "authorization request data has wrong version: authorization code session for fancy-signature has version not-the-right-version instead of "+expectedVersion) } func TestNilSessionRequest(t *testing.T) { @@ -233,7 +238,7 @@ func TestNilSessionRequest(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value", "version":"6", "active": true}`), + "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value", "version":"` + expectedVersion + `", "active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/authcode", @@ -403,7 +408,7 @@ func TestFuzzAndJSONNewValidEmptyAuthorizeCodeSession(t *testing.T) { // set these to match CreateAuthorizeCodeSession so that .JSONEq works validSession.Active = true - validSession.Version = "6" // update this when you update the storage version in the production code + validSession.Version = expectedVersion validSessionJSONBytes, err := json.MarshalIndent(validSession, "", "\t") require.NoError(t, err) @@ -414,9 +419,15 @@ func TestFuzzAndJSONNewValidEmptyAuthorizeCodeSession(t *testing.T) { t.Log("actual value from fuzzing", authorizeCodeSessionJSONFromFuzzing) // can be useful when updating expected value - // while the fuzzer will panic if AuthorizeRequest changes in a way that cannot be fuzzed, - // if it adds a new field that can be fuzzed, this check will fail - // thus if AuthorizeRequest changes, we will detect it here (though we could possibly miss an omitempty field) + // While the fuzzer will panic if AuthorizeRequest changes in a way that cannot be fuzzed, + // if it adds a new field that can be fuzzed, this check will fail. + // Thus, when AuthorizeRequest changes, we will detect it here (though we could possibly miss an omitempty field). + // Whenever this changes, consider increasing the session storage versions. Consider what would happen if an old + // version of a session Secret is read by new code after a Pinniped upgrade? For example, would there be new unset + // fields in the deserialized session data structs? If so, you probably want to increase the storage versions to + // cause those old session Secrets to be discarded upon read after an upgrade. + // Note that when you change the storage version, you will also need to change it in the JSON content of the + // expected value for this assertion. require.JSONEq(t, ExpectedAuthorizeCodeSessionJSONFromFuzzing, authorizeCodeSessionJSONFromFuzzing, "actual:\n%s", authorizeCodeSessionJSONFromFuzzing) } @@ -438,13 +449,13 @@ func TestReadFromSecret(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"id_token_claims":{"jti": "xyz"},"headers":{"extra":{"myheader": "foo"}},"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"6","active": true}`), + "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"id_token_claims":{"jti": "xyz"},"headers":{"extra":{"myheader": "foo"}},"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"` + expectedVersion + `","active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/authcode", }, wantSession: &Session{ - Version: "6", + Version: expectedVersion, Active: true, Request: &fosite.Request{ ID: "abcd-1", @@ -482,7 +493,7 @@ func TestReadFromSecret(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"6","active": true}`), + "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"` + expectedVersion + `","active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/not-authcode", @@ -505,7 +516,7 @@ func TestReadFromSecret(t *testing.T) { }, Type: "storage.pinniped.dev/authcode", }, - wantErr: "authorization request data has wrong version: authorization code session has version wrong-version-here instead of 6", + wantErr: "authorization request data has wrong version: authorization code session has version wrong-version-here instead of " + expectedVersion, }, { name: "missing request", @@ -518,7 +529,7 @@ func TestReadFromSecret(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"version":"6","active": true}`), + "pinniped-storage-data": []byte(`{"version":"` + expectedVersion + `","active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/authcode", diff --git a/internal/fositestorage/openidconnect/openidconnect.go b/internal/fositestorage/openidconnect/openidconnect.go index 58e560a10..a04bea4c3 100644 --- a/internal/fositestorage/openidconnect/openidconnect.go +++ b/internal/fositestorage/openidconnect/openidconnect.go @@ -35,7 +35,8 @@ const ( // Version 4 is when fosite added json tags to their openid.DefaultSession struct. // Version 5 is when we added the UpstreamUsername and UpstreamGroups fields to psession.CustomSessionData. // Version 6 is when we upgraded fosite in Dec 2023. - oidcStorageVersion = "6" + // Version 7 is when OIDCClients were given configurable ID token lifetimes. + oidcStorageVersion = "7" ) var _ openid.OpenIDConnectRequestStorage = &openIDConnectRequestStorage{} diff --git a/internal/fositestorage/openidconnect/openidconnect_test.go b/internal/fositestorage/openidconnect/openidconnect_test.go index 781973d36..8f64299ed 100644 --- a/internal/fositestorage/openidconnect/openidconnect_test.go +++ b/internal/fositestorage/openidconnect/openidconnect_test.go @@ -27,12 +27,17 @@ import ( "go.pinniped.dev/internal/testutil" ) -const namespace = "test-ns" +const ( + namespace = "test-ns" + expectedVersion = "7" // update this when you update the storage version in the production code +) -var fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) -var lifetime = time.Minute * 10 -var fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) -var lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } +var ( + fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) + lifetime = time.Minute * 10 + fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) + lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } +) func TestOpenIdConnectStorage(t *testing.T) { secretsGVR := schema.GroupVersionResource{ @@ -54,7 +59,7 @@ func TestOpenIdConnectStorage(t *testing.T) { }, }, 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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"6"}`), + "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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/oidc", @@ -151,7 +156,7 @@ func TestWrongVersion(t *testing.T) { _, 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 6") + require.EqualError(t, err, "oidc request data has wrong version: oidc session for fancy-signature has version not-the-right-version instead of "+expectedVersion) } func TestNilSessionRequest(t *testing.T) { @@ -166,7 +171,7 @@ func TestNilSessionRequest(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"6"}`), + "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/oidc", diff --git a/internal/fositestorage/pkce/pkce.go b/internal/fositestorage/pkce/pkce.go index 9b6a14d4c..b0d371b6a 100644 --- a/internal/fositestorage/pkce/pkce.go +++ b/internal/fositestorage/pkce/pkce.go @@ -33,7 +33,8 @@ const ( // Version 4 is when fosite added json tags to their openid.DefaultSession struct. // Version 5 is when we added the UpstreamUsername and UpstreamGroups fields to psession.CustomSessionData. // Version 6 is when we upgraded fosite in Dec 2023. - pkceStorageVersion = "6" + // Version 7 is when OIDCClients were given configurable ID token lifetimes. + pkceStorageVersion = "7" ) var _ pkce.PKCERequestStorage = &pkceStorage{} diff --git a/internal/fositestorage/pkce/pkce_test.go b/internal/fositestorage/pkce/pkce_test.go index 100cbd211..ed38d51f6 100644 --- a/internal/fositestorage/pkce/pkce_test.go +++ b/internal/fositestorage/pkce/pkce_test.go @@ -27,12 +27,17 @@ import ( "go.pinniped.dev/internal/testutil" ) -const namespace = "test-ns" +const ( + namespace = "test-ns" + expectedVersion = "7" // update this when you update the storage version in the production code +) -var fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) -var lifetime = time.Minute * 10 -var fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) -var lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } +var ( + fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) + lifetime = time.Minute * 10 + fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) + lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } +) func TestPKCEStorage(t *testing.T) { secretsGVR := schema.GroupVersionResource{ @@ -54,7 +59,7 @@ func TestPKCEStorage(t *testing.T) { }, }, 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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"6"}`), + "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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/pkce", @@ -153,7 +158,7 @@ func TestWrongVersion(t *testing.T) { _, 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 6") + require.EqualError(t, err, "pkce request data has wrong version: pkce session for fancy-signature has version not-the-right-version instead of "+expectedVersion) } func TestNilSessionRequest(t *testing.T) { @@ -171,7 +176,7 @@ func TestNilSessionRequest(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"6"}`), + "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/pkce", diff --git a/internal/fositestorage/refreshtoken/refreshtoken.go b/internal/fositestorage/refreshtoken/refreshtoken.go index d87c6bb9b..efc96071b 100644 --- a/internal/fositestorage/refreshtoken/refreshtoken.go +++ b/internal/fositestorage/refreshtoken/refreshtoken.go @@ -34,7 +34,8 @@ const ( // Version 4 is when fosite added json tags to their openid.DefaultSession struct. // Version 5 is when we added the UpstreamUsername and UpstreamGroups fields to psession.CustomSessionData. // Version 6 is when we upgraded fosite in Dec 2023. - refreshTokenStorageVersion = "6" + // Version 7 is when OIDCClients were given configurable ID token lifetimes. + refreshTokenStorageVersion = "7" ) type RevocationStorage interface { diff --git a/internal/fositestorage/refreshtoken/refreshtoken_test.go b/internal/fositestorage/refreshtoken/refreshtoken_test.go index d6d987c38..6075d0723 100644 --- a/internal/fositestorage/refreshtoken/refreshtoken_test.go +++ b/internal/fositestorage/refreshtoken/refreshtoken_test.go @@ -28,17 +28,23 @@ import ( "go.pinniped.dev/internal/testutil" ) -const namespace = "test-ns" +const ( + namespace = "test-ns" + expectedVersion = "7" // update this when you update the storage version in the production code +) -var secretsGVR = schema.GroupVersionResource{ - Group: "", - Version: "v1", - Resource: "secrets", -} -var fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) -var lifetime = time.Minute * 10 -var fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) -var lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } +var ( + fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC) + lifetime = time.Minute * 10 + fakeNowPlusLifetimeAsString = metav1.Time{Time: fakeNow.Add(lifetime)}.Format(time.RFC3339) + lifetimeFunc = func(requester fosite.Requester) time.Duration { return lifetime } + + secretsGVR = schema.GroupVersionResource{ + Group: "", + Version: "v1", + Resource: "secrets", + } +) func TestRefreshTokenStorage(t *testing.T) { wantActions := []coretesting.Action{ @@ -55,7 +61,7 @@ func TestRefreshTokenStorage(t *testing.T) { }, }, 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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"6"}`), + "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":"","IDTokenLifetimeConfiguration":42000000000},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/refresh-token", @@ -137,7 +143,7 @@ func TestRefreshTokenStorageRevocation(t *testing.T) { }, }, 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":"","IDTokenLifetimeConfiguration":0},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"6"}`), + "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":"","IDTokenLifetimeConfiguration":0},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/refresh-token", @@ -192,7 +198,7 @@ func TestRefreshTokenStorageRevokeRefreshTokenMaybeGracePeriod(t *testing.T) { }, }, 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":"","IDTokenLifetimeConfiguration":0},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"6"}`), + "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":"","IDTokenLifetimeConfiguration":0},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/refresh-token", @@ -266,7 +272,7 @@ func TestWrongVersion(t *testing.T) { _, 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 6") + 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 "+expectedVersion) } func TestNilSessionRequest(t *testing.T) { @@ -284,7 +290,7 @@ func TestNilSessionRequest(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"6"}`), + "pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"` + expectedVersion + `"}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/refresh-token", @@ -371,13 +377,13 @@ func TestReadFromSecret(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"id_token_claims":{"jti": "xyz"},"headers":{"extra":{"myheader": "foo"}},"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"6","active": true}`), + "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"id_token_claims":{"jti": "xyz"},"headers":{"extra":{"myheader": "foo"}},"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","upstreamUsername":"fake-upstream-username","upstreamGroups":["fake-upstream-group1","fake-upstream-group2"],"providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"` + expectedVersion + `","active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/refresh-token", }, wantSession: &Session{ - Version: "6", + Version: expectedVersion, Request: &fosite.Request{ ID: "abcd-1", Client: &clientregistry.Client{}, @@ -414,7 +420,7 @@ func TestReadFromSecret(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"6","active": true}`), + "pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"` + expectedVersion + `","active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/not-refresh-token", @@ -437,7 +443,7 @@ func TestReadFromSecret(t *testing.T) { }, Type: "storage.pinniped.dev/refresh-token", }, - wantErr: "refresh token request data has wrong version: refresh token session has version wrong-version-here instead of 6", + wantErr: "refresh token request data has wrong version: refresh token session has version wrong-version-here instead of " + expectedVersion, }, { name: "missing request", @@ -450,7 +456,7 @@ func TestReadFromSecret(t *testing.T) { }, }, Data: map[string][]byte{ - "pinniped-storage-data": []byte(`{"version":"6","active": true}`), + "pinniped-storage-data": []byte(`{"version":"` + expectedVersion + `","active": true}`), "pinniped-storage-version": []byte("1"), }, Type: "storage.pinniped.dev/refresh-token", diff --git a/test/integration/supervisor_storage_test.go b/test/integration/supervisor_storage_test.go index b0826e035..9da514620 100644 --- a/test/integration/supervisor_storage_test.go +++ b/test/integration/supervisor_storage_test.go @@ -93,7 +93,7 @@ func TestAuthorizeCodeStorage(t *testing.T) { // Note that CreateAuthorizeCodeSession() sets Active to true and also sets the Version before storing the session, // so expect those here. session.Active = true - session.Version = "6" // this is the value of the authorizationcode.authorizeCodeStorageVersion constant + session.Version = "7" // this is the value of the authorizationcode.authorizeCodeStorageVersion constant expectedSessionStorageJSON, err := json.Marshal(session) require.NoError(t, err) require.JSONEq(t, string(expectedSessionStorageJSON), string(initialSecret.Data["pinniped-storage-data"]))