Skip to content

Commit 835fb32

Browse files
[release/6.0] Backport 'Fix Blazor RemoteAuthenticatorView processing the same action multiple times' (#44718)
* Fix Blazor RemoteAuthenticatorView processing the same action multiple times * Fix components-e2e pipeline (#44402)
1 parent de2fa6d commit 835fb32

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

src/Components/WebAssembly/WebAssembly.Authentication/src/RemoteAuthenticatorViewCore.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class RemoteAuthenticatorViewCore<TAuthenticationState> : ComponentBase w
1818
private string _message;
1919
private RemoteAuthenticationApplicationPathsOptions _applicationPaths;
2020
private string _action;
21+
private string _lastHandledAction;
2122

2223
/// <summary>
2324
/// Gets or sets the <see cref="RemoteAuthenticationActions"/> action the component needs to handle.
@@ -165,6 +166,13 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
165166
/// <inheritdoc />
166167
protected override async Task OnParametersSetAsync()
167168
{
169+
if (_lastHandledAction == Action)
170+
{
171+
// Avoid processing the same action more than once.
172+
return;
173+
}
174+
175+
_lastHandledAction = Action;
168176
switch (Action)
169177
{
170178
case RemoteAuthenticationActions.LogIn:

src/Components/WebAssembly/WebAssembly.Authentication/test/RemoteAuthenticatorCoreTests.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,55 @@ public async Task AuthenticationManager_Login_NavigatesToLoginFailureOnError()
116116
Assert.Equal("https://www.example.com/base/authentication/login-failed", remoteAuthenticator.Navigation.Uri.ToString());
117117
}
118118

119+
[Fact]
120+
public async Task AuthenticationManager_Callbacks_OnlyExecuteOncePerAction()
121+
{
122+
// Arrange
123+
var (remoteAuthenticator, renderer, authServiceMock, jsRuntime) = CreateAuthenticationManager(
124+
"https://www.example.com/base/authentication/login-callback?code=1234");
125+
126+
authServiceMock.CompleteSignInCallback = s => Task.FromResult(new RemoteAuthenticationResult<RemoteAuthenticationState>()
127+
{
128+
Status = RemoteAuthenticationStatus.Success,
129+
});
130+
131+
authServiceMock.CompleteSignOutCallback = s => Task.FromResult(new RemoteAuthenticationResult<RemoteAuthenticationState>()
132+
{
133+
Status = RemoteAuthenticationStatus.Success,
134+
});
135+
136+
var logInCallbackInvocationCount = 0;
137+
var logOutCallbackInvocationCount = 0;
138+
139+
var parameterDictionary = new Dictionary<string, object>
140+
{
141+
[_action] = RemoteAuthenticationActions.LogInCallback,
142+
[_onLogInSucceded] = new EventCallbackFactory().Create<RemoteAuthenticationState>(
143+
remoteAuthenticator,
144+
(state) => logInCallbackInvocationCount++),
145+
[_onLogOutSucceeded] = new EventCallbackFactory().Create<RemoteAuthenticationState>(
146+
remoteAuthenticator,
147+
(state) => logOutCallbackInvocationCount++)
148+
};
149+
150+
var initialParameters = ParameterView.FromDictionary(parameterDictionary);
151+
152+
parameterDictionary[_action] = RemoteAuthenticationActions.LogOutCallback;
153+
154+
var finalParameters = ParameterView.FromDictionary(parameterDictionary);
155+
156+
// Act
157+
await renderer.Dispatcher.InvokeAsync<object>(() => remoteAuthenticator.SetParametersAsync(initialParameters));
158+
await renderer.Dispatcher.InvokeAsync<object>(() => remoteAuthenticator.SetParametersAsync(initialParameters));
159+
160+
await renderer.Dispatcher.InvokeAsync<object>(() => remoteAuthenticator.SetParametersAsync(finalParameters));
161+
await renderer.Dispatcher.InvokeAsync<object>(() => remoteAuthenticator.SetParametersAsync(finalParameters));
162+
163+
// Assert
164+
Assert.Equal(1, logInCallbackInvocationCount);
165+
Assert.Equal(1, logOutCallbackInvocationCount);
166+
}
167+
119168
[Fact]
120169
public async Task AuthenticationManager_LoginCallback_ThrowsOnRedirectResult()
121170
{

src/Components/test/E2ETest/Infrastructure/WebDriverExtensions/BasicTestAppAuthenticationWebDriverExtensions.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,11 @@ public static void SignInAs(this IWebDriver browser, Uri baseUri, string usernam
2222
{
2323
// Some tests need to change the authentication state without discarding the
2424
// original page, but this adds several seconds of delay
25-
var javascript = (IJavaScriptExecutor)browser;
2625
var originalWindow = browser.CurrentWindowHandle;
27-
javascript.ExecuteScript("window.open()");
28-
browser.SwitchTo().Window(browser.WindowHandles.Last());
26+
browser.SwitchTo().NewWindow(WindowType.Tab);
2927
browser.Navigate(baseUri, baseRelativeUri, noReload: false);
3028
browser.Exists(By.CssSelector("h1#authentication"));
31-
javascript.ExecuteScript("window.close()");
29+
browser.Close();
3230
browser.SwitchTo().Window(originalWindow);
3331
}
3432
else

0 commit comments

Comments
 (0)