Hi,
For security reasons we wish to implement a forceful logout with a corresponding redirect after a configurable amount of time (i.e., "Session Timeout" after 15 minutes of inactivity). This works reasonably well, unless the user has unsaved changes when the forced logoff occurs. In that case the browser generates a Javascript alert
(see screenshot below) and does not perform the redirect.
We are already calling IUnsavedChangesConfirmationService.ClearState()
before the forced logoff which makes the Blazor confirmation dialog disappear, but the JavaScript-one from the browser remains.
After this forceful logout we want to redirect to a specific page notifying the user that we quit their session due to inactivity. Out-of-the-box this is currently not really configurable if using external authentication (single-sign-on using OAuth). There is apparently a way to do it with for Win-Auth with WindowsActiveDirectoryAuthenticationProviderOptions.SignOutRedirect
which would be nice to have in the base-class ExternalAuthenticationProviderOptions
instead. This way it could also work for other SSO methods without much changes to your code and probably without breaking compatibility.
To Reproduce
Open the attached sample solution based on your MainDemo and reproduce the behavior as follows:
- Login as 'Sam'
- Open any employee
- Make changes to the employee without saving them
- Wait for about a minute before the timeout occurs
- A browser popup prevents the forced sign out from occurring
Expected behavior
User should be logged out and redirected to the logout page without any questions asked.
Screenshots
Additional context
- The demo implementation here performs a forced logout after 1 minute of the
ForceLogOffController
becoming active (basically after login), so you need to be quick about making changes. - The forced logoff works if no unsaved changes exist.
- Of course our actual implementation tracks user activity and multiple blazor sessions of the same user, etc. but the actual force logout problem remains the same.
Looking forward to your suggestions,
Kind regards
Chris
Hello, Chris.
Thanks for the interesting question. It appears that the built-in web browser dialog will be difficult to bypass or this is unrelated to DevExpress/XAF directly (I expect the same behavior in non-XAF apps as well).
Do you have a non-XAF Blazor Server reference application where you implemented a similar mechanism and where it works as you expected (when the built-in web browser dialog was displayed)? We just want to focus on the XAF-related things here, which are in our control. Regards.
Hi Dennis,
that was quick. Interesting response as well. I thought this message has to do with the JavaScript-based
xaf.ConfirmUnsavedChangedController
. Well, thank you for making me look into it abit more in-depth becausexaf.ConfirmUnsavedChangedController
(notice the "d" instead of the "s" in "Changed") plays a role here. But that seems to be the old XAF-WebForms solution.xaf.ConfirmUnsavedChangesController
is relevant here instead. I'm however uncertain about it, because thexaf.ConfirmUnsavedChangesController.SetModified(false)
call that happens whenClearState()
is called, seems to have no effect. However,C#
manually betweenawait serviceProvider.GetRequiredService<IXafJSRuntime>().InvokeVoidAsync("xaf.ConfirmUnsavedChangesController.SetModified", false);
ClearState()
andLogoff()
in theForceLogOffController.StartTimer()
method, it actually works for the scenario outlined above.So what do you make of this?
Hello,
Thank you for the clarification. Indeed, although we don't have a dedicated mechanism for this task, I believe you can utilize this internal code. We don't have plans to change it.
Regards,
Andrey
Thanks for your confirmation that the workaround works for you as well.
It would be nice however if
ClearState
would work here, since it does call the same method internally. I guess the missing await inClearState
leads to a race condition which is why it doesn't work, while the separate awaited call does work.Any chance you are fixing this?
It would also be nice if you think about the
SignOutRedirect
forExternalAuthenticationProviderOptions
I mentioned above.Wishing you a nice day,
Chris
Hello,
Thank you for your suggestion. In v24.2.6, we adjusted the behavior of the LogOff() method, so there is no need to call any additional code (such as IUnsavedChangesConfirmationService.ClearState) to permit an application to log off. Please update your app and test it.
Let me know if this helps.
Regards,
Andrey
Hi Andrey,
it seems the adjusted behavior you mention for 24.2.6 does not work if we're editing a ListView in BatchEdit mode (inside a popup).
In this case a manual call to
ClearState
is still required to make the forced logout work. So sadly we still can't remove that workaround.All the best,
Chris
Hello Christoph,
Thank you for the update.
Please allow us additional time to discuss this within our team. We will update this ticket once we have information to share or if we require clarification.
Best regards,
Herman