Add single/multi identity strategy to OIDC providers
OIDCProviders and OIDCMixin accept strategy='single-identity' (default) or 'multi-identity'. Single-identity evicts other providers' identities and tokens after a successful login so the session holds exactly one user, matching Spring Security's last-login-wins behavior. Ephemeral flow keys are preserved so in-flight logins can still complete.
This commit is contained in:
5 files changed
+224
-14
No files matched your search
@@ -86,19 +86,41 @@ async def who(ctx: HttpContext):
|
||||
await ctx.send_str(200, ', '.join(users))
|
||||
```
|
||||
|
||||
Each provider's session state is namespaced as `oidc:{provider}:...`, so a user
|
||||
can be logged into several providers at once. Logging out of one provider only
|
||||
removes that provider's state and keeps the shared session alive while another
|
||||
provider is still logged in. Make sure each config's `redirect_uri` points at
|
||||
that provider's derived callback path.
|
||||
Each provider's session state is namespaced as `oidc:{provider}:...`. Make sure
|
||||
each config's `redirect_uri` points at that provider's derived callback path.
|
||||
|
||||
### Identity strategy
|
||||
|
||||
`strategy` controls how many identities may coexist in the shared session:
|
||||
|
||||
- `'single-identity'` (default): completing a login evicts every other
|
||||
provider's identity and tokens, so the session holds exactly one user — last
|
||||
login wins, like Spring Security. After a GitHub login, `get_user(ctx,
|
||||
'google')` returns `None` and `require_auth('google')` redirects to the Google
|
||||
login.
|
||||
- `'multi-identity'`: each provider stays logged in independently. Use it for
|
||||
linked accounts, aggregating several provider APIs, or step-up flows. Logging
|
||||
out of one provider keeps the shared session alive while another provider is
|
||||
still logged in.
|
||||
|
||||
```python
|
||||
oidc = OIDCProviders([google_config, github_config], session=session,
|
||||
strategy='multi-identity')
|
||||
```
|
||||
|
||||
Ephemeral flow keys (`state`, `nonce`, `code_verifier`) are never evicted, so
|
||||
logins already in flight can still complete; under `'single-identity'` the last
|
||||
callback to finish wins. Under either strategy, `get_users(ctx)` only reports
|
||||
providers actually present in the session.
|
||||
|
||||
The composable alternative is to create one `OIDCMixin` per provider, pointing
|
||||
each at distinct `login_path`/`callback_path`/`logout_path` values and sharing
|
||||
the same `SessionMixin`:
|
||||
the same `SessionMixin`. The same `strategy` keyword is accepted and defaults to
|
||||
`'single-identity'`:
|
||||
|
||||
```python
|
||||
google = OIDCMixin(google_config, session=session)
|
||||
github = OIDCMixin(github_config, session=session)
|
||||
github = OIDCMixin(github_config, session=session, strategy='multi-identity')
|
||||
app = KayaApp(mixins=[session, google, github])
|
||||
```
|
||||
|
||||
@@ -117,6 +139,7 @@ app = KayaApp(mixins=[session, google, github])
|
||||
- Refresh token support
|
||||
- RP-initiated logout (when provider advertises `end_session_endpoint`)
|
||||
- Multiple providers in one app via `OIDCProviders` (or several `OIDCMixin` instances)
|
||||
- `single-identity` (default) or `multi-identity` session strategy
|
||||
- Composable with any other `KayaMixin` (RSGI, MCP, etc.)
|
||||
|
||||
## Security notes
|
||||
|
||||
Reference in new issue
Block a user