From f21381f0ea6627947d72ff8518bfffe94797a3c6 Mon Sep 17 00:00:00 2001 From: Henning Perl Date: Fri, 4 Aug 2023 14:06:28 +0200 Subject: [PATCH 1/5] feat: propagate logout to identity provider This commit improves the integration between Hydra and Kratos when logging out the user. This adds a new configuration key for configuring a Kratos admin URL. Additionally, Kratos can send a session ID when accepting a login request. If a session ID was specified and a Kratos admin URL was configured, Hydra will disable the corresponding Kratos session through the admin API if a frontchannel or backchannel logout was triggered. --- consent/manager.go | 2 +- consent/manager_test_helpers.go | 14 ++-- consent/registry.go | 2 + consent/strategy_default.go | 21 ++++-- consent/strategy_default_test.go | 3 +- consent/strategy_logout_test.go | 19 ++++- driver/config/provider.go | 7 ++ driver/registry.go | 4 ++ driver/registry_base.go | 14 ++++ flow/consent_types.go | 17 +++-- flow/flow.go | 4 ++ flow/flow_test.go | 1 + go.mod | 1 + go.sum | 2 + internal/httpclient/api/openapi.yaml | 4 ++ .../docs/AcceptOAuth2LoginRequest.md | 26 +++++++ .../model_accept_o_auth2_login_request.go | 37 ++++++++++ internal/kratos/fake_kratos.go | 35 ++++++++++ internal/kratos/kratos.go | 69 +++++++++++++++++++ .../auth_session-0001.json | 1 + .../auth_session-0002.json | 1 + .../auth_session-0003.json | 1 + .../auth_session-0004.json | 1 + .../auth_session-0005.json | 1 + .../auth_session-0006.json | 1 + .../auth_session-0007.json | 1 + .../auth_session-0008.json | 1 + .../auth_session-0009.json | 1 + .../auth_session-0010.json | 1 + .../auth_session-0011.json | 1 + .../auth_session-0012.json | 1 + .../auth_session-0013.json | 1 + .../auth_session-0014.json | 1 + .../auth_session-0015.json | 1 + .../auth_session-0016.json | 1 + .../hydra_oauth2_flow/challenge-0001.json | 1 + .../hydra_oauth2_flow/challenge-0002.json | 1 + .../hydra_oauth2_flow/challenge-0003.json | 1 + .../hydra_oauth2_flow/challenge-0004.json | 1 + .../hydra_oauth2_flow/challenge-0005.json | 1 + .../hydra_oauth2_flow/challenge-0006.json | 1 + .../hydra_oauth2_flow/challenge-0007.json | 1 + .../hydra_oauth2_flow/challenge-0008.json | 1 + .../hydra_oauth2_flow/challenge-0009.json | 1 + .../hydra_oauth2_flow/challenge-0010.json | 1 + .../hydra_oauth2_flow/challenge-0011.json | 1 + .../hydra_oauth2_flow/challenge-0012.json | 1 + .../hydra_oauth2_flow/challenge-0013.json | 1 + .../hydra_oauth2_flow/challenge-0014.json | 1 + .../hydra_oauth2_flow/challenge-0015.json | 1 + .../hydra_oauth2_flow/challenge-0016.json | 1 + ...22501000001_add_kratos_session_id.down.sql | 2 + ...9122501000001_add_kratos_session_id.up.sql | 2 + persistence/sql/persister_consent.go | 31 ++++++--- persistence/sql/persister_nid_test.go | 18 +++-- spec/api.json | 4 ++ spec/config.json | 15 ++++ spec/swagger.json | 4 ++ 58 files changed, 358 insertions(+), 32 deletions(-) create mode 100644 internal/kratos/fake_kratos.go create mode 100644 internal/kratos/kratos.go create mode 100644 persistence/sql/migrations/20230809122501000001_add_kratos_session_id.down.sql create mode 100644 persistence/sql/migrations/20230809122501000001_add_kratos_session_id.up.sql diff --git a/consent/manager.go b/consent/manager.go index 69b62ed8b9e..45cb00240b7 100644 --- a/consent/manager.go +++ b/consent/manager.go @@ -41,7 +41,7 @@ type ( // Cookie management GetRememberedLoginSession(ctx context.Context, loginSessionFromCookie *flow.LoginSession, id string) (*flow.LoginSession, error) CreateLoginSession(ctx context.Context, session *flow.LoginSession) error - DeleteLoginSession(ctx context.Context, id string) error + DeleteLoginSession(ctx context.Context, id string) (deletedSession *flow.LoginSession, err error) RevokeSubjectLoginSession(ctx context.Context, user string) error ConfirmLoginSession(ctx context.Context, session *flow.LoginSession, id string, authTime time.Time, subject string, remember bool) error diff --git a/consent/manager_test_helpers.go b/consent/manager_test_helpers.go index 2d84bf071d5..588aef92174 100644 --- a/consent/manager_test_helpers.go +++ b/consent/manager_test_helpers.go @@ -324,8 +324,12 @@ func TestHelperNID(r interface { require.NoError(t, err) require.Error(t, t2InvalidNID.ConfirmLoginSession(ctx, &testLS, testLS.ID, time.Now(), testLS.Subject, true)) require.NoError(t, t1ValidNID.ConfirmLoginSession(ctx, &testLS, testLS.ID, time.Now(), testLS.Subject, true)) - require.Error(t, t2InvalidNID.DeleteLoginSession(ctx, testLS.ID)) - require.NoError(t, t1ValidNID.DeleteLoginSession(ctx, testLS.ID)) + ls, err := t2InvalidNID.DeleteLoginSession(ctx, testLS.ID) + require.Error(t, err) + assert.Nil(t, ls) + ls, err = t1ValidNID.DeleteLoginSession(ctx, testLS.ID) + require.NoError(t, err) + assert.Equal(t, testLS.ID, ls.ID) } } @@ -429,8 +433,9 @@ func ManagerTests(deps Deps, m Manager, clientManager client.Manager, fositeMana }, } { t.Run("case=delete-get-"+tc.id, func(t *testing.T) { - err := m.DeleteLoginSession(ctx, tc.id) + ls, err := m.DeleteLoginSession(ctx, tc.id) require.NoError(t, err) + assert.EqualValues(t, tc.id, ls.ID) _, err = m.GetRememberedLoginSession(ctx, nil, tc.id) require.Error(t, err) @@ -1083,7 +1088,8 @@ func ManagerTests(deps Deps, m Manager, clientManager client.Manager, fositeMana require.NoError(t, err) assert.EqualValues(t, expected.ID, result.ID) - require.NoError(t, m.DeleteLoginSession(ctx, s.ID)) + _, err = m.DeleteLoginSession(ctx, s.ID) + require.NoError(t, err) result, err = m.GetConsentRequest(ctx, expected.ID) require.NoError(t, err) diff --git a/consent/registry.go b/consent/registry.go index 447e345ee5b..59e626efaad 100644 --- a/consent/registry.go +++ b/consent/registry.go @@ -9,6 +9,7 @@ import ( "github.com/ory/fosite/handler/openid" "github.com/ory/hydra/v2/aead" "github.com/ory/hydra/v2/client" + "github.com/ory/hydra/v2/internal/kratos" "github.com/ory/hydra/v2/x" ) @@ -17,6 +18,7 @@ type InternalRegistry interface { x.RegistryCookieStore x.RegistryLogger x.HTTPClientProvider + kratos.Provider Registry client.Registry diff --git a/consent/strategy_default.go b/consent/strategy_default.go index cc30d98cc5d..97a6efddd48 100644 --- a/consent/strategy_default.go +++ b/consent/strategy_default.go @@ -312,7 +312,9 @@ func (s *DefaultStrategy) revokeAuthenticationSession(ctx context.Context, w htt return nil } - return s.r.ConsentManager().DeleteLoginSession(r.Context(), sid) + _, err = s.r.ConsentManager().DeleteLoginSession(r.Context(), sid) + + return err } func (s *DefaultStrategy) revokeAuthenticationCookie(w http.ResponseWriter, r *http.Request, ss sessions.Store) (string, error) { @@ -457,6 +459,7 @@ func (s *DefaultStrategy) verifyAuthentication( return nil, fosite.ErrAccessDenied.WithHint("The login session cookie was not found or malformed.") } + loginSession.KratosSessionID = f.KratosSessionID if err := s.r.ConsentManager().ConfirmLoginSession(ctx, loginSession, sessionID, time.Time(session.AuthenticatedAt), session.Subject, session.Remember); err != nil { return nil, err } @@ -730,7 +733,8 @@ func (s *DefaultStrategy) generateFrontChannelLogoutURLs(ctx context.Context, su return urls, nil } -func (s *DefaultStrategy) executeBackChannelLogout(ctx context.Context, r *http.Request, subject, sid string) error { +func (s *DefaultStrategy) executeBackChannelLogout(r *http.Request, subject, sid string) error { + ctx := r.Context() clients, err := s.r.ConsentManager().ListUserAuthenticatedClientsWithBackChannelLogout(ctx, subject, sid) if err != nil { return err @@ -990,8 +994,9 @@ func (s *DefaultStrategy) issueLogoutVerifier(ctx context.Context, w http.Respon return nil, errorsx.WithStack(ErrAbortOAuth2Request) } -func (s *DefaultStrategy) performBackChannelLogoutAndDeleteSession(_ context.Context, r *http.Request, subject string, sid string) error { - if err := s.executeBackChannelLogout(r.Context(), r, subject, sid); err != nil { +func (s *DefaultStrategy) performBackChannelLogoutAndDeleteSession(r *http.Request, subject string, sid string) error { + ctx := r.Context() + if err := s.executeBackChannelLogout(r, subject, sid); err != nil { return err } @@ -1000,10 +1005,12 @@ func (s *DefaultStrategy) performBackChannelLogoutAndDeleteSession(_ context.Con // // executeBackChannelLogout only fails on system errors so not on URL errors, so this should be fine // even if an upstream URL fails! - if err := s.r.ConsentManager().DeleteLoginSession(r.Context(), sid); errors.Is(err, sqlcon.ErrNoRows) { + if session, err := s.r.ConsentManager().DeleteLoginSession(ctx, sid); errors.Is(err, sqlcon.ErrNoRows) { // This is ok (session probably already revoked), do nothing! } else if err != nil { return err + } else { + _ = s.r.Kratos().DisableSession(ctx, session.KratosSessionID.String()) } return nil @@ -1058,7 +1065,7 @@ func (s *DefaultStrategy) completeLogout(ctx context.Context, w http.ResponseWri return nil, err } - if err := s.performBackChannelLogoutAndDeleteSession(r.Context(), r, lr.Subject, lr.SessionID); err != nil { + if err := s.performBackChannelLogoutAndDeleteSession(r, lr.Subject, lr.SessionID); err != nil { return nil, err } @@ -1095,7 +1102,7 @@ func (s *DefaultStrategy) HandleHeadlessLogout(ctx context.Context, _ http.Respo return lsErr } - if err := s.performBackChannelLogoutAndDeleteSession(r.Context(), r, loginSession.Subject, sid); err != nil { + if err := s.performBackChannelLogoutAndDeleteSession(r, loginSession.Subject, sid); err != nil { return err } diff --git a/consent/strategy_default_test.go b/consent/strategy_default_test.go index 3d8efab8130..870c96ffb50 100644 --- a/consent/strategy_default_test.go +++ b/consent/strategy_default_test.go @@ -8,6 +8,7 @@ import ( "net/http" "net/http/cookiejar" "net/http/httptest" + "net/url" "testing" hydra "github.com/ory/hydra-client-go/v2" @@ -17,8 +18,6 @@ import ( "github.com/ory/fosite/token/jwt" "github.com/ory/x/urlx" - "net/url" - "github.com/google/uuid" "github.com/tidwall/gjson" diff --git a/consent/strategy_logout_test.go b/consent/strategy_logout_test.go index 3bd5f911811..0d36d6cce05 100644 --- a/consent/strategy_logout_test.go +++ b/consent/strategy_logout_test.go @@ -16,6 +16,7 @@ import ( "testing" "time" + "github.com/ory/hydra/v2/internal/kratos" "github.com/ory/x/pointerx" "github.com/stretchr/testify/assert" @@ -35,9 +36,11 @@ import ( func TestLogoutFlows(t *testing.T) { ctx := context.Background() + fakeKratos := kratos.NewFake() reg := internal.NewMockedRegistry(t, &contextx.Default{}) reg.Config().MustSet(ctx, config.KeyAccessTokenStrategy, "opaque") reg.Config().MustSet(ctx, config.KeyConsentRequestMaxAge, time.Hour) + reg.WithKratos(fakeKratos) defaultRedirectedMessage := "redirected to default server" postLogoutCallback := func(w http.ResponseWriter, r *http.Request) { @@ -181,7 +184,7 @@ func TestLogoutFlows(t *testing.T) { checkAndAcceptLoginHandler(t, adminApi, subject, func(t *testing.T, res *hydra.OAuth2LoginRequest, err error) hydra.AcceptOAuth2LoginRequest { require.NoError(t, err) //res.Payload.SessionID - return hydra.AcceptOAuth2LoginRequest{Remember: pointerx.Bool(true)} + return hydra.AcceptOAuth2LoginRequest{Remember: pointerx.Bool(true), SessionId: pointerx.Ptr(kratos.FakeSessionID)} }), checkAndAcceptConsentHandler(t, adminApi, func(t *testing.T, res *hydra.OAuth2ConsentRequest, err error) hydra.AcceptOAuth2ConsentRequest { require.NoError(t, err) @@ -476,6 +479,7 @@ func TestLogoutFlows(t *testing.T) { }) t.Run("case=should return to default post logout because session was revoked in browser context", func(t *testing.T) { + fakeKratos.Reset() c := createSampleClient(t) sid := make(chan string) acceptLoginAsAndWatchSid(t, subject, sid) @@ -518,9 +522,13 @@ func TestLogoutFlows(t *testing.T) { assert.NotEmpty(t, res.Request.URL.Query().Get("code")) wg.Wait() + + assert.True(t, fakeKratos.DisableSessionWasCalled) + assert.Equal(t, fakeKratos.LastDisabledSession, kratos.FakeSessionID) }) t.Run("case=should execute backchannel logout in headless flow with sid", func(t *testing.T) { + fakeKratos.Reset() numSidConsumers := 2 sid := make(chan string, numSidConsumers) acceptLoginAsAndWatchSidForConsumers(t, subject, sid, true, numSidConsumers) @@ -535,22 +543,31 @@ func TestLogoutFlows(t *testing.T) { logoutViaHeadlessAndExpectNoContent(t, createBrowserWithSession(t, c), url.Values{"sid": {<-sid}}) backChannelWG.Wait() // we want to ensure that all back channels have been called! + assert.True(t, fakeKratos.DisableSessionWasCalled) + assert.Equal(t, fakeKratos.LastDisabledSession, kratos.FakeSessionID) }) t.Run("case=should logout in headless flow with non-existing sid", func(t *testing.T) { + fakeKratos.Reset() logoutViaHeadlessAndExpectNoContent(t, browserWithoutSession, url.Values{"sid": {"non-existing-sid"}}) + assert.False(t, fakeKratos.DisableSessionWasCalled) }) t.Run("case=should logout in headless flow with session that has remember=false", func(t *testing.T) { + fakeKratos.Reset() sid := make(chan string) acceptLoginAsAndWatchSidForConsumers(t, subject, sid, false, 1) c := createSampleClient(t) logoutViaHeadlessAndExpectNoContent(t, createBrowserWithSession(t, c), url.Values{"sid": {<-sid}}) + assert.True(t, fakeKratos.DisableSessionWasCalled) + assert.Equal(t, fakeKratos.LastDisabledSession, kratos.FakeSessionID) }) t.Run("case=should fail headless logout because neither sid nor subject were provided", func(t *testing.T) { + fakeKratos.Reset() logoutViaHeadlessAndExpectError(t, browserWithoutSession, url.Values{}, `Either 'subject' or 'sid' query parameters need to be defined.`) + assert.False(t, fakeKratos.DisableSessionWasCalled) }) } diff --git a/driver/config/provider.go b/driver/config/provider.go index 509ba9c9b72..ba0e75df457 100644 --- a/driver/config/provider.go +++ b/driver/config/provider.go @@ -80,6 +80,7 @@ const ( KeyPublicURL = "urls.self.public" KeyAdminURL = "urls.self.admin" KeyIssuerURL = "urls.self.issuer" + KeyKratosAdminURL = "urls.kratos.admin" KeyAccessTokenStrategy = "strategies.access_token" KeyJWTScopeClaimStrategy = "strategies.jwt.scope_claim" KeyDBIgnoreUnknownTableColumns = "db.ignore_unknown_table_columns" @@ -388,6 +389,12 @@ func (p *DefaultProvider) IssuerURL(ctx context.Context) *url.URL { ) } +func (p *DefaultProvider) KratosAdminURL(ctx context.Context) (*url.URL, bool) { + u := p.getProvider(ctx).RequestURIF(KeyKratosAdminURL, nil) + + return u, u != nil +} + func (p *DefaultProvider) OAuth2ClientRegistrationURL(ctx context.Context) *url.URL { return p.getProvider(ctx).RequestURIF(KeyOAuth2ClientRegistrationURL, new(url.URL)) } diff --git a/driver/registry.go b/driver/registry.go index d518d8a7f6e..e81d7c35e9a 100644 --- a/driver/registry.go +++ b/driver/registry.go @@ -10,6 +10,7 @@ import ( "go.opentelemetry.io/otel/trace" + "github.com/ory/hydra/v2/internal/kratos" "github.com/ory/x/httprouterx" "github.com/ory/x/popx" @@ -54,6 +55,7 @@ type Registry interface { WithLogger(l *logrusx.Logger) Registry WithTracer(t trace.Tracer) Registry WithTracerWrapper(TracerWrapper) Registry + WithKratos(k kratos.Client) Registry x.HTTPClientProvider GetJWKSFetcherStrategy() fosite.JWKSFetcherStrategy @@ -72,6 +74,8 @@ type Registry interface { x.TracingProvider FlowCipher() *aead.XChaCha20Poly1305 + kratos.Provider + RegisterRoutes(ctx context.Context, admin *httprouterx.RouterAdmin, public *httprouterx.RouterPublic) ClientHandler() *client.Handler KeyHandler() *jwk.Handler diff --git a/driver/registry_base.go b/driver/registry_base.go index 910084ced52..0f85fb50be5 100644 --- a/driver/registry_base.go +++ b/driver/registry_base.go @@ -28,6 +28,7 @@ import ( "github.com/ory/hydra/v2/driver/config" "github.com/ory/hydra/v2/fositex" "github.com/ory/hydra/v2/hsm" + "github.com/ory/hydra/v2/internal/kratos" "github.com/ory/hydra/v2/jwk" "github.com/ory/hydra/v2/oauth2" "github.com/ory/hydra/v2/oauth2/trust" @@ -88,6 +89,7 @@ type RegistryBase struct { hmacs *foauth2.HMACSHAStrategy fc *fositex.Config publicCORS *cors.Cors + kratos kratos.Client } func (m *RegistryBase) GetJWKSFetcherStrategy() fosite.JWKSFetcherStrategy { @@ -201,6 +203,11 @@ func (m *RegistryBase) WithTracerWrapper(wrapper TracerWrapper) Registry { return m.r } +func (m *RegistryBase) WithKratos(k kratos.Client) Registry { + m.kratos = k + return m.r +} + func (m *RegistryBase) Logger() *logrusx.Logger { if m.l == nil { m.l = logrusx.New("Ory Hydra", m.BuildVersion()) @@ -552,3 +559,10 @@ func (m *RegistryBase) HSMContext() hsm.Context { func (m *RegistrySQL) ClientAuthenticator() x.ClientAuthenticator { return m.OAuth2Provider().(*fosite.Fosite) } + +func (m *RegistryBase) Kratos() kratos.Client { + if m.kratos == nil { + m.kratos = kratos.New(m) + } + return m.kratos +} diff --git a/flow/consent_types.go b/flow/consent_types.go index 89e56ef8aa7..6986bdfbd1e 100644 --- a/flow/consent_types.go +++ b/flow/consent_types.go @@ -42,11 +42,12 @@ type OAuth2RedirectTo struct { // swagger:ignore type LoginSession struct { - ID string `db:"id"` - NID uuid.UUID `db:"nid"` - AuthenticatedAt sqlxx.NullTime `db:"authenticated_at"` - Subject string `db:"subject"` - Remember bool `db:"remember"` + ID string `db:"id"` + NID uuid.UUID `db:"nid"` + AuthenticatedAt sqlxx.NullTime `db:"authenticated_at"` + Subject string `db:"subject"` + KratosSessionID sqlxx.NullString `db:"kratos_session_id"` + Remember bool `db:"remember"` } func (LoginSession) TableName() string { @@ -292,6 +293,12 @@ type HandledLoginRequest struct { // required: true Subject string `json:"subject"` + // KratosSessionID is the session ID of the end-user that authenticated. + // If specified, we will use this value to propagate the logout. + // + // required: false + KratosSessionID string `json:"session_id"` + // ForceSubjectIdentifier forces the "pairwise" user ID of the end-user that authenticated. The "pairwise" user ID refers to the // (Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID // Connect specification. It allows you to set an obfuscated subject ("user") identifier that is unique to the client. diff --git a/flow/flow.go b/flow/flow.go index 0868e7f5f14..566948066ca 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -136,6 +136,8 @@ type Flow struct { // channel logout. Its value can generally be used to associate consecutive login requests by a certain user. SessionID sqlxx.NullString `db:"login_session_id"` + KratosSessionID sqlxx.NullString `db:"kratos_session_id"` + LoginVerifier string `db:"login_verifier"` LoginCSRF string `db:"login_csrf"` @@ -291,6 +293,7 @@ func (f *Flow) HandleLoginRequest(h *HandledLoginRequest) error { f.ForceSubjectIdentifier = h.ForceSubjectIdentifier f.LoginError = h.Error + f.KratosSessionID = sqlxx.NullString(h.KratosSessionID) f.LoginRemember = h.Remember f.LoginRememberFor = h.RememberFor f.LoginExtendSessionLifespan = h.ExtendSessionLifespan @@ -311,6 +314,7 @@ func (f *Flow) GetHandledLoginRequest() HandledLoginRequest { ACR: f.ACR, AMR: f.AMR, Subject: f.Subject, + KratosSessionID: f.KratosSessionID.String(), ForceSubjectIdentifier: f.ForceSubjectIdentifier, Context: f.Context, WasHandled: f.LoginWasUsed, diff --git a/flow/flow_test.go b/flow/flow_test.go index 6358c47595b..9cfe514ca50 100644 --- a/flow/flow_test.go +++ b/flow/flow_test.go @@ -42,6 +42,7 @@ func (f *Flow) setHandledLoginRequest(r *HandledLoginRequest) { f.ACR = r.ACR f.AMR = r.AMR f.Subject = r.Subject + f.KratosSessionID = sqlxx.NullString(r.KratosSessionID) f.ForceSubjectIdentifier = r.ForceSubjectIdentifier f.Context = r.Context f.LoginWasUsed = r.WasHandled diff --git a/go.mod b/go.mod index 35d4722dd2d..c5eb822b48a 100644 --- a/go.mod +++ b/go.mod @@ -44,6 +44,7 @@ require ( github.com/ory/herodot v0.10.3-0.20230626083119-d7e5192f0d88 github.com/ory/hydra-client-go/v2 v2.1.1 github.com/ory/jsonschema/v3 v3.0.8 + github.com/ory/kratos-client-go v0.13.1 github.com/ory/x v0.0.575 github.com/pborman/uuid v1.2.1 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 2d89b2a5f3f..ece661bf778 100644 --- a/go.sum +++ b/go.sum @@ -646,6 +646,8 @@ github.com/ory/herodot v0.10.3-0.20230626083119-d7e5192f0d88 h1:J0CIFKdpUeqKbVMw github.com/ory/herodot v0.10.3-0.20230626083119-d7e5192f0d88/go.mod h1:MMNmY6MG1uB6fnXYFaHoqdV23DTWctlPsmRCeq/2+wc= github.com/ory/jsonschema/v3 v3.0.8 h1:Ssdb3eJ4lDZ/+XnGkvQS/te0p+EkolqwTsDOCxr/FmU= github.com/ory/jsonschema/v3 v3.0.8/go.mod h1:ZPzqjDkwd3QTnb2Z6PAS+OTvBE2x5i6m25wCGx54W/0= +github.com/ory/kratos-client-go v0.13.1 h1:o+pFV9ZRMFSBa4QeNJYbJeLz036UWU4p+7yfKghK+0E= +github.com/ory/kratos-client-go v0.13.1/go.mod h1:hkrFJuHSBQw+qN6Ks0faOAYhAKwtpjvhCZzsQ7g/Ufc= github.com/ory/x v0.0.575 h1:LvOeR+YlJ6/JtvIJvSwMoDBY/i3GACUe7HpWXHGNUTA= github.com/ory/x v0.0.575/go.mod h1:aeJFTlvDLGYSABzPS3z5SeLcYC52Ek7uGZiuYGcTMSU= github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= diff --git a/internal/httpclient/api/openapi.yaml b/internal/httpclient/api/openapi.yaml index 0841ffa5e9d..c3cc32a129f 100644 --- a/internal/httpclient/api/openapi.yaml +++ b/internal/httpclient/api/openapi.yaml @@ -2001,6 +2001,10 @@ components: \ for the duration of the browser session (using a session cookie)." format: int64 type: integer + session_id: + description: "KratosSessionID is the session ID of the end-user that authenticated.\n\ + If specified, we will use this value to propagate the logout." + type: string subject: description: Subject is the user ID of the end-user that authenticated. type: string diff --git a/internal/httpclient/docs/AcceptOAuth2LoginRequest.md b/internal/httpclient/docs/AcceptOAuth2LoginRequest.md index 5c41c4923bd..5a885b50aea 100644 --- a/internal/httpclient/docs/AcceptOAuth2LoginRequest.md +++ b/internal/httpclient/docs/AcceptOAuth2LoginRequest.md @@ -11,6 +11,7 @@ Name | Type | Description | Notes **ForceSubjectIdentifier** | Pointer to **string** | ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the (Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID Connect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client. Please note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the sub claim in the OAuth 2.0 Introspection. Per default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself you can use this field. Please note that setting this field has no effect if `pairwise` is not configured in ORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's configuration). Please also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies that you have to compute this value on every authentication process (probably depending on the client ID or some other unique value). If you fail to compute the proper value, then authentication processes which have id_token_hint set might fail. | [optional] **Remember** | Pointer to **bool** | Remember, if set to true, tells ORY Hydra to remember this user by telling the user agent (browser) to store a cookie with authentication data. If the same user performs another OAuth 2.0 Authorization Request, he/she will not be asked to log in again. | [optional] **RememberFor** | Pointer to **int64** | RememberFor sets how long the authentication should be remembered for in seconds. If set to `0`, the authorization will be remembered for the duration of the browser session (using a session cookie). | [optional] +**SessionId** | Pointer to **string** | KratosSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. | [optional] **Subject** | **string** | Subject is the user ID of the end-user that authenticated. | ## Methods @@ -217,6 +218,31 @@ SetRememberFor sets RememberFor field to given value. HasRememberFor returns a boolean if a field has been set. +### GetSessionId + +`func (o *AcceptOAuth2LoginRequest) GetSessionId() string` + +GetSessionId returns the SessionId field if non-nil, zero value otherwise. + +### GetSessionIdOk + +`func (o *AcceptOAuth2LoginRequest) GetSessionIdOk() (*string, bool)` + +GetSessionIdOk returns a tuple with the SessionId field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetSessionId + +`func (o *AcceptOAuth2LoginRequest) SetSessionId(v string)` + +SetSessionId sets SessionId field to given value. + +### HasSessionId + +`func (o *AcceptOAuth2LoginRequest) HasSessionId() bool` + +HasSessionId returns a boolean if a field has been set. + ### GetSubject `func (o *AcceptOAuth2LoginRequest) GetSubject() string` diff --git a/internal/httpclient/model_accept_o_auth2_login_request.go b/internal/httpclient/model_accept_o_auth2_login_request.go index 36720ee04b3..8194a09614a 100644 --- a/internal/httpclient/model_accept_o_auth2_login_request.go +++ b/internal/httpclient/model_accept_o_auth2_login_request.go @@ -29,6 +29,8 @@ type AcceptOAuth2LoginRequest struct { Remember *bool `json:"remember,omitempty"` // RememberFor sets how long the authentication should be remembered for in seconds. If set to `0`, the authorization will be remembered for the duration of the browser session (using a session cookie). RememberFor *int64 `json:"remember_for,omitempty"` + // KratosSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. + SessionId *string `json:"session_id,omitempty"` // Subject is the user ID of the end-user that authenticated. Subject string `json:"subject"` } @@ -276,6 +278,38 @@ func (o *AcceptOAuth2LoginRequest) SetRememberFor(v int64) { o.RememberFor = &v } +// GetSessionId returns the SessionId field value if set, zero value otherwise. +func (o *AcceptOAuth2LoginRequest) GetSessionId() string { + if o == nil || o.SessionId == nil { + var ret string + return ret + } + return *o.SessionId +} + +// GetSessionIdOk returns a tuple with the SessionId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AcceptOAuth2LoginRequest) GetSessionIdOk() (*string, bool) { + if o == nil || o.SessionId == nil { + return nil, false + } + return o.SessionId, true +} + +// HasSessionId returns a boolean if a field has been set. +func (o *AcceptOAuth2LoginRequest) HasSessionId() bool { + if o != nil && o.SessionId != nil { + return true + } + + return false +} + +// SetSessionId gets a reference to the given string and assigns it to the SessionId field. +func (o *AcceptOAuth2LoginRequest) SetSessionId(v string) { + o.SessionId = &v +} + // GetSubject returns the Subject field value func (o *AcceptOAuth2LoginRequest) GetSubject() string { if o == nil { @@ -323,6 +357,9 @@ func (o AcceptOAuth2LoginRequest) MarshalJSON() ([]byte, error) { if o.RememberFor != nil { toSerialize["remember_for"] = o.RememberFor } + if o.SessionId != nil { + toSerialize["session_id"] = o.SessionId + } if true { toSerialize["subject"] = o.Subject } diff --git a/internal/kratos/fake_kratos.go b/internal/kratos/fake_kratos.go new file mode 100644 index 00000000000..a356146e4df --- /dev/null +++ b/internal/kratos/fake_kratos.go @@ -0,0 +1,35 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +package kratos + +import "context" + +type ( + FakeKratos struct { + DisableSessionWasCalled bool + LastDisabledSession string + } +) + +const ( + FakeSessionID = "fake-kratos-session-id" +) + +var _ Client = new(FakeKratos) + +func NewFake() *FakeKratos { + return &FakeKratos{} +} + +func (f *FakeKratos) DisableSession(_ context.Context, kratosSessionID string) error { + f.DisableSessionWasCalled = true + f.LastDisabledSession = kratosSessionID + + return nil +} + +func (f *FakeKratos) Reset() { + f.DisableSessionWasCalled = false + f.LastDisabledSession = "" +} diff --git a/internal/kratos/kratos.go b/internal/kratos/kratos.go new file mode 100644 index 00000000000..d7db5b771c8 --- /dev/null +++ b/internal/kratos/kratos.go @@ -0,0 +1,69 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +package kratos + +import ( + "context" + "net/url" + + "go.opentelemetry.io/otel/attribute" + + "github.com/ory/hydra/v2/driver/config" + "github.com/ory/hydra/v2/x" + client "github.com/ory/kratos-client-go" + "github.com/ory/x/otelx" +) + +type ( + dependencies interface { + config.Provider + x.HTTPClientProvider + x.TracingProvider + } + Provider interface { + Kratos() Client + } + Client interface { + DisableSession(ctx context.Context, kratosSessionID string) error + } + Default struct { + dependencies + } +) + +func New(d dependencies) Client { + return &Default{dependencies: d} +} + +func (k *Default) DisableSession(ctx context.Context, kratosSessionID string) (err error) { + ctx, span := k.Tracer(ctx).Tracer().Start(ctx, "kratos.DisableSession") + otelx.End(span, &err) + + adminURL, ok := k.Config().KratosAdminURL(ctx) + if !ok { + span.SetAttributes(attribute.Bool("skipped", true)) + span.SetAttributes(attribute.String("reason", "kratos admin url not set")) + return nil + } + + if kratosSessionID == "" { + span.SetAttributes(attribute.Bool("skipped", true)) + span.SetAttributes(attribute.String("reason", "kratos session ID is empty")) + return nil + } + + kratos := client.NewAPIClient(k.clientConfiguration(ctx, adminURL)) + _, err = kratos.IdentityApi.DisableSession(ctx, kratosSessionID).Execute() + + return err + +} + +func (k *Default) clientConfiguration(ctx context.Context, adminURL *url.URL) *client.Configuration { + configuration := client.NewConfiguration() + configuration.Servers = client.ServerConfigurations{{URL: adminURL.String()}} + configuration.HTTPClient = k.HTTPClient(ctx).StandardClient() + + return configuration +} diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0001.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0001.json index a642f6606bf..9ed28857755 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0001.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0001.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0001", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0002.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0002.json index 65d132ab888..aeac476a9ab 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0002.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0002.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0002", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0003.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0003.json index dfa9ae21e86..76ff6e432b5 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0003.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0003.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0003", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0004.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0004.json index 4411c2064a5..a8688ae9c31 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0004.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0004.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0004", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0005.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0005.json index cba9dcf6125..2e21492c6d3 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0005.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0005.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0005", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0006.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0006.json index 2081943455f..1a6e76f87da 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0006.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0006.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0006", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0007.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0007.json index c701732aac3..619fcc9b034 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0007.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0007.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0007", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0008.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0008.json index b8fc116b728..b6ef3fc1632 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0008.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0008.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0008", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0009.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0009.json index 57cee5ecb1e..7cb33bb7c7d 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0009.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0009.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0009", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0010.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0010.json index 3e6b4d5fa10..93539884214 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0010.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0010.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0010", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0011.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0011.json index 1344d7158fb..f0ee5752657 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0011.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0011.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0011", + "KratosSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0012.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0012.json index 876277e2440..bc7c53ecc7a 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0012.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0012.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0012", + "KratosSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0013.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0013.json index 404a1b4fe37..7b9795b58ce 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0013.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0013.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0013", + "KratosSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0014.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0014.json index 472bef86c13..d25982c1b71 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0014.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0014.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0014", + "KratosSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0015.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0015.json index 1f82a76af6b..74f67ac3124 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0015.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0015.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0015", + "KratosSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0016.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0016.json index e4e49d49af9..4ee258ff5d4 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0016.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0016.json @@ -3,5 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0016", + "KratosSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0001.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0001.json index d89f26c7d42..a42275d0e7e 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0001.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0001.json @@ -14,6 +14,7 @@ "ClientID": "", "RequestURL": "http://request/0001", "SessionID": "", + "KratosSessionID": "", "LoginVerifier": "verifier-0001", "LoginCSRF": "csrf-0001", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0002.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0002.json index 369ba83ba25..15477fa8d96 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0002.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0002.json @@ -14,6 +14,7 @@ "ClientID": "", "RequestURL": "http://request/0002", "SessionID": "", + "KratosSessionID": "", "LoginVerifier": "verifier-0002", "LoginCSRF": "csrf-0002", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0003.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0003.json index 66718c0ba27..ff40b309384 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0003.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0003.json @@ -14,6 +14,7 @@ "ClientID": "", "RequestURL": "http://request/0003", "SessionID": "auth_session-0003", + "KratosSessionID": "", "LoginVerifier": "verifier-0003", "LoginCSRF": "csrf-0003", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0004.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0004.json index e707616aa87..53fd97cd38c 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0004.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0004.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0004", "SessionID": "auth_session-0004", + "KratosSessionID": "", "LoginVerifier": "verifier-0004", "LoginCSRF": "csrf-0004", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0005.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0005.json index fcc4760db32..f30f13352bb 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0005.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0005.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0005", "SessionID": "auth_session-0005", + "KratosSessionID": "", "LoginVerifier": "verifier-0005", "LoginCSRF": "csrf-0005", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0006.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0006.json index 825ca5b9b00..b17f4f62df6 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0006.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0006.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0006", "SessionID": "auth_session-0006", + "KratosSessionID": "", "LoginVerifier": "verifier-0006", "LoginCSRF": "csrf-0006", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0007.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0007.json index 1d20de4190f..a6428804cb3 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0007.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0007.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0007", "SessionID": "auth_session-0007", + "KratosSessionID": "", "LoginVerifier": "verifier-0007", "LoginCSRF": "csrf-0007", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0008.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0008.json index 3ed3dad5245..595ecbe13ee 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0008.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0008.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0008", "SessionID": "auth_session-0008", + "KratosSessionID": "", "LoginVerifier": "verifier-0008", "LoginCSRF": "csrf-0008", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0009.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0009.json index 61f8bbabf0c..4c56c49cc06 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0009.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0009.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0009", "SessionID": "auth_session-0009", + "KratosSessionID": "", "LoginVerifier": "verifier-0009", "LoginCSRF": "csrf-0009", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0010.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0010.json index a886dd0aefe..82592b03db4 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0010.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0010.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0010", "SessionID": "auth_session-0010", + "KratosSessionID": "", "LoginVerifier": "verifier-0010", "LoginCSRF": "csrf-0010", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0011.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0011.json index dda3212a8d7..7d68c1cacde 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0011.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0011.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0011", "SessionID": "auth_session-0011", + "KratosSessionID": "", "LoginVerifier": "verifier-0011", "LoginCSRF": "csrf-0011", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0012.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0012.json index d6491837a10..eb93e192387 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0012.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0012.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0012", "SessionID": "auth_session-0012", + "KratosSessionID": "", "LoginVerifier": "verifier-0012", "LoginCSRF": "csrf-0012", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0013.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0013.json index 89ca9f7daf4..0238bb794f7 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0013.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0013.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0013", "SessionID": "auth_session-0013", + "KratosSessionID": "", "LoginVerifier": "verifier-0013", "LoginCSRF": "csrf-0013", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0014.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0014.json index d020259b581..d3c832a270c 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0014.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0014.json @@ -16,6 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0014", "SessionID": "auth_session-0014", + "KratosSessionID": "", "LoginVerifier": "verifier-0014", "LoginCSRF": "csrf-0014", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0015.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0015.json index 78ee82f16d5..b7aedcb245a 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0015.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0015.json @@ -18,6 +18,7 @@ "ClientID": "", "RequestURL": "http://request/0015", "SessionID": "auth_session-0015", + "KratosSessionID": "", "LoginVerifier": "verifier-0015", "LoginCSRF": "csrf-0015", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0016.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0016.json index e3bddee39a1..09a9125013d 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0016.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0016.json @@ -18,6 +18,7 @@ "ClientID": "", "RequestURL": "http://request/0016", "SessionID": "auth_session-0016", + "KratosSessionID": "", "LoginVerifier": "verifier-0016", "LoginCSRF": "csrf-0016", "LoginInitializedAt": null, diff --git a/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.down.sql b/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.down.sql new file mode 100644 index 00000000000..84b7cfe9b41 --- /dev/null +++ b/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE hydra_oauth2_flow DROP COLUMN kratos_session_id; +ALTER TABLE hydra_oauth2_authentication_session DROP COLUMN kratos_session_id; \ No newline at end of file diff --git a/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.up.sql b/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.up.sql new file mode 100644 index 00000000000..11ecf8165f0 --- /dev/null +++ b/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE hydra_oauth2_flow ADD COLUMN kratos_session_id VARCHAR(40); +ALTER TABLE hydra_oauth2_authentication_session ADD COLUMN kratos_session_id VARCHAR(40); \ No newline at end of file diff --git a/persistence/sql/persister_consent.go b/persistence/sql/persister_consent.go index bd401d56423..11ca9b28a46 100644 --- a/persistence/sql/persister_consent.go +++ b/persistence/sql/persister_consent.go @@ -14,6 +14,7 @@ import ( "github.com/gofrs/uuid" "github.com/ory/hydra/v2/oauth2/flowctx" + "github.com/ory/x/otelx" "github.com/ory/x/sqlxx" "github.com/ory/x/errorsx" @@ -421,13 +422,19 @@ func (p *Persister) ConfirmLoginSession(ctx context.Context, session *flow.Login return p.CreateWithNetwork(ctx, session) } + var kratosSessionID string + if session != nil { + kratosSessionID = session.KratosSessionID.String() + } + // In some unit tests, we still confirm the login session without data from the cookie. We can remove this case // once all tests are fixed. n, err := p.Connection(ctx).Where("id = ? AND nid = ?", id, p.NetworkID(ctx)).UpdateQuery(&flow.LoginSession{ AuthenticatedAt: sqlxx.NullTime(authenticatedAt), Subject: subject, Remember: remember, - }, "authenticated_at", "subject", "remember") + KratosSessionID: sqlxx.NullString(kratosSessionID), + }, "authenticated_at", "subject", "remember", "kratos_session_id") if err != nil { return sqlcon.HandleError(err) } @@ -450,16 +457,24 @@ func (p *Persister) CreateLoginSession(ctx context.Context, session *flow.LoginS return nil } -func (p *Persister) DeleteLoginSession(ctx context.Context, id string) error { +func (p *Persister) DeleteLoginSession(ctx context.Context, id string) (deletedSession *flow.LoginSession, err error) { ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteLoginSession") - defer span.End() + defer otelx.End(span, &err) - count, err := p.Connection(ctx).RawQuery("DELETE FROM hydra_oauth2_authentication_session WHERE id=? AND nid=?", id, p.NetworkID(ctx)).ExecWithCount() - if count == 0 { - return errorsx.WithStack(x.ErrNotFound) - } else { - return sqlcon.HandleError(err) + var session flow.LoginSession + + err = p.Connection(ctx).RawQuery( + `DELETE FROM hydra_oauth2_authentication_session + WHERE id = ? AND nid = ? + RETURNING *`, + id, + p.NetworkID(ctx), + ).First(&session) + if err != nil { + return nil, sqlcon.HandleError(err) } + + return &session, nil } func (p *Persister) FindGrantedAndRememberedConsentRequests(ctx context.Context, client, subject string) (rs []flow.AcceptOAuth2ConsentRequest, err error) { diff --git a/persistence/sql/persister_nid_test.go b/persistence/sql/persister_nid_test.go index 83fad7c1452..e3c72bd3856 100644 --- a/persistence/sql/persister_nid_test.go +++ b/persistence/sql/persister_nid_test.go @@ -10,6 +10,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/ory/hydra/v2/persistence" "github.com/ory/x/uuidx" @@ -632,14 +634,22 @@ func (s *PersisterTestSuite) TestDeleteLoginSession() { t := s.T() for k, r := range s.registries { t.Run(k, func(t *testing.T) { - ls := flow.LoginSession{ID: uuid.Must(uuid.NewV4()).String(), Remember: true} + ls := flow.LoginSession{ + ID: uuid.Must(uuid.NewV4()).String(), + Remember: true, + KratosSessionID: sqlxx.NullString(uuid.Must(uuid.NewV4()).String()), + } persistLoginSession(s.t1, t, r.Persister(), &ls) - require.Error(t, r.Persister().DeleteLoginSession(s.t2, ls.ID)) - _, err := r.Persister().GetRememberedLoginSession(s.t1, nil, ls.ID) + deletedLS, err := r.Persister().DeleteLoginSession(s.t2, ls.ID) + require.Error(t, err) + assert.Nil(t, deletedLS) + _, err = r.Persister().GetRememberedLoginSession(s.t1, nil, ls.ID) require.NoError(t, err) - require.NoError(t, r.Persister().DeleteLoginSession(s.t1, ls.ID)) + deletedLS, err = r.Persister().DeleteLoginSession(s.t1, ls.ID) + require.NoError(t, err) + assert.Equal(t, ls, *deletedLS) _, err = r.Persister().GetRememberedLoginSession(s.t1, nil, ls.ID) require.Error(t, err) }) diff --git a/spec/api.json b/spec/api.json index 0c4a3d7077f..e0e3463623d 100644 --- a/spec/api.json +++ b/spec/api.json @@ -216,6 +216,10 @@ "format": "int64", "type": "integer" }, + "session_id": { + "description": "KratosSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", + "type": "string" + }, "subject": { "description": "Subject is the user ID of the end-user that authenticated.", "type": "string" diff --git a/spec/config.json b/spec/config.json index cbdba33cdfd..116c0c75247 100644 --- a/spec/config.json +++ b/spec/config.json @@ -760,6 +760,21 @@ "https://my-example.app/logout-successful", "/ui" ] + }, + "kratos": { + "type": "object", + "additionalProperties": false, + "properties": { + "admin": { + "type": "string", + "title": "The admin URL of the ORY Kratos instance.", + "description": "If set, ORY Hydra will use this URL to log out the user in addition to removing the Hydra session.", + "format": "uri-reference", + "examples": [ + "https://kratos.example.com/admin" + ] + } + } } } }, diff --git a/spec/swagger.json b/spec/swagger.json index 48e19616d07..9579048a636 100755 --- a/spec/swagger.json +++ b/spec/swagger.json @@ -2246,6 +2246,10 @@ "type": "integer", "format": "int64" }, + "session_id": { + "description": "KratosSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", + "type": "string" + }, "subject": { "description": "Subject is the user ID of the end-user that authenticated.", "type": "string" From 4649f4d44ab5b13c45c0b585b7310f664499935e Mon Sep 17 00:00:00 2001 From: Henning Perl Date: Thu, 10 Aug 2023 13:50:28 +0200 Subject: [PATCH 2/5] fix: add special case for MySQL --- consent/strategy_default.go | 6 +++- flow/consent_types.go | 2 +- oauth2/fosite_store_test.go | 4 +-- persistence/sql/migratest/migration_test.go | 1 - persistence/sql/persister_consent.go | 35 +++++++++++++++++++++ persistence/sql/persister_nid_test.go | 4 +-- 6 files changed, 45 insertions(+), 7 deletions(-) diff --git a/consent/strategy_default.go b/consent/strategy_default.go index 97a6efddd48..6bff9b8072b 100644 --- a/consent/strategy_default.go +++ b/consent/strategy_default.go @@ -1010,7 +1010,11 @@ func (s *DefaultStrategy) performBackChannelLogoutAndDeleteSession(r *http.Reque } else if err != nil { return err } else { - _ = s.r.Kratos().DisableSession(ctx, session.KratosSessionID.String()) + innerErr := s.r.Kratos().DisableSession(ctx, session.KratosSessionID.String()) + if innerErr != nil { + s.r.Logger().WithError(innerErr).WithField("sid", sid).Error("Unable to revoke session in ORY Kratos.") + } + // We don't return the error here because we don't want to break the logout flow if Kratos is down. } return nil diff --git a/flow/consent_types.go b/flow/consent_types.go index 6986bdfbd1e..0fae36d0ccb 100644 --- a/flow/consent_types.go +++ b/flow/consent_types.go @@ -297,7 +297,7 @@ type HandledLoginRequest struct { // If specified, we will use this value to propagate the logout. // // required: false - KratosSessionID string `json:"session_id"` + KratosSessionID string `json:"kratos_session_id,omitempty"` // ForceSubjectIdentifier forces the "pairwise" user ID of the end-user that authenticated. The "pairwise" user ID refers to the // (Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID diff --git a/oauth2/fosite_store_test.go b/oauth2/fosite_store_test.go index 767f33444d5..f1e0a03c65a 100644 --- a/oauth2/fosite_store_test.go +++ b/oauth2/fosite_store_test.go @@ -52,7 +52,7 @@ func setupRegistries(t *testing.T) { } func TestManagers(t *testing.T) { - ctx := context.TODO() + ctx := context.Background() tests := []struct { name string enableSessionEncrypted bool @@ -67,7 +67,7 @@ func TestManagers(t *testing.T) { }, } for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { + t.Run("suite="+tc.name, func(t *testing.T) { setupRegistries(t) require.NoError(t, registries["memory"].ClientManager().CreateClient(context.Background(), &client.Client{LegacyClientID: "foobar"})) // this is a workaround because the client is not being created for memory store by test helpers. diff --git a/persistence/sql/migratest/migration_test.go b/persistence/sql/migratest/migration_test.go index 7c4db0c81d2..e08834a9b4a 100644 --- a/persistence/sql/migratest/migration_test.go +++ b/persistence/sql/migratest/migration_test.go @@ -60,7 +60,6 @@ func CompareWithFixture(t *testing.T, actual interface{}, prefix string, id stri } func TestMigrations(t *testing.T) { - //pop.Debug = true connections := make(map[string]*pop.Connection, 1) if testing.Short() { diff --git a/persistence/sql/persister_consent.go b/persistence/sql/persister_consent.go index 11ca9b28a46..ced61f3c0e6 100644 --- a/persistence/sql/persister_consent.go +++ b/persistence/sql/persister_consent.go @@ -461,6 +461,11 @@ func (p *Persister) DeleteLoginSession(ctx context.Context, id string) (deletedS ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteLoginSession") defer otelx.End(span, &err) + if p.Connection(ctx).Dialect.Name() == "mysql" { + // MySQL does not support RETURNING. + return p.mySQLDeleteLoginSession(ctx, id) + } + var session flow.LoginSession err = p.Connection(ctx).RawQuery( @@ -477,6 +482,36 @@ func (p *Persister) DeleteLoginSession(ctx context.Context, id string) (deletedS return &session, nil } +func (p *Persister) mySQLDeleteLoginSession(ctx context.Context, id string) (*flow.LoginSession, error) { + var session flow.LoginSession + + err := p.Connection(ctx).Transaction(func(tx *pop.Connection) error { + err := tx.RawQuery(` +SELECT * FROM hydra_oauth2_authentication_session +WHERE id = ? AND nid = ?`, + id, + p.NetworkID(ctx), + ).First(&session) + if err != nil { + return err + } + + return p.Connection(ctx).RawQuery(` +DELETE FROM hydra_oauth2_authentication_session +WHERE id = ? AND nid = ?`, + id, + p.NetworkID(ctx), + ).Exec() + }) + + if err != nil { + return nil, sqlcon.HandleError(err) + } + + return &session, nil + +} + func (p *Persister) FindGrantedAndRememberedConsentRequests(ctx context.Context, client, subject string) (rs []flow.AcceptOAuth2ConsentRequest, err error) { ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.FindGrantedAndRememberedConsentRequests") defer span.End() diff --git a/persistence/sql/persister_nid_test.go b/persistence/sql/persister_nid_test.go index e3c72bd3856..b60ec326874 100644 --- a/persistence/sql/persister_nid_test.go +++ b/persistence/sql/persister_nid_test.go @@ -190,7 +190,7 @@ func (s *PersisterTestSuite) TestConfirmLoginSession() { require.NoError(t, r.Persister().CreateLoginSession(s.t1, ls)) // Expects the login session to be confirmed in the correct context. - require.NoError(t, r.Persister().ConfirmLoginSession(s.t1, ls, ls.ID, time.Now(), ls.Subject, !ls.Remember)) + require.NoError(t, r.Persister().ConfirmLoginSession(s.t1, ls, ls.ID, time.Now().UTC(), ls.Subject, !ls.Remember)) actual := &flow.LoginSession{} require.NoError(t, r.Persister().Connection(context.Background()).Find(actual, ls.ID)) exp, _ := json.Marshal(ls) @@ -199,7 +199,7 @@ func (s *PersisterTestSuite) TestConfirmLoginSession() { // Can't find the login session in the wrong context. require.ErrorIs(t, - r.Persister().ConfirmLoginSession(s.t2, ls, ls.ID, time.Now(), ls.Subject, !ls.Remember), + r.Persister().ConfirmLoginSession(s.t2, ls, ls.ID, time.Now().UTC(), ls.Subject, !ls.Remember), x.ErrNotFound, ) }) From fb0707373b29a699290315820756cfa98380b0b5 Mon Sep 17 00:00:00 2001 From: Henning Perl Date: Thu, 10 Aug 2023 16:28:04 +0200 Subject: [PATCH 3/5] chore: update sdk --- consent/strategy_logout_test.go | 2 +- internal/httpclient/api/openapi.yaml | 8 +- .../docs/AcceptOAuth2LoginRequest.md | 52 ++++++------- .../model_accept_o_auth2_login_request.go | 74 +++++++++---------- spec/api.json | 8 +- spec/swagger.json | 8 +- 6 files changed, 76 insertions(+), 76 deletions(-) diff --git a/consent/strategy_logout_test.go b/consent/strategy_logout_test.go index 0d36d6cce05..5f093ccd1eb 100644 --- a/consent/strategy_logout_test.go +++ b/consent/strategy_logout_test.go @@ -184,7 +184,7 @@ func TestLogoutFlows(t *testing.T) { checkAndAcceptLoginHandler(t, adminApi, subject, func(t *testing.T, res *hydra.OAuth2LoginRequest, err error) hydra.AcceptOAuth2LoginRequest { require.NoError(t, err) //res.Payload.SessionID - return hydra.AcceptOAuth2LoginRequest{Remember: pointerx.Bool(true), SessionId: pointerx.Ptr(kratos.FakeSessionID)} + return hydra.AcceptOAuth2LoginRequest{Remember: pointerx.Ptr(true), KratosSessionId: pointerx.Ptr(kratos.FakeSessionID)} }), checkAndAcceptConsentHandler(t, adminApi, func(t *testing.T, res *hydra.OAuth2ConsentRequest, err error) hydra.AcceptOAuth2ConsentRequest { require.NoError(t, err) diff --git a/internal/httpclient/api/openapi.yaml b/internal/httpclient/api/openapi.yaml index c3cc32a129f..db75a789076 100644 --- a/internal/httpclient/api/openapi.yaml +++ b/internal/httpclient/api/openapi.yaml @@ -1989,6 +1989,10 @@ components: \ the proper value, then authentication processes which have id_token_hint\ \ set might fail." type: string + kratos_session_id: + description: "KratosSessionID is the session ID of the end-user that authenticated.\n\ + If specified, we will use this value to propagate the logout." + type: string remember: description: "Remember, if set to true, tells ORY Hydra to remember this\ \ user by telling the user agent (browser) to store\na cookie with authentication\ @@ -2001,10 +2005,6 @@ components: \ for the duration of the browser session (using a session cookie)." format: int64 type: integer - session_id: - description: "KratosSessionID is the session ID of the end-user that authenticated.\n\ - If specified, we will use this value to propagate the logout." - type: string subject: description: Subject is the user ID of the end-user that authenticated. type: string diff --git a/internal/httpclient/docs/AcceptOAuth2LoginRequest.md b/internal/httpclient/docs/AcceptOAuth2LoginRequest.md index 5a885b50aea..785add0f8ef 100644 --- a/internal/httpclient/docs/AcceptOAuth2LoginRequest.md +++ b/internal/httpclient/docs/AcceptOAuth2LoginRequest.md @@ -9,9 +9,9 @@ Name | Type | Description | Notes **Context** | Pointer to **interface{}** | | [optional] **ExtendSessionLifespan** | Pointer to **bool** | Extend OAuth2 authentication session lifespan If set to `true`, the OAuth2 authentication cookie lifespan is extended. This is for example useful if you want the user to be able to use `prompt=none` continuously. This value can only be set to `true` if the user has an authentication, which is the case if the `skip` value is `true`. | [optional] **ForceSubjectIdentifier** | Pointer to **string** | ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the (Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID Connect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client. Please note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the sub claim in the OAuth 2.0 Introspection. Per default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself you can use this field. Please note that setting this field has no effect if `pairwise` is not configured in ORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's configuration). Please also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies that you have to compute this value on every authentication process (probably depending on the client ID or some other unique value). If you fail to compute the proper value, then authentication processes which have id_token_hint set might fail. | [optional] +**KratosSessionId** | Pointer to **string** | KratosSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. | [optional] **Remember** | Pointer to **bool** | Remember, if set to true, tells ORY Hydra to remember this user by telling the user agent (browser) to store a cookie with authentication data. If the same user performs another OAuth 2.0 Authorization Request, he/she will not be asked to log in again. | [optional] **RememberFor** | Pointer to **int64** | RememberFor sets how long the authentication should be remembered for in seconds. If set to `0`, the authorization will be remembered for the duration of the browser session (using a session cookie). | [optional] -**SessionId** | Pointer to **string** | KratosSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. | [optional] **Subject** | **string** | Subject is the user ID of the end-user that authenticated. | ## Methods @@ -168,6 +168,31 @@ SetForceSubjectIdentifier sets ForceSubjectIdentifier field to given value. HasForceSubjectIdentifier returns a boolean if a field has been set. +### GetKratosSessionId + +`func (o *AcceptOAuth2LoginRequest) GetKratosSessionId() string` + +GetKratosSessionId returns the KratosSessionId field if non-nil, zero value otherwise. + +### GetKratosSessionIdOk + +`func (o *AcceptOAuth2LoginRequest) GetKratosSessionIdOk() (*string, bool)` + +GetKratosSessionIdOk returns a tuple with the KratosSessionId field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetKratosSessionId + +`func (o *AcceptOAuth2LoginRequest) SetKratosSessionId(v string)` + +SetKratosSessionId sets KratosSessionId field to given value. + +### HasKratosSessionId + +`func (o *AcceptOAuth2LoginRequest) HasKratosSessionId() bool` + +HasKratosSessionId returns a boolean if a field has been set. + ### GetRemember `func (o *AcceptOAuth2LoginRequest) GetRemember() bool` @@ -218,31 +243,6 @@ SetRememberFor sets RememberFor field to given value. HasRememberFor returns a boolean if a field has been set. -### GetSessionId - -`func (o *AcceptOAuth2LoginRequest) GetSessionId() string` - -GetSessionId returns the SessionId field if non-nil, zero value otherwise. - -### GetSessionIdOk - -`func (o *AcceptOAuth2LoginRequest) GetSessionIdOk() (*string, bool)` - -GetSessionIdOk returns a tuple with the SessionId field if it's non-nil, zero value otherwise -and a boolean to check if the value has been set. - -### SetSessionId - -`func (o *AcceptOAuth2LoginRequest) SetSessionId(v string)` - -SetSessionId sets SessionId field to given value. - -### HasSessionId - -`func (o *AcceptOAuth2LoginRequest) HasSessionId() bool` - -HasSessionId returns a boolean if a field has been set. - ### GetSubject `func (o *AcceptOAuth2LoginRequest) GetSubject() string` diff --git a/internal/httpclient/model_accept_o_auth2_login_request.go b/internal/httpclient/model_accept_o_auth2_login_request.go index 8194a09614a..3d4afaf88f9 100644 --- a/internal/httpclient/model_accept_o_auth2_login_request.go +++ b/internal/httpclient/model_accept_o_auth2_login_request.go @@ -25,12 +25,12 @@ type AcceptOAuth2LoginRequest struct { ExtendSessionLifespan *bool `json:"extend_session_lifespan,omitempty"` // ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the (Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID Connect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client. Please note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the sub claim in the OAuth 2.0 Introspection. Per default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself you can use this field. Please note that setting this field has no effect if `pairwise` is not configured in ORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's configuration). Please also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies that you have to compute this value on every authentication process (probably depending on the client ID or some other unique value). If you fail to compute the proper value, then authentication processes which have id_token_hint set might fail. ForceSubjectIdentifier *string `json:"force_subject_identifier,omitempty"` + // KratosSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. + KratosSessionId *string `json:"kratos_session_id,omitempty"` // Remember, if set to true, tells ORY Hydra to remember this user by telling the user agent (browser) to store a cookie with authentication data. If the same user performs another OAuth 2.0 Authorization Request, he/she will not be asked to log in again. Remember *bool `json:"remember,omitempty"` // RememberFor sets how long the authentication should be remembered for in seconds. If set to `0`, the authorization will be remembered for the duration of the browser session (using a session cookie). RememberFor *int64 `json:"remember_for,omitempty"` - // KratosSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. - SessionId *string `json:"session_id,omitempty"` // Subject is the user ID of the end-user that authenticated. Subject string `json:"subject"` } @@ -214,6 +214,38 @@ func (o *AcceptOAuth2LoginRequest) SetForceSubjectIdentifier(v string) { o.ForceSubjectIdentifier = &v } +// GetKratosSessionId returns the KratosSessionId field value if set, zero value otherwise. +func (o *AcceptOAuth2LoginRequest) GetKratosSessionId() string { + if o == nil || o.KratosSessionId == nil { + var ret string + return ret + } + return *o.KratosSessionId +} + +// GetKratosSessionIdOk returns a tuple with the KratosSessionId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AcceptOAuth2LoginRequest) GetKratosSessionIdOk() (*string, bool) { + if o == nil || o.KratosSessionId == nil { + return nil, false + } + return o.KratosSessionId, true +} + +// HasKratosSessionId returns a boolean if a field has been set. +func (o *AcceptOAuth2LoginRequest) HasKratosSessionId() bool { + if o != nil && o.KratosSessionId != nil { + return true + } + + return false +} + +// SetKratosSessionId gets a reference to the given string and assigns it to the KratosSessionId field. +func (o *AcceptOAuth2LoginRequest) SetKratosSessionId(v string) { + o.KratosSessionId = &v +} + // GetRemember returns the Remember field value if set, zero value otherwise. func (o *AcceptOAuth2LoginRequest) GetRemember() bool { if o == nil || o.Remember == nil { @@ -278,38 +310,6 @@ func (o *AcceptOAuth2LoginRequest) SetRememberFor(v int64) { o.RememberFor = &v } -// GetSessionId returns the SessionId field value if set, zero value otherwise. -func (o *AcceptOAuth2LoginRequest) GetSessionId() string { - if o == nil || o.SessionId == nil { - var ret string - return ret - } - return *o.SessionId -} - -// GetSessionIdOk returns a tuple with the SessionId field value if set, nil otherwise -// and a boolean to check if the value has been set. -func (o *AcceptOAuth2LoginRequest) GetSessionIdOk() (*string, bool) { - if o == nil || o.SessionId == nil { - return nil, false - } - return o.SessionId, true -} - -// HasSessionId returns a boolean if a field has been set. -func (o *AcceptOAuth2LoginRequest) HasSessionId() bool { - if o != nil && o.SessionId != nil { - return true - } - - return false -} - -// SetSessionId gets a reference to the given string and assigns it to the SessionId field. -func (o *AcceptOAuth2LoginRequest) SetSessionId(v string) { - o.SessionId = &v -} - // GetSubject returns the Subject field value func (o *AcceptOAuth2LoginRequest) GetSubject() string { if o == nil { @@ -351,15 +351,15 @@ func (o AcceptOAuth2LoginRequest) MarshalJSON() ([]byte, error) { if o.ForceSubjectIdentifier != nil { toSerialize["force_subject_identifier"] = o.ForceSubjectIdentifier } + if o.KratosSessionId != nil { + toSerialize["kratos_session_id"] = o.KratosSessionId + } if o.Remember != nil { toSerialize["remember"] = o.Remember } if o.RememberFor != nil { toSerialize["remember_for"] = o.RememberFor } - if o.SessionId != nil { - toSerialize["session_id"] = o.SessionId - } if true { toSerialize["subject"] = o.Subject } diff --git a/spec/api.json b/spec/api.json index e0e3463623d..67f4d6e1346 100644 --- a/spec/api.json +++ b/spec/api.json @@ -207,6 +207,10 @@ "description": "ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the\n(Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID\nConnect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client.\n\nPlease note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the\nsub claim in the OAuth 2.0 Introspection.\n\nPer default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself\nyou can use this field. Please note that setting this field has no effect if `pairwise` is not configured in\nORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's\nconfiguration).\n\nPlease also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies\nthat you have to compute this value on every authentication process (probably depending on the client ID or some\nother unique value).\n\nIf you fail to compute the proper value, then authentication processes which have id_token_hint set might fail.", "type": "string" }, + "kratos_session_id": { + "description": "KratosSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", + "type": "string" + }, "remember": { "description": "Remember, if set to true, tells ORY Hydra to remember this user by telling the user agent (browser) to store\na cookie with authentication data. If the same user performs another OAuth 2.0 Authorization Request, he/she\nwill not be asked to log in again.", "type": "boolean" @@ -216,10 +220,6 @@ "format": "int64", "type": "integer" }, - "session_id": { - "description": "KratosSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", - "type": "string" - }, "subject": { "description": "Subject is the user ID of the end-user that authenticated.", "type": "string" diff --git a/spec/swagger.json b/spec/swagger.json index 9579048a636..ad2926d09f5 100755 --- a/spec/swagger.json +++ b/spec/swagger.json @@ -2237,6 +2237,10 @@ "description": "ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the\n(Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID\nConnect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client.\n\nPlease note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the\nsub claim in the OAuth 2.0 Introspection.\n\nPer default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself\nyou can use this field. Please note that setting this field has no effect if `pairwise` is not configured in\nORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's\nconfiguration).\n\nPlease also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies\nthat you have to compute this value on every authentication process (probably depending on the client ID or some\nother unique value).\n\nIf you fail to compute the proper value, then authentication processes which have id_token_hint set might fail.", "type": "string" }, + "kratos_session_id": { + "description": "KratosSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", + "type": "string" + }, "remember": { "description": "Remember, if set to true, tells ORY Hydra to remember this user by telling the user agent (browser) to store\na cookie with authentication data. If the same user performs another OAuth 2.0 Authorization Request, he/she\nwill not be asked to log in again.", "type": "boolean" @@ -2246,10 +2250,6 @@ "type": "integer", "format": "int64" }, - "session_id": { - "description": "KratosSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", - "type": "string" - }, "subject": { "description": "Subject is the user ID of the end-user that authenticated.", "type": "string" From 1a1a4894f32841be5caa13d72777462699685a00 Mon Sep 17 00:00:00 2001 From: Henning Perl Date: Mon, 14 Aug 2023 11:47:55 +0200 Subject: [PATCH 4/5] chore: consistent naming --- consent/strategy_default.go | 4 +- consent/strategy_default_test.go | 11 +-- consent/strategy_logout_test.go | 2 +- driver/config/provider.go | 10 +- flow/consent_types.go | 16 +-- flow/flow.go | 36 +++---- flow/flow_test.go | 2 +- internal/httpclient/api/openapi.yaml | 7 +- .../docs/AcceptOAuth2LoginRequest.md | 26 ++--- .../model_accept_o_auth2_login_request.go | 36 +++---- internal/kratos/fake_kratos.go | 4 +- internal/kratos/kratos.go | 8 +- .../auth_session-0001.json | 2 +- .../auth_session-0002.json | 2 +- .../auth_session-0003.json | 2 +- .../auth_session-0004.json | 2 +- .../auth_session-0005.json | 2 +- .../auth_session-0006.json | 2 +- .../auth_session-0007.json | 2 +- .../auth_session-0008.json | 2 +- .../auth_session-0009.json | 2 +- .../auth_session-0010.json | 2 +- .../auth_session-0011.json | 2 +- .../auth_session-0012.json | 2 +- .../auth_session-0013.json | 2 +- .../auth_session-0014.json | 2 +- .../auth_session-0015.json | 2 +- .../auth_session-0016.json | 2 +- .../auth_session-0017.json | 8 ++ .../hydra_oauth2_flow/challenge-0001.json | 2 +- .../hydra_oauth2_flow/challenge-0002.json | 2 +- .../hydra_oauth2_flow/challenge-0003.json | 2 +- .../hydra_oauth2_flow/challenge-0004.json | 2 +- .../hydra_oauth2_flow/challenge-0005.json | 2 +- .../hydra_oauth2_flow/challenge-0006.json | 2 +- .../hydra_oauth2_flow/challenge-0007.json | 2 +- .../hydra_oauth2_flow/challenge-0008.json | 2 +- .../hydra_oauth2_flow/challenge-0009.json | 2 +- .../hydra_oauth2_flow/challenge-0010.json | 2 +- .../hydra_oauth2_flow/challenge-0011.json | 2 +- .../hydra_oauth2_flow/challenge-0012.json | 2 +- .../hydra_oauth2_flow/challenge-0013.json | 2 +- .../hydra_oauth2_flow/challenge-0014.json | 2 +- .../hydra_oauth2_flow/challenge-0015.json | 2 +- .../hydra_oauth2_flow/challenge-0016.json | 2 +- .../hydra_oauth2_flow/challenge-0017.json | 79 +++++++++++++++ persistence/sql/migratest/migration_test.go | 4 +- .../20230809122501000001_testdata.sql | 97 +++++++++++++++++++ ...22501000001_add_kratos_session_id.down.sql | 4 +- ...9122501000001_add_kratos_session_id.up.sql | 4 +- persistence/sql/persister_consent.go | 14 +-- persistence/sql/persister_nid_test.go | 6 +- spec/api.json | 4 +- spec/config.json | 4 +- spec/swagger.json | 4 +- 55 files changed, 320 insertions(+), 134 deletions(-) create mode 100644 persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0017.json create mode 100644 persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0017.json create mode 100644 persistence/sql/migratest/testdata/20230809122501000001_testdata.sql diff --git a/consent/strategy_default.go b/consent/strategy_default.go index 6bff9b8072b..084872b60d1 100644 --- a/consent/strategy_default.go +++ b/consent/strategy_default.go @@ -459,7 +459,7 @@ func (s *DefaultStrategy) verifyAuthentication( return nil, fosite.ErrAccessDenied.WithHint("The login session cookie was not found or malformed.") } - loginSession.KratosSessionID = f.KratosSessionID + loginSession.IdentityProviderSessionID = f.IdentityProviderSessionID if err := s.r.ConsentManager().ConfirmLoginSession(ctx, loginSession, sessionID, time.Time(session.AuthenticatedAt), session.Subject, session.Remember); err != nil { return nil, err } @@ -1010,7 +1010,7 @@ func (s *DefaultStrategy) performBackChannelLogoutAndDeleteSession(r *http.Reque } else if err != nil { return err } else { - innerErr := s.r.Kratos().DisableSession(ctx, session.KratosSessionID.String()) + innerErr := s.r.Kratos().DisableSession(ctx, session.IdentityProviderSessionID.String()) if innerErr != nil { s.r.Logger().WithError(innerErr).WithField("sid", sid).Error("Unable to revoke session in ORY Kratos.") } diff --git a/consent/strategy_default_test.go b/consent/strategy_default_test.go index 870c96ffb50..75c7682ded3 100644 --- a/consent/strategy_default_test.go +++ b/consent/strategy_default_test.go @@ -11,21 +11,18 @@ import ( "net/url" "testing" - hydra "github.com/ory/hydra-client-go/v2" - - "github.com/stretchr/testify/require" - - "github.com/ory/fosite/token/jwt" - "github.com/ory/x/urlx" - "github.com/google/uuid" + "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + "github.com/ory/fosite/token/jwt" + hydra "github.com/ory/hydra-client-go/v2" "github.com/ory/hydra/v2/client" . "github.com/ory/hydra/v2/consent" "github.com/ory/hydra/v2/driver" "github.com/ory/hydra/v2/internal/testhelpers" "github.com/ory/x/ioutilx" + "github.com/ory/x/urlx" ) func checkAndAcceptLoginHandler(t *testing.T, apiClient *hydra.APIClient, subject string, cb func(*testing.T, *hydra.OAuth2LoginRequest, error) hydra.AcceptOAuth2LoginRequest) http.HandlerFunc { diff --git a/consent/strategy_logout_test.go b/consent/strategy_logout_test.go index 5f093ccd1eb..7f0af09f080 100644 --- a/consent/strategy_logout_test.go +++ b/consent/strategy_logout_test.go @@ -184,7 +184,7 @@ func TestLogoutFlows(t *testing.T) { checkAndAcceptLoginHandler(t, adminApi, subject, func(t *testing.T, res *hydra.OAuth2LoginRequest, err error) hydra.AcceptOAuth2LoginRequest { require.NoError(t, err) //res.Payload.SessionID - return hydra.AcceptOAuth2LoginRequest{Remember: pointerx.Ptr(true), KratosSessionId: pointerx.Ptr(kratos.FakeSessionID)} + return hydra.AcceptOAuth2LoginRequest{Remember: pointerx.Ptr(true), IdentityProviderSessionId: pointerx.Ptr(kratos.FakeSessionID)} }), checkAndAcceptConsentHandler(t, adminApi, func(t *testing.T, res *hydra.OAuth2ConsentRequest, err error) hydra.AcceptOAuth2ConsentRequest { require.NoError(t, err) diff --git a/driver/config/provider.go b/driver/config/provider.go index 026e2e48f86..7b2f12f905a 100644 --- a/driver/config/provider.go +++ b/driver/config/provider.go @@ -80,7 +80,7 @@ const ( KeyPublicURL = "urls.self.public" KeyAdminURL = "urls.self.admin" KeyIssuerURL = "urls.self.issuer" - KeyKratosAdminURL = "urls.kratos.admin" + KeyIdentityProviderAdminURL = "urls.identity_provider.admin_base_url" KeyAccessTokenStrategy = "strategies.access_token" KeyJWTScopeClaimStrategy = "strategies.jwt.scope_claim" KeyDBIgnoreUnknownTableColumns = "db.ignore_unknown_table_columns" @@ -105,8 +105,10 @@ const ( const DSNMemory = "memory" -var _ hasherx.PBKDF2Configurator = (*DefaultProvider)(nil) -var _ hasherx.BCryptConfigurator = (*DefaultProvider)(nil) +var ( + _ hasherx.PBKDF2Configurator = (*DefaultProvider)(nil) + _ hasherx.BCryptConfigurator = (*DefaultProvider)(nil) +) type DefaultProvider struct { l *logrusx.Logger @@ -395,7 +397,7 @@ func (p *DefaultProvider) IssuerURL(ctx context.Context) *url.URL { } func (p *DefaultProvider) KratosAdminURL(ctx context.Context) (*url.URL, bool) { - u := p.getProvider(ctx).RequestURIF(KeyKratosAdminURL, nil) + u := p.getProvider(ctx).RequestURIF(KeyIdentityProviderAdminURL, nil) return u, u != nil } diff --git a/flow/consent_types.go b/flow/consent_types.go index 0fae36d0ccb..9a2666c7867 100644 --- a/flow/consent_types.go +++ b/flow/consent_types.go @@ -42,12 +42,12 @@ type OAuth2RedirectTo struct { // swagger:ignore type LoginSession struct { - ID string `db:"id"` - NID uuid.UUID `db:"nid"` - AuthenticatedAt sqlxx.NullTime `db:"authenticated_at"` - Subject string `db:"subject"` - KratosSessionID sqlxx.NullString `db:"kratos_session_id"` - Remember bool `db:"remember"` + ID string `db:"id"` + NID uuid.UUID `db:"nid"` + AuthenticatedAt sqlxx.NullTime `db:"authenticated_at"` + Subject string `db:"subject"` + IdentityProviderSessionID sqlxx.NullString `db:"identity_provider_session_id"` + Remember bool `db:"remember"` } func (LoginSession) TableName() string { @@ -293,11 +293,11 @@ type HandledLoginRequest struct { // required: true Subject string `json:"subject"` - // KratosSessionID is the session ID of the end-user that authenticated. + // IdentityProviderSessionID is the session ID of the end-user that authenticated. // If specified, we will use this value to propagate the logout. // // required: false - KratosSessionID string `json:"kratos_session_id,omitempty"` + IdentityProviderSessionID string `json:"identity_provider_session_id,omitempty"` // ForceSubjectIdentifier forces the "pairwise" user ID of the end-user that authenticated. The "pairwise" user ID refers to the // (Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID diff --git a/flow/flow.go b/flow/flow.go index 566948066ca..7e8eeb077c8 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -136,7 +136,9 @@ type Flow struct { // channel logout. Its value can generally be used to associate consecutive login requests by a certain user. SessionID sqlxx.NullString `db:"login_session_id"` - KratosSessionID sqlxx.NullString `db:"kratos_session_id"` + // IdentityProviderSessionID is the session ID of the end-user that authenticated. + // If specified, we will use this value to propagate the logout. + IdentityProviderSessionID sqlxx.NullString `db:"identity_provider_session_id"` LoginVerifier string `db:"login_verifier"` LoginCSRF string `db:"login_csrf"` @@ -293,7 +295,7 @@ func (f *Flow) HandleLoginRequest(h *HandledLoginRequest) error { f.ForceSubjectIdentifier = h.ForceSubjectIdentifier f.LoginError = h.Error - f.KratosSessionID = sqlxx.NullString(h.KratosSessionID) + f.IdentityProviderSessionID = sqlxx.NullString(h.IdentityProviderSessionID) f.LoginRemember = h.Remember f.LoginRememberFor = h.RememberFor f.LoginExtendSessionLifespan = h.ExtendSessionLifespan @@ -307,21 +309,21 @@ func (f *Flow) HandleLoginRequest(h *HandledLoginRequest) error { func (f *Flow) GetHandledLoginRequest() HandledLoginRequest { return HandledLoginRequest{ - ID: f.ID, - Remember: f.LoginRemember, - RememberFor: f.LoginRememberFor, - ExtendSessionLifespan: f.LoginExtendSessionLifespan, - ACR: f.ACR, - AMR: f.AMR, - Subject: f.Subject, - KratosSessionID: f.KratosSessionID.String(), - ForceSubjectIdentifier: f.ForceSubjectIdentifier, - Context: f.Context, - WasHandled: f.LoginWasUsed, - Error: f.LoginError, - LoginRequest: f.GetLoginRequest(), - RequestedAt: f.RequestedAt, - AuthenticatedAt: f.LoginAuthenticatedAt, + ID: f.ID, + Remember: f.LoginRemember, + RememberFor: f.LoginRememberFor, + ExtendSessionLifespan: f.LoginExtendSessionLifespan, + ACR: f.ACR, + AMR: f.AMR, + Subject: f.Subject, + IdentityProviderSessionID: f.IdentityProviderSessionID.String(), + ForceSubjectIdentifier: f.ForceSubjectIdentifier, + Context: f.Context, + WasHandled: f.LoginWasUsed, + Error: f.LoginError, + LoginRequest: f.GetLoginRequest(), + RequestedAt: f.RequestedAt, + AuthenticatedAt: f.LoginAuthenticatedAt, } } diff --git a/flow/flow_test.go b/flow/flow_test.go index 9cfe514ca50..25a832c780e 100644 --- a/flow/flow_test.go +++ b/flow/flow_test.go @@ -42,7 +42,7 @@ func (f *Flow) setHandledLoginRequest(r *HandledLoginRequest) { f.ACR = r.ACR f.AMR = r.AMR f.Subject = r.Subject - f.KratosSessionID = sqlxx.NullString(r.KratosSessionID) + f.IdentityProviderSessionID = sqlxx.NullString(r.IdentityProviderSessionID) f.ForceSubjectIdentifier = r.ForceSubjectIdentifier f.Context = r.Context f.LoginWasUsed = r.WasHandled diff --git a/internal/httpclient/api/openapi.yaml b/internal/httpclient/api/openapi.yaml index db75a789076..6a5d7ab2ec6 100644 --- a/internal/httpclient/api/openapi.yaml +++ b/internal/httpclient/api/openapi.yaml @@ -1989,9 +1989,10 @@ components: \ the proper value, then authentication processes which have id_token_hint\ \ set might fail." type: string - kratos_session_id: - description: "KratosSessionID is the session ID of the end-user that authenticated.\n\ - If specified, we will use this value to propagate the logout." + identity_provider_session_id: + description: "IdentityProviderSessionID is the session ID of the end-user\ + \ that authenticated.\nIf specified, we will use this value to propagate\ + \ the logout." type: string remember: description: "Remember, if set to true, tells ORY Hydra to remember this\ diff --git a/internal/httpclient/docs/AcceptOAuth2LoginRequest.md b/internal/httpclient/docs/AcceptOAuth2LoginRequest.md index 785add0f8ef..e6f6d554546 100644 --- a/internal/httpclient/docs/AcceptOAuth2LoginRequest.md +++ b/internal/httpclient/docs/AcceptOAuth2LoginRequest.md @@ -9,7 +9,7 @@ Name | Type | Description | Notes **Context** | Pointer to **interface{}** | | [optional] **ExtendSessionLifespan** | Pointer to **bool** | Extend OAuth2 authentication session lifespan If set to `true`, the OAuth2 authentication cookie lifespan is extended. This is for example useful if you want the user to be able to use `prompt=none` continuously. This value can only be set to `true` if the user has an authentication, which is the case if the `skip` value is `true`. | [optional] **ForceSubjectIdentifier** | Pointer to **string** | ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the (Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID Connect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client. Please note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the sub claim in the OAuth 2.0 Introspection. Per default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself you can use this field. Please note that setting this field has no effect if `pairwise` is not configured in ORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's configuration). Please also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies that you have to compute this value on every authentication process (probably depending on the client ID or some other unique value). If you fail to compute the proper value, then authentication processes which have id_token_hint set might fail. | [optional] -**KratosSessionId** | Pointer to **string** | KratosSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. | [optional] +**IdentityProviderSessionId** | Pointer to **string** | IdentityProviderSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. | [optional] **Remember** | Pointer to **bool** | Remember, if set to true, tells ORY Hydra to remember this user by telling the user agent (browser) to store a cookie with authentication data. If the same user performs another OAuth 2.0 Authorization Request, he/she will not be asked to log in again. | [optional] **RememberFor** | Pointer to **int64** | RememberFor sets how long the authentication should be remembered for in seconds. If set to `0`, the authorization will be remembered for the duration of the browser session (using a session cookie). | [optional] **Subject** | **string** | Subject is the user ID of the end-user that authenticated. | @@ -168,30 +168,30 @@ SetForceSubjectIdentifier sets ForceSubjectIdentifier field to given value. HasForceSubjectIdentifier returns a boolean if a field has been set. -### GetKratosSessionId +### GetIdentityProviderSessionId -`func (o *AcceptOAuth2LoginRequest) GetKratosSessionId() string` +`func (o *AcceptOAuth2LoginRequest) GetIdentityProviderSessionId() string` -GetKratosSessionId returns the KratosSessionId field if non-nil, zero value otherwise. +GetIdentityProviderSessionId returns the IdentityProviderSessionId field if non-nil, zero value otherwise. -### GetKratosSessionIdOk +### GetIdentityProviderSessionIdOk -`func (o *AcceptOAuth2LoginRequest) GetKratosSessionIdOk() (*string, bool)` +`func (o *AcceptOAuth2LoginRequest) GetIdentityProviderSessionIdOk() (*string, bool)` -GetKratosSessionIdOk returns a tuple with the KratosSessionId field if it's non-nil, zero value otherwise +GetIdentityProviderSessionIdOk returns a tuple with the IdentityProviderSessionId field if it's non-nil, zero value otherwise and a boolean to check if the value has been set. -### SetKratosSessionId +### SetIdentityProviderSessionId -`func (o *AcceptOAuth2LoginRequest) SetKratosSessionId(v string)` +`func (o *AcceptOAuth2LoginRequest) SetIdentityProviderSessionId(v string)` -SetKratosSessionId sets KratosSessionId field to given value. +SetIdentityProviderSessionId sets IdentityProviderSessionId field to given value. -### HasKratosSessionId +### HasIdentityProviderSessionId -`func (o *AcceptOAuth2LoginRequest) HasKratosSessionId() bool` +`func (o *AcceptOAuth2LoginRequest) HasIdentityProviderSessionId() bool` -HasKratosSessionId returns a boolean if a field has been set. +HasIdentityProviderSessionId returns a boolean if a field has been set. ### GetRemember diff --git a/internal/httpclient/model_accept_o_auth2_login_request.go b/internal/httpclient/model_accept_o_auth2_login_request.go index 3d4afaf88f9..85c5355b2d6 100644 --- a/internal/httpclient/model_accept_o_auth2_login_request.go +++ b/internal/httpclient/model_accept_o_auth2_login_request.go @@ -25,8 +25,8 @@ type AcceptOAuth2LoginRequest struct { ExtendSessionLifespan *bool `json:"extend_session_lifespan,omitempty"` // ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the (Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID Connect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client. Please note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the sub claim in the OAuth 2.0 Introspection. Per default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself you can use this field. Please note that setting this field has no effect if `pairwise` is not configured in ORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's configuration). Please also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies that you have to compute this value on every authentication process (probably depending on the client ID or some other unique value). If you fail to compute the proper value, then authentication processes which have id_token_hint set might fail. ForceSubjectIdentifier *string `json:"force_subject_identifier,omitempty"` - // KratosSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. - KratosSessionId *string `json:"kratos_session_id,omitempty"` + // IdentityProviderSessionID is the session ID of the end-user that authenticated. If specified, we will use this value to propagate the logout. + IdentityProviderSessionId *string `json:"identity_provider_session_id,omitempty"` // Remember, if set to true, tells ORY Hydra to remember this user by telling the user agent (browser) to store a cookie with authentication data. If the same user performs another OAuth 2.0 Authorization Request, he/she will not be asked to log in again. Remember *bool `json:"remember,omitempty"` // RememberFor sets how long the authentication should be remembered for in seconds. If set to `0`, the authorization will be remembered for the duration of the browser session (using a session cookie). @@ -214,36 +214,36 @@ func (o *AcceptOAuth2LoginRequest) SetForceSubjectIdentifier(v string) { o.ForceSubjectIdentifier = &v } -// GetKratosSessionId returns the KratosSessionId field value if set, zero value otherwise. -func (o *AcceptOAuth2LoginRequest) GetKratosSessionId() string { - if o == nil || o.KratosSessionId == nil { +// GetIdentityProviderSessionId returns the IdentityProviderSessionId field value if set, zero value otherwise. +func (o *AcceptOAuth2LoginRequest) GetIdentityProviderSessionId() string { + if o == nil || o.IdentityProviderSessionId == nil { var ret string return ret } - return *o.KratosSessionId + return *o.IdentityProviderSessionId } -// GetKratosSessionIdOk returns a tuple with the KratosSessionId field value if set, nil otherwise +// GetIdentityProviderSessionIdOk returns a tuple with the IdentityProviderSessionId field value if set, nil otherwise // and a boolean to check if the value has been set. -func (o *AcceptOAuth2LoginRequest) GetKratosSessionIdOk() (*string, bool) { - if o == nil || o.KratosSessionId == nil { +func (o *AcceptOAuth2LoginRequest) GetIdentityProviderSessionIdOk() (*string, bool) { + if o == nil || o.IdentityProviderSessionId == nil { return nil, false } - return o.KratosSessionId, true + return o.IdentityProviderSessionId, true } -// HasKratosSessionId returns a boolean if a field has been set. -func (o *AcceptOAuth2LoginRequest) HasKratosSessionId() bool { - if o != nil && o.KratosSessionId != nil { +// HasIdentityProviderSessionId returns a boolean if a field has been set. +func (o *AcceptOAuth2LoginRequest) HasIdentityProviderSessionId() bool { + if o != nil && o.IdentityProviderSessionId != nil { return true } return false } -// SetKratosSessionId gets a reference to the given string and assigns it to the KratosSessionId field. -func (o *AcceptOAuth2LoginRequest) SetKratosSessionId(v string) { - o.KratosSessionId = &v +// SetIdentityProviderSessionId gets a reference to the given string and assigns it to the IdentityProviderSessionId field. +func (o *AcceptOAuth2LoginRequest) SetIdentityProviderSessionId(v string) { + o.IdentityProviderSessionId = &v } // GetRemember returns the Remember field value if set, zero value otherwise. @@ -351,8 +351,8 @@ func (o AcceptOAuth2LoginRequest) MarshalJSON() ([]byte, error) { if o.ForceSubjectIdentifier != nil { toSerialize["force_subject_identifier"] = o.ForceSubjectIdentifier } - if o.KratosSessionId != nil { - toSerialize["kratos_session_id"] = o.KratosSessionId + if o.IdentityProviderSessionId != nil { + toSerialize["identity_provider_session_id"] = o.IdentityProviderSessionId } if o.Remember != nil { toSerialize["remember"] = o.Remember diff --git a/internal/kratos/fake_kratos.go b/internal/kratos/fake_kratos.go index a356146e4df..9164b742f58 100644 --- a/internal/kratos/fake_kratos.go +++ b/internal/kratos/fake_kratos.go @@ -22,9 +22,9 @@ func NewFake() *FakeKratos { return &FakeKratos{} } -func (f *FakeKratos) DisableSession(_ context.Context, kratosSessionID string) error { +func (f *FakeKratos) DisableSession(ctx context.Context, identityProviderSessionID string) error { f.DisableSessionWasCalled = true - f.LastDisabledSession = kratosSessionID + f.LastDisabledSession = identityProviderSessionID return nil } diff --git a/internal/kratos/kratos.go b/internal/kratos/kratos.go index d7db5b771c8..1cafc950ded 100644 --- a/internal/kratos/kratos.go +++ b/internal/kratos/kratos.go @@ -25,7 +25,7 @@ type ( Kratos() Client } Client interface { - DisableSession(ctx context.Context, kratosSessionID string) error + DisableSession(ctx context.Context, identityProviderSessionID string) error } Default struct { dependencies @@ -36,7 +36,7 @@ func New(d dependencies) Client { return &Default{dependencies: d} } -func (k *Default) DisableSession(ctx context.Context, kratosSessionID string) (err error) { +func (k *Default) DisableSession(ctx context.Context, identityProviderSessionID string) (err error) { ctx, span := k.Tracer(ctx).Tracer().Start(ctx, "kratos.DisableSession") otelx.End(span, &err) @@ -47,14 +47,14 @@ func (k *Default) DisableSession(ctx context.Context, kratosSessionID string) (e return nil } - if kratosSessionID == "" { + if identityProviderSessionID == "" { span.SetAttributes(attribute.Bool("skipped", true)) span.SetAttributes(attribute.String("reason", "kratos session ID is empty")) return nil } kratos := client.NewAPIClient(k.clientConfiguration(ctx, adminURL)) - _, err = kratos.IdentityApi.DisableSession(ctx, kratosSessionID).Execute() + _, err = kratos.IdentityApi.DisableSession(ctx, identityProviderSessionID).Execute() return err diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0001.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0001.json index 9ed28857755..eb6ec18517e 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0001.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0001.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0001", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0002.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0002.json index aeac476a9ab..130b019ccff 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0002.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0002.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0002", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0003.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0003.json index 76ff6e432b5..c6a2c35901f 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0003.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0003.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0003", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0004.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0004.json index a8688ae9c31..5da2bd40758 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0004.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0004.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0004", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0005.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0005.json index 2e21492c6d3..0b3c6f8f4d7 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0005.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0005.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0005", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0006.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0006.json index 1a6e76f87da..aa63cb104bb 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0006.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0006.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0006", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0007.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0007.json index 619fcc9b034..07b96a3d592 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0007.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0007.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0007", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0008.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0008.json index b6ef3fc1632..2e781eeda86 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0008.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0008.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0008", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0009.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0009.json index 7cb33bb7c7d..204d0fffaf2 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0009.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0009.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0009", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0010.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0010.json index 93539884214..02608ae43f4 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0010.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0010.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0010", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0011.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0011.json index f0ee5752657..33d7187e6e2 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0011.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0011.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0011", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0012.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0012.json index bc7c53ecc7a..5269cc061b2 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0012.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0012.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0012", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0013.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0013.json index 7b9795b58ce..b4a2ee9f13d 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0013.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0013.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0013", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0014.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0014.json index d25982c1b71..a9bb155e485 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0014.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0014.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0014", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0015.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0015.json index 74f67ac3124..c88a473e7cc 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0015.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0015.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0015", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": false } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0016.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0016.json index 4ee258ff5d4..e2d69a9796b 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0016.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0016.json @@ -3,6 +3,6 @@ "NID": "00000000-0000-0000-0000-000000000000", "AuthenticatedAt": null, "Subject": "subject-0016", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "Remember": true } diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0017.json b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0017.json new file mode 100644 index 00000000000..aea0119e354 --- /dev/null +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_authentication_session/auth_session-0017.json @@ -0,0 +1,8 @@ +{ + "ID": "auth_session-0017", + "NID": "00000000-0000-0000-0000-000000000000", + "AuthenticatedAt": null, + "Subject": "subject-0017", + "IdentityProviderSessionID": "identity_provider_session_id-0017", + "Remember": true +} diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0001.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0001.json index a42275d0e7e..c790dc021e7 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0001.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0001.json @@ -14,7 +14,7 @@ "ClientID": "", "RequestURL": "http://request/0001", "SessionID": "", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0001", "LoginCSRF": "csrf-0001", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0002.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0002.json index 15477fa8d96..1917ef94c5f 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0002.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0002.json @@ -14,7 +14,7 @@ "ClientID": "", "RequestURL": "http://request/0002", "SessionID": "", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0002", "LoginCSRF": "csrf-0002", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0003.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0003.json index ff40b309384..39ca512a15a 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0003.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0003.json @@ -14,7 +14,7 @@ "ClientID": "", "RequestURL": "http://request/0003", "SessionID": "auth_session-0003", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0003", "LoginCSRF": "csrf-0003", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0004.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0004.json index 53fd97cd38c..b3dc1b958e0 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0004.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0004.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0004", "SessionID": "auth_session-0004", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0004", "LoginCSRF": "csrf-0004", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0005.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0005.json index f30f13352bb..2a642cae89b 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0005.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0005.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0005", "SessionID": "auth_session-0005", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0005", "LoginCSRF": "csrf-0005", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0006.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0006.json index b17f4f62df6..89bfd52e6e3 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0006.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0006.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0006", "SessionID": "auth_session-0006", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0006", "LoginCSRF": "csrf-0006", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0007.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0007.json index a6428804cb3..2c84d09ad47 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0007.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0007.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0007", "SessionID": "auth_session-0007", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0007", "LoginCSRF": "csrf-0007", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0008.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0008.json index 595ecbe13ee..d2e7d2f2fdd 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0008.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0008.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0008", "SessionID": "auth_session-0008", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0008", "LoginCSRF": "csrf-0008", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0009.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0009.json index 4c56c49cc06..6d3e70d5e37 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0009.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0009.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0009", "SessionID": "auth_session-0009", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0009", "LoginCSRF": "csrf-0009", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0010.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0010.json index 82592b03db4..6b8f3cf7a10 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0010.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0010.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0010", "SessionID": "auth_session-0010", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0010", "LoginCSRF": "csrf-0010", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0011.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0011.json index 7d68c1cacde..5b11c1941d1 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0011.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0011.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0011", "SessionID": "auth_session-0011", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0011", "LoginCSRF": "csrf-0011", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0012.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0012.json index eb93e192387..b648871cda5 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0012.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0012.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0012", "SessionID": "auth_session-0012", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0012", "LoginCSRF": "csrf-0012", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0013.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0013.json index 0238bb794f7..1f28bb67647 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0013.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0013.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0013", "SessionID": "auth_session-0013", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0013", "LoginCSRF": "csrf-0013", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0014.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0014.json index d3c832a270c..3e2dd7bb444 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0014.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0014.json @@ -16,7 +16,7 @@ "ClientID": "", "RequestURL": "http://request/0014", "SessionID": "auth_session-0014", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0014", "LoginCSRF": "csrf-0014", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0015.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0015.json index b7aedcb245a..5723154839a 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0015.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0015.json @@ -18,7 +18,7 @@ "ClientID": "", "RequestURL": "http://request/0015", "SessionID": "auth_session-0015", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0015", "LoginCSRF": "csrf-0015", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0016.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0016.json index 09a9125013d..e653059fe46 100644 --- a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0016.json +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0016.json @@ -18,7 +18,7 @@ "ClientID": "", "RequestURL": "http://request/0016", "SessionID": "auth_session-0016", - "KratosSessionID": "", + "IdentityProviderSessionID": "", "LoginVerifier": "verifier-0016", "LoginCSRF": "csrf-0016", "LoginInitializedAt": null, diff --git a/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0017.json b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0017.json new file mode 100644 index 00000000000..fd65dab7164 --- /dev/null +++ b/persistence/sql/migratest/fixtures/hydra_oauth2_flow/challenge-0017.json @@ -0,0 +1,79 @@ +{ + "ID": "challenge-0017", + "NID": "00000000-0000-0000-0000-000000000000", + "RequestedScope": [ + "requested_scope-0016_1", + "requested_scope-0016_2" + ], + "RequestedAudience": [ + "requested_audience-0016_1", + "requested_audience-0016_2" + ], + "LoginSkip": true, + "Subject": "subject-0017", + "OpenIDConnectContext": { + "display": "display-0017" + }, + "Client": null, + "ClientID": "", + "RequestURL": "http://request/0017", + "SessionID": "auth_session-0017", + "IdentityProviderSessionID": "identity_provider_session_id-0017", + "LoginVerifier": "verifier-0017", + "LoginCSRF": "csrf-0017", + "LoginInitializedAt": null, + "RequestedAt": "0001-01-01T00:00:00Z", + "State": 128, + "LoginRemember": true, + "LoginRememberFor": 15, + "LoginExtendSessionLifespan": true, + "ACR": "acr-0017", + "AMR": [ + "amr-0017-1", + "amr-0017-2" + ], + "ForceSubjectIdentifier": "force_subject_id-0017", + "Context": { + "context": "0017" + }, + "LoginWasUsed": true, + "LoginError": { + "error": "", + "error_description": "", + "error_hint": "", + "status_code": 0, + "error_debug": "", + "valid": false + }, + "LoginAuthenticatedAt": null, + "ConsentChallengeID": "challenge-0017", + "ConsentSkip": true, + "ConsentVerifier": "verifier-0017", + "ConsentCSRF": "csrf-0017", + "GrantedScope": [ + "granted_scope-0016_1", + "granted_scope-0016_2" + ], + "GrantedAudience": [ + "granted_audience-0016_1", + "granted_audience-0016_2" + ], + "ConsentRemember": true, + "ConsentRememberFor": 15, + "ConsentHandledAt": null, + "ConsentWasHandled": true, + "ConsentError": { + "error": "", + "error_description": "", + "error_hint": "", + "status_code": 0, + "error_debug": "", + "valid": false + }, + "SessionIDToken": { + "session_id_token-0017": "0017" + }, + "SessionAccessToken": { + "session_access_token-0017": "0017" + } +} diff --git a/persistence/sql/migratest/migration_test.go b/persistence/sql/migratest/migration_test.go index e08834a9b4a..02047008c1f 100644 --- a/persistence/sql/migratest/migration_test.go +++ b/persistence/sql/migratest/migration_test.go @@ -132,7 +132,7 @@ func TestMigrations(t *testing.T) { flows := []flow.Flow{} require.NoError(t, c.All(&flows)) - require.Equal(t, 16, len(flows)) + require.Equal(t, 17, len(flows)) t.Run("case=hydra_oauth2_flow", func(t *testing.T) { for _, f := range flows { @@ -144,7 +144,7 @@ func TestMigrations(t *testing.T) { t.Run("case=hydra_oauth2_authentication_session", func(t *testing.T) { ss := []flow.LoginSession{} c.All(&ss) - require.Equal(t, 16, len(ss)) + require.Equal(t, 17, len(ss)) for _, s := range ss { testhelpersuuid.AssertUUID(t, &s.NID) diff --git a/persistence/sql/migratest/testdata/20230809122501000001_testdata.sql b/persistence/sql/migratest/testdata/20230809122501000001_testdata.sql new file mode 100644 index 00000000000..472700be3db --- /dev/null +++ b/persistence/sql/migratest/testdata/20230809122501000001_testdata.sql @@ -0,0 +1,97 @@ +INSERT INTO hydra_oauth2_authentication_session ( + id, + nid, + authenticated_at, + subject, + remember, + identity_provider_session_id +) VALUES ( + 'auth_session-0017', + (SELECT id FROM networks LIMIT 1), + CURRENT_TIMESTAMP, + 'subject-0017', + true, + 'identity_provider_session_id-0017' +); + +INSERT INTO hydra_oauth2_flow ( + login_challenge, + nid, + requested_scope, + login_verifier, + login_csrf, + subject, + request_url, + login_skip, + client_id, + requested_at, + oidc_context, + login_session_id, + requested_at_audience, + login_initialized_at, + state, + login_remember, + login_remember_for, + login_error, + acr, + login_authenticated_at, + login_was_used, + forced_subject_identifier, + context, + amr, + consent_challenge_id, + consent_verifier, + consent_skip, + consent_csrf, + granted_scope, + consent_remember, + consent_remember_for, + consent_error, + session_access_token, + session_id_token, + consent_was_used, + granted_at_audience, + consent_handled_at, + login_extend_session_lifespan, + identity_provider_session_id +) VALUES ( + 'challenge-0017', + (SELECT id FROM networks LIMIT 1), + '["requested_scope-0016_1","requested_scope-0016_2"]', + 'verifier-0017', + 'csrf-0017', + 'subject-0017', + 'http://request/0017', + true, + 'client-21', + CURRENT_TIMESTAMP, + '{"display": "display-0017"}', + 'auth_session-0017', + '["requested_audience-0016_1","requested_audience-0016_2"]', + CURRENT_TIMESTAMP, + 128, + true, + 15, + '{}', + 'acr-0017', + CURRENT_TIMESTAMP, + true, + 'force_subject_id-0017', + '{"context": "0017"}', + '["amr-0017-1","amr-0017-2"]', + 'challenge-0017', + 'verifier-0017', + true, + 'csrf-0017', + '["granted_scope-0016_1","granted_scope-0016_2"]', + true, + 15, + '{}', + '{"session_access_token-0017": "0017"}', + '{"session_id_token-0017": "0017"}', + true, + '["granted_audience-0016_1","granted_audience-0016_2"]', + CURRENT_TIMESTAMP, + true, + 'identity_provider_session_id-0017' +); diff --git a/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.down.sql b/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.down.sql index 84b7cfe9b41..b5ab0899249 100644 --- a/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.down.sql +++ b/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.down.sql @@ -1,2 +1,2 @@ -ALTER TABLE hydra_oauth2_flow DROP COLUMN kratos_session_id; -ALTER TABLE hydra_oauth2_authentication_session DROP COLUMN kratos_session_id; \ No newline at end of file +ALTER TABLE hydra_oauth2_flow DROP COLUMN identity_provider_session_id; +ALTER TABLE hydra_oauth2_authentication_session DROP COLUMN identity_provider_session_id; \ No newline at end of file diff --git a/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.up.sql b/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.up.sql index 11ecf8165f0..1d39c457105 100644 --- a/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.up.sql +++ b/persistence/sql/migrations/20230809122501000001_add_kratos_session_id.up.sql @@ -1,2 +1,2 @@ -ALTER TABLE hydra_oauth2_flow ADD COLUMN kratos_session_id VARCHAR(40); -ALTER TABLE hydra_oauth2_authentication_session ADD COLUMN kratos_session_id VARCHAR(40); \ No newline at end of file +ALTER TABLE hydra_oauth2_flow ADD COLUMN identity_provider_session_id VARCHAR(40); +ALTER TABLE hydra_oauth2_authentication_session ADD COLUMN identity_provider_session_id VARCHAR(40); \ No newline at end of file diff --git a/persistence/sql/persister_consent.go b/persistence/sql/persister_consent.go index ced61f3c0e6..40858a03bdc 100644 --- a/persistence/sql/persister_consent.go +++ b/persistence/sql/persister_consent.go @@ -422,19 +422,19 @@ func (p *Persister) ConfirmLoginSession(ctx context.Context, session *flow.Login return p.CreateWithNetwork(ctx, session) } - var kratosSessionID string + var IdentityProviderSessionID string if session != nil { - kratosSessionID = session.KratosSessionID.String() + IdentityProviderSessionID = session.IdentityProviderSessionID.String() } // In some unit tests, we still confirm the login session without data from the cookie. We can remove this case // once all tests are fixed. n, err := p.Connection(ctx).Where("id = ? AND nid = ?", id, p.NetworkID(ctx)).UpdateQuery(&flow.LoginSession{ - AuthenticatedAt: sqlxx.NullTime(authenticatedAt), - Subject: subject, - Remember: remember, - KratosSessionID: sqlxx.NullString(kratosSessionID), - }, "authenticated_at", "subject", "remember", "kratos_session_id") + AuthenticatedAt: sqlxx.NullTime(authenticatedAt), + Subject: subject, + Remember: remember, + IdentityProviderSessionID: sqlxx.NullString(IdentityProviderSessionID), + }, "authenticated_at", "subject", "remember", "identity_provider_session_id") if err != nil { return sqlcon.HandleError(err) } diff --git a/persistence/sql/persister_nid_test.go b/persistence/sql/persister_nid_test.go index b60ec326874..807656aa2d4 100644 --- a/persistence/sql/persister_nid_test.go +++ b/persistence/sql/persister_nid_test.go @@ -635,9 +635,9 @@ func (s *PersisterTestSuite) TestDeleteLoginSession() { for k, r := range s.registries { t.Run(k, func(t *testing.T) { ls := flow.LoginSession{ - ID: uuid.Must(uuid.NewV4()).String(), - Remember: true, - KratosSessionID: sqlxx.NullString(uuid.Must(uuid.NewV4()).String()), + ID: uuid.Must(uuid.NewV4()).String(), + Remember: true, + IdentityProviderSessionID: sqlxx.NullString(uuid.Must(uuid.NewV4()).String()), } persistLoginSession(s.t1, t, r.Persister(), &ls) diff --git a/spec/api.json b/spec/api.json index 67f4d6e1346..1e6b8cd225d 100644 --- a/spec/api.json +++ b/spec/api.json @@ -207,8 +207,8 @@ "description": "ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the\n(Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID\nConnect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client.\n\nPlease note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the\nsub claim in the OAuth 2.0 Introspection.\n\nPer default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself\nyou can use this field. Please note that setting this field has no effect if `pairwise` is not configured in\nORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's\nconfiguration).\n\nPlease also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies\nthat you have to compute this value on every authentication process (probably depending on the client ID or some\nother unique value).\n\nIf you fail to compute the proper value, then authentication processes which have id_token_hint set might fail.", "type": "string" }, - "kratos_session_id": { - "description": "KratosSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", + "identity_provider_session_id": { + "description": "IdentityProviderSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", "type": "string" }, "remember": { diff --git a/spec/config.json b/spec/config.json index a848b8cffbb..dc96a1f56cd 100644 --- a/spec/config.json +++ b/spec/config.json @@ -761,11 +761,11 @@ "/ui" ] }, - "kratos": { + "identity_provider": { "type": "object", "additionalProperties": false, "properties": { - "admin": { + "admin_base_url": { "type": "string", "title": "The admin URL of the ORY Kratos instance.", "description": "If set, ORY Hydra will use this URL to log out the user in addition to removing the Hydra session.", diff --git a/spec/swagger.json b/spec/swagger.json index ad2926d09f5..9fda613b50e 100755 --- a/spec/swagger.json +++ b/spec/swagger.json @@ -2237,8 +2237,8 @@ "description": "ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the\n(Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID\nConnect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client.\n\nPlease note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the\nsub claim in the OAuth 2.0 Introspection.\n\nPer default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself\nyou can use this field. Please note that setting this field has no effect if `pairwise` is not configured in\nORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's\nconfiguration).\n\nPlease also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies\nthat you have to compute this value on every authentication process (probably depending on the client ID or some\nother unique value).\n\nIf you fail to compute the proper value, then authentication processes which have id_token_hint set might fail.", "type": "string" }, - "kratos_session_id": { - "description": "KratosSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", + "identity_provider_session_id": { + "description": "IdentityProviderSessionID is the session ID of the end-user that authenticated.\nIf specified, we will use this value to propagate the logout.", "type": "string" }, "remember": { From 4f63d4f8b3a837469a39b04c8da780fe216eee14 Mon Sep 17 00:00:00 2001 From: Henning Perl Date: Mon, 14 Aug 2023 12:02:11 +0200 Subject: [PATCH 5/5] fix: cleanup persister --- consent/strategy_logout_test.go | 5 ++++- persistence/sql/persister_consent.go | 14 ++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/consent/strategy_logout_test.go b/consent/strategy_logout_test.go index 7f0af09f080..82005931961 100644 --- a/consent/strategy_logout_test.go +++ b/consent/strategy_logout_test.go @@ -184,7 +184,10 @@ func TestLogoutFlows(t *testing.T) { checkAndAcceptLoginHandler(t, adminApi, subject, func(t *testing.T, res *hydra.OAuth2LoginRequest, err error) hydra.AcceptOAuth2LoginRequest { require.NoError(t, err) //res.Payload.SessionID - return hydra.AcceptOAuth2LoginRequest{Remember: pointerx.Ptr(true), IdentityProviderSessionId: pointerx.Ptr(kratos.FakeSessionID)} + return hydra.AcceptOAuth2LoginRequest{ + Remember: pointerx.Ptr(true), + IdentityProviderSessionId: pointerx.Ptr(kratos.FakeSessionID), + } }), checkAndAcceptConsentHandler(t, adminApi, func(t *testing.T, res *hydra.OAuth2ConsentRequest, err error) hydra.AcceptOAuth2ConsentRequest { require.NoError(t, err) diff --git a/persistence/sql/persister_consent.go b/persistence/sql/persister_consent.go index 40858a03bdc..e92be0fff01 100644 --- a/persistence/sql/persister_consent.go +++ b/persistence/sql/persister_consent.go @@ -422,19 +422,13 @@ func (p *Persister) ConfirmLoginSession(ctx context.Context, session *flow.Login return p.CreateWithNetwork(ctx, session) } - var IdentityProviderSessionID string - if session != nil { - IdentityProviderSessionID = session.IdentityProviderSessionID.String() - } - // In some unit tests, we still confirm the login session without data from the cookie. We can remove this case // once all tests are fixed. n, err := p.Connection(ctx).Where("id = ? AND nid = ?", id, p.NetworkID(ctx)).UpdateQuery(&flow.LoginSession{ - AuthenticatedAt: sqlxx.NullTime(authenticatedAt), - Subject: subject, - Remember: remember, - IdentityProviderSessionID: sqlxx.NullString(IdentityProviderSessionID), - }, "authenticated_at", "subject", "remember", "identity_provider_session_id") + AuthenticatedAt: sqlxx.NullTime(authenticatedAt), + Subject: subject, + Remember: remember, + }, "authenticated_at", "subject", "remember") if err != nil { return sqlcon.HandleError(err) }