- ABP Framework version: v8.3.2
- UI Type: Blazor WASM
- Database System: EF Core (SQL Server)
- Tiered (for MVC) or Auth Server Separated (for Angular): no
Hi, I have an ABP 8.3.2 blazor wasm solution. I need to implement some additional logic when a user signs out or when a user exits the application. What is the best way to implement such logic using the ABP Framework?
15 Answer(s)
-
0
Hi, you need to create a custom event handler for that purpose. Please apply the following steps:
- Create a custom event handler as follows (doc: https://kevinchalet.com/2018/07/02/implementing-advanced-scenarios-using-the-new-openiddict-rc3-events-model/):
using System.Threading.Tasks; using OpenIddict.Server; namespace MySolution; public class SignOutEventHandler : IOpenIddictServerHandler<OpenIddictServerEvents.ProcessSignOutContext> { public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder<OpenIddictServerEvents.ProcessSignOutContext>() .UseSingletonHandler<SignOutEventHandler>() .SetOrder(100_000) .SetType(OpenIddictServerHandlerType.Custom) .Build(); public ValueTask HandleAsync(OpenIddictServerEvents.ProcessSignOutContext context) { //your logic... return ValueTask.CompletedTask; } }
- Then register the event handler in the module class:
public class MySolutionHttpApiHostModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) { //... PreConfigure<OpenIddictServerBuilder>(serverBuilder => { serverBuilder.AddEventHandler(SignOutEventHandler.Descriptor); }); //... } }
- After these steps, your
SignOutEventHandler
class's HandleAsync method trigger after every signout request.
-
0
Hi, Thanks for the reply! This solution only works when a user correctly signs out of the application, which is a partial answer to my question. Is there no way to do the same also when a user closes the browser window or leaves the application website?
-
0
Hi, Thanks for the reply! This solution only works when a user correctly signs out of the application, which is a partial answer to my question. Is there no way to do the same also when a user closes the browser window or leaves the application website?
Hi, there is not an event for that purpose on the OpenIddict side. You may consider using SignalR, and when the user disconnects, apply your logic. (however, sometimes signalr connection terminates because of numerous reasons, so you should check it accordingly)
Regards.
-
0
Hi,
Can you provide me with a code example of the SignalR approach you are suggesting?
-
0
Hi,
Can you provide me with a code example of the SignalR approach you are suggesting?
Hi, you can create a Hub, and then use the DisconnectAsync() method to control the disconnections (https://abp.io/docs/latest/framework/real-time/signalr):
1-) Create a Hub:
public class UserConnectionHub : AbpHub { public override async Task OnDisconnectedAsync(Exception exception) { await HandleUserLogout(Context.ConnectionId); //or your custom logic... await base.OnDisconnectedAsync(exception); } }
2-) In your blazor side (connect):
var connection = new HubConnectionBuilder() .WithUrl("/userConnectionHub") .WithAutomaticReconnect() .Build(); try { await connection.StartAsync(); Console.WriteLine("SignalR Connected."); } catch (Exception ex) { Console.WriteLine($"SignalR Connection Failed: {ex.Message}"); }
You can call the code above, in a constructor of your blazor pages (in the base class).
-
0
Hi,
Thanks for the example! I have a couple questions:
- With SignalR automated reconnect turned on in the HUB connection, how can i know when a user has disconnected from the application rather then having lost connection and trying to reconnect?
- How do you handle hub connection in the Chat Module, is there any standard you use in Blazor WASM?
- If multiple hubs are registered, would they interfere with each others or live independetly without problems?
Thanks in advance.
-
0
- With SignalR automated reconnect turned on in the HUB connection, how can i know when a user has disconnected from the application rather then having lost connection and trying to reconnect?
Frankly speaking, I'm not sure you can do this with 100% correctness. However, you may create a temporary table/queue, push the current disconnected user to the queue, then read from the queue in a specific time interval, and check if there is an audit log there is related to the user after adding it to the queue. So, you can check if its really leave the application or temporarily disconnected.
- How do you handle hub connection in the Chat Module, is there any standard you use in Blazor WASM?
You can download the chat module's source code and use its hub by your needs or you can follow the approach I suggested above.
- If multiple hubs are registered, would they interfere with each others or live independetly without problems?
They should live independently without problems.
Using SignalR might be hard to maintain and ensure user leaved the application or not. Maybe you can search for another approach for your use case. For example, you might use beforeunload event on the JS side (https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event), or use a similar approach for the Blazor WASM.
Regards.
-
0
Hi,
I can't seem to be able to download the Chat Module source code, could you kindly send it to my email or explain the approach you used in the module?
Thanks.
-
0
Hi,
I can't seem to be able to download the Chat Module source code, could you kindly send it to my email or explain the approach you used in the module?
Thanks.
In the chat module, there is a hub class called
ChatHub
and we simply use it to trigger a socket connection (for sending a message, deleting a conversation, and deleting a message on the server side, and on the client side doing the receiving events). Creating a new hub and using itsDisconnectAsync
is what comes to my mind as the first solution.However, investigating the other options can be better, because it might be hard to maintain and understand if the user really disconnected temporarily or permanently. Since this is not related to ABP, I'm sorry to not being able to answer with a concrete solution.
Regards.
-
0
Hi,
Thanks for the help anyway. One last question regarding the logout: How can i redirect a user to the homepage after logout rather then the "You have been logged out" page?
-
0
How can i redirect a user to the homepage after logout rather then the "You have been logged out" page?
There should be an
OpenIddictDataSeedContributor
class under your domain project, you should open it and update thepostLogoutRedirectUri
:// postLogoutRedirectUri: $"{blazorRootUrl}/authentication/logout-callback", postLogoutRedirectUri: $"{blazorRootUrl}",
Then, run the dbmigrator project to update your database. (since you already have a database, this change will not be applied, so you can manually update in database for now - or delete the OpenIddictApplication table records and run the dbmigrator)
-
0
Hi,
I have done as you explained but when i press the logout button now it gives me the following error:
error:invalid_request error_description:The specified 'post_logout_redirect_uri' is invalid. error_uri:https://documentation.openiddict.com/errors/ID2052
It looks like in the url 'post_logout_redirect_uri' is still the old PostLoginRedirectUrl. How can i fix this?
-
0
Hi,
I have done as you explained but when i press the logout button now it gives me the following error:
error:invalid_request error_description:The specified 'post_logout_redirect_uri' is invalid. error_uri:https://documentation.openiddict.com/errors/ID2052
It looks like in the url 'post_logout_redirect_uri' is still the old PostLoginRedirectUrl. How can i fix this?
You should also configure the
OpenIddictServerBuilder
in the *HttpApi.Host module (add the following code in your preconfigureservices method):PreConfigure<OpenIddictServerBuilder>(serverBuilder => { serverBuilder.SetLogoutEndpointUris("<your-blazor-root-url>"); });
-
0
Hi,
PreConfigure<OpenIddictServerBuilder>(serverBuilder => { serverBuilder.SetLogoutEndpointUris("<your-blazor-root-url>"); });
Seems to change the "Logout Url" (the url you go to when logging out) rather then "Post Logout Url" (the url you go to after having logged out).
-
0
Hi,
PreConfigure<OpenIddictServerBuilder>(serverBuilder => { serverBuilder.SetLogoutEndpointUris("<your-blazor-root-url>"); });
Seems to change the "Logout Url" (the url you go to when logging out) rather then "Post Logout Url" (the url you go to after having logged out).
Hi sorry, you are right. After the change you made in the
OpenIddictDataSeedContributor
, the only thing you need to do is to open the*BlazorModule
class and make the following change:builder.Services.AddOidcAuthentication(options => { builder.Configuration.Bind("AuthServer", options.ProviderOptions); options.UserOptions.NameClaim = OpenIddictConstants.Claims.Name; options.UserOptions.RoleClaim = OpenIddictConstants.Claims.Role; options.ProviderOptions.DefaultScopes.Add("AbpSolution5"); options.ProviderOptions.DefaultScopes.Add("roles"); options.ProviderOptions.DefaultScopes.Add("email"); options.ProviderOptions.DefaultScopes.Add("phone"); //add this line options.ProviderOptions.PostLogoutRedirectUri = "https://localhost:44353"; });