There is a an object of type AuthenticationState named "context" that is available inside AuthorizeView and AuthorizedRouteView components. This object allows to access the ClaimsPrincipal via context.User.
I can see in the source code that AuthenticationState is passed down to these components as Task by the CascadingValue component implemented in the CascadingAuthenticationState component (which in turn is defined at the top of the component hierarchy in App.razor).
However, when I inspect the source of the AuthorizeRouteView I can see the cascading parameter of type Task named ExistingCascadedAuthenticationState. Yet, it is a complete mystery to me how and where does the Task gets unwrapped and exposed as "context". Does anyone know the answer?
You need to dig deep, and it's a little complicated.
AuthorizeView
inherits from AuthorizeViewCore
AuthorizedRouteView
builds it's own AuthorizeRouteViewCore
inheriting from AuthorizeViewCore
.Code at the bottom of AuthorizedRouteView
:
private sealed class AuthorizeRouteViewCore : AuthorizeViewCore
{
[Parameter]
public RouteData RouteData { get; set; } = default!;
protected override IAuthorizeData[]? GetAuthorizeData()
=> AttributeAuthorizeDataCache.GetAuthorizeDataForType(RouteData.PageType);
}
AuthorizedRouteView
captures any cascade into ExistingCascadedAuthenticationState
. If one exists (not null) then CascadingAuthenticationState
exists in App
, so nothing more needs doing. If it's null then it adds CascadingAuthenticationState
as the component root component into its render fragment. This guarantees that Task<AuthenticationState>
is cascaded.
AuthorizeViewCore
captures the cascaded value:
[CascadingParameter] private Task<AuthenticationState>? AuthenticationState { get; set; }
It gets "unwrapped" in OnParametersSetAsync
currentAuthenticationState = await AuthenticationState;
isAuthorized = await IsAuthorizedAsync(currentAuthenticationState.User);
and used in BuildRenderTree
to the "context" you see.
var authorized = Authorized ?? ChildContent;
builder.AddContent(0, authorized?.Invoke(currentAuthenticationState!));
The content comes from:
RenderFragment<TValue>
declared as follows where TValue
- content
- is declared as AuthenticationState
:
[Parameter] public RenderFragment<AuthenticationState>? Authorized { get; set; }