aspnetcore
aspnetcore copied to clipboard
[Blazor Wasm AD B2C] Authentication OnLogInSucceeded event fired multiple times.
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the bug
There seems to be a few related issues:
- By default the same token network request with
scope: openid profile offline_access, grant_type: refresh_token
is being called twice (is this necessary?). The authentication response time is already quite slow so this is pretty painful. - By default the
OnLogInSucceeded
event inRemoteAuthenticatorView
is firing twice. - Passing
[CascadingParameter] public Task<AuthenticationState>? AuthenticationState { get; set; }
causesOnLogInSucceeded
to fire three times. Is there a better way of retrieving the user claims here? - For application insights we need to set the AuthenticatedUserContext. By calling
SetAuthenticatedUserContext
theOnLoginSucceeded
is being called four times!
Full code:
<RemoteAuthenticatorView Action="@Action" OnLogInSucceeded="OnLogInSucceeded" OnLogOutSucceeded="OnLogOutSucceeded" >
<LogInFailed>
<ErrorDisplay Title="Sorry, your login failed." RetryText="logging in again" RetryAction="RedirectToLogin"
OnError="@(() => LogError("LogInFailed"))" />
</LogInFailed>
<LogOutFailed>
<ErrorDisplay Title="Sorry, log out operation failed." RetryText="refreshing the page" RetryAction="RefreshPage"
OnError="@(() => LogError("LogOutFailed"))" />
</LogOutFailed>
</RemoteAuthenticatorView>
@code{
[Parameter] public string? Action { get; set; }
[CascadingParameter] public Task<AuthenticationState>? AuthenticationState { get; set; }
private async Task OnLogInSucceeded()
{
Console.WriteLine("onlogin");
var user = (await AuthenticationState!).User;
await AppInsights.SetAuthenticatedUserContext(user.Id(), storeInCookie: true);
}
private async Task OnLogOutSucceeded()
{
Console.WriteLine("onlogout");
await AppInsights.ClearAuthenticatedUserContext();
}
Expected Behavior
-
scope: openid profile offline_access, grant_type: refresh_token
token network request to be called once -
OnLoginSucceeded
to only be called once
Steps To Reproduce
Blazor WebAssembly standalone with Azure AD B2C
Exceptions (if any)
No response
.NET Version
6.0.101
Anything else?
No response
Thanks for contacting us.
We're moving this issue to the .NET 7 Planning
milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.
This needs to be fixed sooner than .NET 7 planning stage. We are having this exact same issue. .NET 6.0.2 using Azure AD B2C. OnLoginSucceeded fires multiple times, which means that some post-login work we want to do can happen multiple times. It should happen just once and be dependable to fire only once, especially if we need to do any long running tasks during login like downloading some information from a Web API after the user has authenticated successfully.
Right now, I have to check the nonce value that comes back on the AdditionalProperties dictionary of the RemoteUserAccount and compare it to previous calls to know if I have done work before.
Lastly, shouldn't OnLoginSucceeded complete before the application tries to initialize a destination page it is trying to navigate to?
I know the title of this says AD B2C but I am having the same issue with normal AAD Authentication and OnLoginSucceded, except for me it fires constantly, forever, over and over again.
I am using Blazor WASM Hosted and OnLoginSucceded (on the Client) I am simply calling an API on the Server.
This is the Authentication.razor file
@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action" OnLogInSucceeded="GetCurrentUserProfile"/>
This is the code behind. Authentication.razor.cs file
public partial class Authentication
{
[Inject] public IUserProfileService UserProfileService { get; set; }
[Inject] public CurrentUserProfileState CurrentUserProfileState { get; set; }
[Parameter] public string? Action { get; set; }
private async Task GetCurrentUserProfile()
{
CurrentUserProfileState.UserProfileState = await UserProfileService.RetrieveCurrentUserProfileAsync();
}
}
CurrentUserProfileState
Is a singleton to store the result of the API call.
But when trying to login, I am stuck on a page that looks like this
And when I inspect the Brwoser Console, it is constantly call the Server API over and over again forever until I kill the process.
Am I doing some stupidly wrong here? This is the approach everyone tells me to use to do Post Login activities, so I'd thought they would have ran inito this as well.
@Gareth064 found a solution? Same problem here. As soon as i try to await it hangs.
Without the "await Task.Delay(1);" it works fine.
@wrkntwrkn Nope, didn't find a solution that would work so I abandoned the feature in my app until this is sorted.
Fires twice with AAD B2C for me, .NET 6
Even if this issue won't be fixed for .NET 7, the least Microsoft could do is provide some guidance on a workaround or recommended best practice to mitigate this issue. A list of do's and don'ts even? Or an alternative way to do post-login work if there is one?
Anything would be helpful for this rather than leaving us out to dry on this because this can't possibly be an edge use case for most developers.
I agree with the above comments. At the least, some guidance on how to avoid this issue would be helpful.
If it helps anyone, personally, using fluxor I just fire off an action when OnLoginSucceeded fires and when handling that action, I check current state to see if I've already fired it (it triggers a logged in bool) and ignore subsequent events.
Could be done using a static variable or local storage or some such as well.
Pretty simple but it works.
Duplicate of https://github.com/dotnet/aspnetcore/issues/39507
Does the other ticket include fix for:
- By default the same token network request with scope: openid profile offline_access, grant_type: refresh_token is being called twice (is this necessary)?