Blazor Web Assembly (stand alone) - [Authorize] Attribute not recognising roles straight after login
have a custom
AuthenticationStateProvider
that adds roles to the ClaimsPrincipal in public override async Task<AuthenticationState> GetAuthenticationStateAsync()
As an anonymous user, when I hit a route protected with the [Authorize(Roles="Administrator")]
attribute, the app correctly sends me to login and redirects me back to the protected route after login.
However, when I log in as a user account that has the "Administrator" role, upon landing back on the protected route it tells me that I don't have permission to access that page (i.e. I'm logged in but don't have the correct role).
If I reload the page in the browser, it then recognises that I have the role and lets me in.
In my case, I'm adding the authorize attribute to a whole directory using _Imports.razor
:
Not sure what I'm doing wrong.28 Replies
Is GetAuthenticationState being called again once you land back on the protected route?
I'd log just to make sure there's no weird order of operations bug
@Crdl I added an info log at the start of
GetAuthenticationStateAsync
:
In the browser log...
info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] GetAuthenticationStateAsync() called info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: RolesAuthorizationRequirement:User.IsInRole must be true for one of the following roles: (GlobalAdministrator|Administrator)I did the above, then restarted the Blazor app. 1. Went to my /admin route in the browser 2. Was correctly redirected to login page on my OIDC server 3. Logged in - was redirected back to /admin Then saw the logs above
Is the first GetAuthenticationState call actually getting what you expect?
Can you log in there basically everything you should have?
And see how that differs after you refresh
Added more logging... It looks like inside the
GetAuthenticationStateAsync()
call the user.Identity?.IsAuthenticated
is returning false on that run.
info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### GetAuthenticationStateAsync() called invoke-js.ts:176 info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### We are authenticated: False invoke-js.ts:176 info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### DONEAfter hitting reload in the browser:
info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### GetAuthenticationStateAsync() called invoke-js.ts:176 info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### We are authenticated: True info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### Profile: {"Id":"4592defe-abdf-43bd-833d-4dede705b5aa","Email":"test-user-1@test.com","Name":"Administrator","Roles":[{"Id":"01J3Z3F1X6AJMXA8AAM0PSWAN0","Name":"GlobalAdministrator"}],"Permissions":["Role:Create","Role:Read","Role:Update","Role:Delete","Role:ManagePermissions","UserProfile:Create","UserProfile:Read","UserProfile:Update","UserProfile:Delete","UserProfile:ManageRoles","Permission:Read"]} invoke-js.ts:176 info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### Adding roles to claims: http://schemas.microsoft.com/ws/2008/06/identity/claims/role: GlobalAdministrator invoke-js.ts:176 info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### Adding new claims identity to principal: [{"Type":"http://schemas.microsoft.com/ws/2008/06/identity/claims/role","Value":"GlobalAdministrator"}] invoke-js.ts:176 info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### NotifyAuthenticationStateChanged info: Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService[0] ### DONEThe issue is that
user.Identity?.IsAuthenticated
is false at the point where the OIDC server redirects us back to the app
I just don't get why since we just logged inJust a hunch, maybe just double check your middleware is in the right order on the server?
ASP.NET Core Middleware
Learn about ASP.NET Core middleware and the request pipeline.
Itβs stand alone web assembly. No server.
Any more ideas @Crdl - I'm at a complete loss π¦
@Kyr can I see the rest of your
AuthenticationStateProvider
?Sure - attached as it's too big for a message
What's in the base class?
That's the default .NET class that is being loaded in web assembly when using OIDC authentication
@Crdl I'd happily jump in a voice channel and screen-share if that would help resolve this π
Am currently at work unfortunately π
Me too ... trying to get this working as a POC template in an attempt to get Blazor adoption in the business.
Already had to abandon the .NET 8 InteractiveAuto style Server + Wasm way of doing things because it just doesn't work with remote auth when you need client components to make authenticated requests to an external API... now having different auth problems with pure wasm.
It's so frustrating because I can see Blazor's potential... yet it roadblocks me at every turn
https://github.com/dotnet/aspnetcore/blob/main/src/Components/WebAssembly/WebAssembly.Authentication/src/Services/RemoteAuthenticationService.cs#L104 could it be this
useCache
flag?GitHub
aspnetcore/src/Components/WebAssembly/WebAssembly.Authentication/sr...
ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux. - dotnet/aspnetcore
Not sure how it can be if I'm overriding
GetAuthenticationStateAsync()