Release v2.8.0
Stacks on #59 (
feature/logout-and-persistent-tenant-switch). Merge #59 first — until then this PR's diff includes #59's commits. The link endpoint reuses theIngressExtensions.cs/WellKnownPaths.cschanges from #59.
Adds the AuthProxy half of the "add a credential" proof-of-control flow for Cratis/Studio#862: a session-preserving link challenge that authenticates a second identity-provider login for an already signed-in user and hands the freshly authenticated subject to the application — without replacing the primary session.
Added
GET /.cratis/link/{scheme}— a session-preserving credential-linking challenge. It authenticates the requested provider for an already signed-in user but, on the provider callback, captures the authenticatedsubjectand posts it to the application instead of signing the new identity in, so the user's primary session is preserved. The one-time link token and a same-site-onlyreturnUrltravel through the flow. (Cratis/Studio#862)Cratis:AuthProxy:Link:ExchangeUrlconfiguration — the application back-channel endpoint AuthProxy posts{ subject, identityProvider }to (with the link token as the bearer credential), the link counterpart ofCratis:AuthProxy:Invite:ExchangeUrl. (Cratis/Studio#862)
Security
- The link challenge requires an authenticated session (anonymous →
401), validates the provider scheme (unknown →404) and requires a one-time token (missing →400).returnUrlis constrained to a same-site relative path so the endpoint can never be turned into an open redirect. The subject is delivered to the application server-to-server from a real provider authentication — never trusted from client input. (Cratis/Studio#862)
Notes for review
- Not an iframe. The design in the issue calls for an iframe, but provider consent pages send
X-Frame-Options: DENYand AuthProxy cookies areSameSite=Lax, so the flow is a popup / top-level redirect, as agreed in the issue's posted design. - Session preservation is achieved by short-circuiting
OnTicketReceivedwithcontext.HandleResponse()before theRemoteAuthenticationHandlersigns the ticket into the cookie scheme (the "capturesub/issand short-circuit" option from the design), rather than a throwaway sign-in scheme. - Same-account limitation (assumption): the challenge does not force
prompt=select_account, so a provider with an active SSO session may silently return the same account. Left out because prompt handling differs across OIDC/OAuth and GitHub has no standard equivalent; flagging for review — it can be added if linking a different account of the same provider must be guaranteed.
🤖 Generated with Claude Code