Skip to content

fix(authorization): restore legacy UserState-via-ContextData fallback#22

Open
cliedeman wants to merge 1 commit into
mainfrom
fix/auth-legacy-userstate-contextdata
Open

fix(authorization): restore legacy UserState-via-ContextData fallback#22
cliedeman wants to merge 1 commit into
mainfrom
fix/auth-legacy-userstate-contextdata

Conversation

@cliedeman

Copy link
Copy Markdown

Problem

PRs ChilliCream#8267 / ChilliCream#8329 migrated UserState out of ContextData (the well-known key "HotChocolate.Authorization.UserState", whose WellKnownContextData.UserState constant was deleted) into the typed Features collection. DefaultAuthorizationHandler.GetUserState now reads only Features.TryGet<UserState>() and throws MissingStateException otherwise.

The rewritten TryCreateUserStateIfNotExists only handled a bare ClaimsPrincipal placed in ContextData under nameof(ClaimsPrincipal). Consumers that supplied a ready-made UserState object under the old well-known key silently stopped authenticating.

This bites the Strawberry Shake in-memory client: it runs in-process and bypasses DefaultHttpRequestInterceptor / DefaultSocketSessionInterceptor (which normally build UserState from context.User), so the user is injected manually via SetGlobalState("HotChocolate.Authorization.UserState", new UserState(principal)). Post-migration that value never reached the Features-based handler, so authorization saw an unauthenticated user.

Fix

AuthorizationFeatureExtensions.TryCreateUserStateIfNotExists now promotes a UserState found under the legacy key into Features, taking precedence over reconstructing one from a ClaimsPrincipal. The legacy key is a local private const (no shared constant survives the migration; DefaultAuthorizationHandler likewise hardcodes the same string in its error message).

Test

Authorize_Should_Use_Explicit_UserState_When_Passed_Through_ContextData injects a UserState via SetGlobalState under the legacy key and asserts the request gets past authentication (it fails later with "The node ID string has an invalid format." rather than a NotAuthenticated error). All 34 Authorization.Tests pass locally.

Targets main so the full CI runs the real Authorization.Tests.

— Claude
🤖 Generated with Claude Code

After ChilliCream#8267/ChilliCream#8329 moved UserState out of ContextData (well-known key
"HotChocolate.Authorization.UserState") into the typed Features collection,
DefaultAuthorizationHandler.GetUserState reads only Features and the rewritten
TryCreateUserStateIfNotExists only handled a bare ClaimsPrincipal. Consumers that
inject a ready-made UserState under the old key (notably the Strawberry Shake
in-memory client, which bypasses the request/socket interceptors and calls
SetGlobalState("HotChocolate.Authorization.UserState", new UserState(principal)))
silently stopped authenticating.

Re-add a legacy-key fallback that promotes a UserState found under the old key into
Features, taking precedence over reconstructing one from a ClaimsPrincipal.

Adds Authorize_Should_Use_Explicit_UserState_When_Passed_Through_ContextData;
all 34 Authorization.Tests pass.
@github-actions

Copy link
Copy Markdown

Patch coverage

100.0% of changed lines covered (6/6)

File Covered Changed Patch %
…/Authorization/Extensions/AuthorizationFeatureExtensions.cs 6 6 100.0% 🟢

Project coverage: 52.4% (215296/411035 lines)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants