I have a public home page than anyone can access, but I would also like to check if the user is currently logged in when they access the page of the first time, as this check drives what the user can see on the navigation menu.
I have recently upgrade to 3.2 Preview 2 and implemented the new auth provided (thank you for this!), which is all working well.
However, when I try use the _IAccessTokenProvider_ or the _AuthenticationStateProvider_ in the _OnInitializedAsync_ of the _App.razor_ or _MainLayout.razor_ to try and "silently" check the users logged in status. I am getting the following error:
Unhandled exception rendering component:
Microsoft.JSInterop.JSException: Cannot read property 'getUser' of undefined
TypeError: Cannot read property 'getUser' of undefined
Clearly, something hasn't been setup properly before I am trying to access this.
Am I doing this right, or there is an event I can subscribe to when the auth has been successfully setup and is ready to use?
Is there another place I can attempt to silently check if the user has an access token, other than the
_OnInitializedAsync_ of the _App.razor_ or _MainLayout.razor_ that will allow the user to have seamless experience, if already logged in?
Thanks for your time.
@MitchellNZ thanks for contacting us.
Can you provide a minimal repro project that showcases your issue so that we can investigate?
@javiercn sure thing.
I have created a repo project here that demonstrates my issue (its using the latest template with auth and .NET Core hosted).
The pages of interest are App.razor and Counter.razor.
Steps
Microsoft.JSInterop.JSException: Cannot read property 'getUser' of undefined).The potential issue I see here is, if I do something like this (the OnInitializedAsync code in Counter.razor), and it returns an access token successfully, I could fire off an authorised request to server and get some response back without issue but my _view_ is giving no indication that the user is logged in.
Now I assume this is because the RequestAccessToken does not trigger the NotifyAuthenticationStateChanged method. But I'm not sure if how expensive it is to do so each time, or if its possible to only do it when a _new_ token is retrieved from the server.
I also understand that if I add an Authorize tag to this page, everything would flow through the auth pipeline you have created and display a logged in status just fine. But my use case is trying to cover the scenario where the page might be a public one, and display additional functionality only if the user is logged in.
Outcome
Ideally, I would like to find a way to silently check if the user is logged in whenever they load any route on my website, so I can show them they are logged in and display additional navigation menu items, etc. I'm not sure if I am on the right track with this, or you recommend another way?
Hope this is clear enough!
Thanks again for your time.
@MitchellNZ thanks for the repro.
I investigated and this is a legitimate bug, it's an issue with the async initialization in the AuthorizeService.
@javiercn Great - thanks for taking the time to investigate!
As for the second part of my comment - do you have any thoughts on the fact you can call RequestAccessToken and get a valid access token (silently, if the user is still logged into Identity Server) which can then be used to make authorized requests - but without showing any indication to the user via the view.
Is this something that should be updated to call NotifyAuthenticationStateChanged when a token is retrieved successfully from the Identity Server? Or can this be handled another way?
Thanks again for your time.
As for the second part of my comment - do you have any thoughts on the fact you can call RequestAccessToken and get a valid access token (silently, if the user is still logged into Identity Server) which can then be used to make authorized requests - but without showing any indication to the user via the view.
Is this something that should be updated to call NotifyAuthenticationStateChanged when a token is retrieved successfully from the Identity Server? Or can this be handled another way?
The AuthenticationStateProvider should detect that you are logged-in on the underlying provider, so you shouldn't need to do this.
Ideally, I would like to find a way to silently check if the user is logged in whenever they load any route on my website, so I can show them they are logged in and display additional navigation menu items, etc. I'm not sure if I am on the right track with this, or you recommend another way?
Yes, there is a much simpler way. Use <AuthorizeView>. For example:
<AuthorizeView>
<Authorized><p>This content will be rendered if you're logged in.</p></Authorized>
<NotAuthorized><p>This content will be rendered otherwise.</p></NotAuthorized>
</AuthorizeView>
The <AuthorizeView> component automatically updates its output dynamically when a user changes their auth state.
Not closing this issue though, because as per @javiercn:
I investigated and this is a legitimate bug, it's an issue with the async initialization in the AuthorizeService.
@SteveSandersonMS Thanks for your reply.
I have been using the <AuthorizeView> as you suggested, which is working great.
However, my issue is that I have no way to silently check if the user is signed in.
As you mentioned,
The
component automatically updates its output dynamically when a user changes their auth state.
But this is not helpful for me to silent check their auth state in the first place.
Everything is working nicely after the user has manually clicked the login button themselves.
What I want, is to silently check their logged in status when the app loads, without any user interaction and just fail gracefully (by doing nothing) if the login state is NotAuthorized.
This will allow me to have my app seamlessly show additional functionality in nested components (like navigation items) _if_ they are logged in, while continuing to just be a public app that doesn't require them to be logged in at all.
Hope this helps clarify.
I also hope I'm understanding what you mean and not overlooking something!
Thanks again,
Mitchell.
@MitchellNZ Did you try the following? https://docs.microsoft.com/en-us/aspnet/core/security/blazor/?view=aspnetcore-3.1&tabs=visual-studio#procedural-logic
@SteveSandersonMS I think the remainder here might be related to https://github.com/dotnet/aspnetcore/issues/20027
@SteveSandersonMS @javiercn yes, #20027 appears to be the same issue I am trying to address.
Sorry for any confusion with my wording of the issue!
Closing this as a dupe of https://github.com/dotnet/aspnetcore/issues/20027
Most helpful comment
@MitchellNZ thanks for the repro.
I investigated and this is a legitimate bug, it's an issue with the async initialization in the AuthorizeService.