You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
DBSC: full support for multiple DBSC schemes, including testing and validation #69682
The experimental DBSC implementation (Microsoft.AspNetCore.Authentication.DeviceBoundSessions) was designed and tested around a single DBSC scheme wrapping a single source cookie scheme. AddDeviceBoundSession is callable multiple times, but multi-scheme behavior was never specified, implemented end to end, or validated. This issue tracks full support for multiple DBSC schemes, including design, implementation, testing, and validation, as a requirement for any reintroduction of DBSC.
Related to #66478 (DBSC tracking), #68117 (API proposal), #68520 (scheme-convention alignment), #69619 (derived cookies should inherit the source DataProtectionProvider), and #67794 (shared ITicketStore). The implementation was removed from .NET 11 by #69462, so this tracks a requirement for the reintroduction rather than a servicing change. Code links refer to the last main commit before the removal, b3d5795c6f.
Problem: Data Protection isolation is only partially scheme-scoped
DBSC protects data in two places, and they behave differently with several schemes.
A challenge minted for scheme A unprotects successfully on scheme B. The only binding is the principal claim UID (and the session id for refresh), not the scheme. Registration and refresh challenges are separated from each other by purpose, but not between schemes.
DeviceBoundSessionChallengeProtector is registered once as a singleton (DeviceBoundSessionExtensions.AddDeviceBoundSessionCore) and uses the application-default IDataProtectionProvider. It cannot use a different provider per DBSC scheme.
DeviceBoundSessionHandler also constructs its own DeviceBoundSessionChallengeProtector instance, while DeviceBoundSessionRegistrationHeader resolves the DI singleton to mint the registration challenge. The two only agree today because both use the default provider.
PostConfigureCookieAuthenticationOptions.cs (core cookies): shows the scheme-keyed purpose that DBSC cookies already get.
Recommended direction: make challenge protection per DBSC scheme and rooted in the source scheme's effective DataProtectionProvider, with the DBSC scheme name in the purpose chain.
The handler already has Options.RegistrationSourceScheme and an IOptionsMonitor<CookieAuthenticationOptions>, and the registration header already receives the resolved DBSC scheme, so one per-scheme protector (for example from a factory or cache keyed by scheme) can serve both. Changing the purposes invalidates in-flight challenges, which is acceptable because the package is experimental.
Other multi-scheme areas to specify and validate
Data Protection is not the only area. The following also need an explicit design and tests:
Endpoint path collisions.RegistrationPath and RefreshPath default to the same values (/.well-known/dbsc/registration and /refresh) for every DBSC scheme. HandleRequestAsync matches on method and path only, so with default paths the first handler registered answers every request, and registration or refresh runs against the wrong source scheme. Options validation only checks that registration and refresh differ within one scheme. Decide between per-scheme paths, a distinguishing component, or failing fast on a cross-scheme collision.
Shared state in DeviceBoundSessionSourceSchemes. The scheme maps are keyed by source scheme. Define and test behavior when the same source scheme is registered twice or when derived names collide, and fail with a clear error.
Registration exchange guard.DeviceBoundSessionCookieEvents.RegistrationExchangeItemKey is a single HttpContext.Items key. Confirm it cannot suppress sign-out handling for a different scheme within one request.
Documentation. Document the supported multi-scheme topologies and their limits, including Data Protection behavior and path configuration.
Acceptance criteria
A registration challenge issued for DBSC scheme A is rejected by scheme B, even when both schemes share the same DataProtectionProvider and the same principal.
A refresh challenge issued for scheme A is rejected by scheme B, even with the same principal and session id.
Challenges use the effective DataProtectionProvider of their own source scheme. A challenge minted under a dedicated provider cannot be validated under the application-default provider, and the reverse also fails.
Challenge minting (registration header) and validation (handler) resolve the same per-scheme protector.
Source, refresh, and session cookies of all schemes remain pairwise non-interchangeable (extends DerivedCookieSchemes_RemainDataProtected_AndSchemeKeyed).
Two DBSC schemes with the default paths either work correctly or fail at startup with a clear message. Requests are never handled by the wrong scheme.
Registration, refresh, session cookie issuance, and sign-out work independently for two DBSC schemes within one app, each with its own source scheme and settings.
Tests use the real AddCookie and AddDeviceBoundSession registration pipeline, not only direct PostConfigure calls, so options ordering is covered. They cover at least two schemes, with both shared and distinct providers.
An end-to-end validation with two schemes is documented, using the DbscDebugServer sample or equivalent, to confirm the browser flow.
Summary
The experimental DBSC implementation (
Microsoft.AspNetCore.Authentication.DeviceBoundSessions) was designed and tested around a single DBSC scheme wrapping a single source cookie scheme.AddDeviceBoundSessionis callable multiple times, but multi-scheme behavior was never specified, implemented end to end, or validated. This issue tracks full support for multiple DBSC schemes, including design, implementation, testing, and validation, as a requirement for any reintroduction of DBSC.Related to #66478 (DBSC tracking), #68117 (API proposal), #68520 (scheme-convention alignment), #69619 (derived cookies should inherit the source
DataProtectionProvider), and #67794 (sharedITicketStore). The implementation was removed from .NET 11 by #69462, so this tracks a requirement for the reintroduction rather than a servicing change. Code links refer to the lastmaincommit before the removal,b3d5795c6f.Problem: Data Protection isolation is only partially scheme-scoped
DBSC protects data in two places, and they behave differently with several schemes.
{source}.Dbsc.Refresh)CookieAuthenticationMiddleware,{derivedScheme},v2{source}.Dbsc.Session)DeviceBoundSessionChallengeProtector…Challenge.Registration.v1DeviceBoundSessionChallengeProtector…Challenge.Refresh.v1Consequences with two or more DBSC schemes:
DeviceBoundSessionChallengeProtectoris registered once as a singleton (DeviceBoundSessionExtensions.AddDeviceBoundSessionCore) and uses the application-defaultIDataProtectionProvider. It cannot use a different provider per DBSC scheme.DeviceBoundSessionHandleralso constructs its ownDeviceBoundSessionChallengeProtectorinstance, whileDeviceBoundSessionRegistrationHeaderresolves the DI singleton to mint the registration challenge. The two only agree today because both use the default provider.Affected code:
DeviceBoundSessionChallengeProtector.cs(constructor): fixed purposes, no scheme.DeviceBoundSessionHandler.cs(constructor): creates its own challenge protector from the default provider.DeviceBoundSessionRegistrationHeader.cs: resolves the singleton challenge protector.DeviceBoundSessionExtensions.cs(AddDeviceBoundSessionCore):TryAddSingleton<DeviceBoundSessionChallengeProtector>().PostConfigureCookieAuthenticationOptions.cs(core cookies): shows the scheme-keyed purpose that DBSC cookies already get.Recommended direction: make challenge protection per DBSC scheme and rooted in the source scheme's effective
DataProtectionProvider, with the DBSC scheme name in the purpose chain.The handler already has
Options.RegistrationSourceSchemeand anIOptionsMonitor<CookieAuthenticationOptions>, and the registration header already receives the resolved DBSC scheme, so one per-scheme protector (for example from a factory or cache keyed by scheme) can serve both. Changing the purposes invalidates in-flight challenges, which is acceptable because the package is experimental.Other multi-scheme areas to specify and validate
Data Protection is not the only area. The following also need an explicit design and tests:
RegistrationPathandRefreshPathdefault to the same values (/.well-known/dbsc/registrationand/refresh) for every DBSC scheme.HandleRequestAsyncmatches on method and path only, so with default paths the first handler registered answers every request, and registration or refresh runs against the wrong source scheme. Options validation only checks that registration and refresh differ within one scheme. Decide between per-scheme paths, a distinguishing component, or failing fast on a cross-scheme collision.RefreshPath. Confirm that cookies of different schemes sharing a directory do not interfere, and that paths remain correct under a path base. Related to DBSC derived session cookie should preserve source cookie path #69618 and DBSC: separate browser-advertised endpoint URLs from local handler paths #67850.PostConfigureDeviceBoundSessionAuthenticationOptionsonly upgrades the app's default authenticate scheme when it matches a DBSC source scheme. Define behavior for apps using several DBSC source schemes, including per-request forwarding (DBSC session authentication does not preserve the source scheme's per-request forwarding #69620).DeviceBoundSessionSourceSchemes. The scheme maps are keyed by source scheme. Define and test behavior when the same source scheme is registered twice or when derived names collide, and fail with a clear error.DataProtectionProvider,TicketDataFormat,SessionStore(DBSC: share source scheme ITicketStore (server-side revocation) with derived cookies #67794), and events. Derived schemes must follow their own source, not another one.DeviceBoundSessionCookieEvents.RegistrationExchangeItemKeyis a singleHttpContext.Itemskey. Confirm it cannot suppress sign-out handling for a different scheme within one request.Acceptance criteria
DataProtectionProviderand the same principal.DataProtectionProviderof their own source scheme. A challenge minted under a dedicated provider cannot be validated under the application-default provider, and the reverse also fails.DerivedCookieSchemes_RemainDataProtected_AndSchemeKeyed).AddCookieandAddDeviceBoundSessionregistration pipeline, not only directPostConfigurecalls, so options ordering is covered. They cover at least two schemes, with both shared and distinct providers.DbscDebugServersample or equivalent, to confirm the browser flow.