Skip to content

Added back channel logout endpoint without context#4704

Open
shepilov wants to merge 7 commits intomasterfrom
feat/backchannel-logout-without-context
Open

Added back channel logout endpoint without context#4704
shepilov wants to merge 7 commits intomasterfrom
feat/backchannel-logout-without-context

Conversation

@shepilov
Copy link
Contributor

The previous design had three practical problems:

  • The provider had to know stack’s internal OIDC context name to call back channel logout.
  • When sid was available, stack could still end up logging out more than the current OIDC session

With this PR:

  • Cozy now supports POST /oidc/logout in addition to the existing POST /oidc/:context/logout
  • context is resolved server-side from the logout token and existing sid bindings
  • local browser sessions are bound to OIDC sid
  • OIDC-derived OAuth clients are also bound to OIDC sid
  • backchannel logout can revoke both bound browser sessions and bound OAuth clients
  • the existing contextful endpoint remains supported

@shepilov shepilov requested a review from a team as a code owner March 20, 2026 16:56
@shepilov shepilov force-pushed the feat/backchannel-logout-without-context branch 4 times, most recently from 8f9301e to 1200bcf Compare March 23, 2026 19:16
}
}

func combineLogoutContextCandidates(contextsBySID, contextsByIssuerAudience []string) []string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming of these parameters is confusing as I expect to find maps but they're slices.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What name do you propose for the list of contexts that were found by sid ?

web/oidc/oidc.go Outdated
var contextsBySID []string
var err error
if sid != "" {
contextsBySID, err = session.FindOIDCProviderKeysBySID(sid)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confusing variable name. I expect it to be a map while it's a slice.

web/oidc/oidc.go Outdated
// if there is no session, try to resolve it by OIDC configuration in logout token
case 0:
{
contextsByIssuerAudience := findOIDCContextsByIssuerAudience(iss, aud)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confusing variable name. I expect it to be a map while it's a slice.

func Logout(c echo.Context) error {
contextName := c.Param("context")
conf, err := getGenericConfig(contextName)
return handleLogout(c, c.Param("context"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why put the implementation in a separate function since it's used only here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially, I was going to move it to a separate package, but it's just a small isolation of the web layer from logic/service. But maybe it doesnt make sense now

return &oidcConfig, nil
}
// OIDCConfiguration represents the OpenID Connect configuration from the well-known endpoint.
type OIDCConfiguration = oidcprovider.Metadata
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the alias? It would be easier to follow if we used oidcprovider.Metadata directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactoring artifacts

}

s := &Session{}
err = couchdb.GetDoc(inst, consts.Sessions, ref.SessionID, s)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use Get(inst, ref.SessionID) here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because Get(inst, ref.SessionID) it's not just document fetch, it's doing a lot of things, and for example, we might refresh LastSeen on a session we are about to delete

@shepilov shepilov force-pushed the feat/backchannel-logout-without-context branch from 1200bcf to 3005b31 Compare March 24, 2026 11:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants