I have been building out my first Blazor application, and have been figuring out the pattern I want to follow for user authentication. Rather than use the built in Blazor authentication components, I am using the libraries I have built over the years, and I can plug into almost any app without having to think.
Where I got tripped up a bit with Blazor was in communicating the logged in an logged out status across components. After lots of Googling and experimenting, here is what I came up with:
In my Blazor Mainlayout page, I embedded the login bar component directly. This login bar just shows a login button, or if the user is logged in shows a logout button and the users name. When the signin button is clicked, the logon bar launches a login form component to collect username and password, and call the authentication API with the credentials. When a login is successful, the login bar updates a singleton class applicationvars.cs that holds all the profile information. This singleton allows all pages in the application to access these values. This is a nice, compact, and elegant way to handle what we used to call global and session variables – and is rapidly becoming one of my favorite things about Blazor.
Where I got tripped up was when I wanted to enforce a logout, or deal with a user session expired situation and message it appropriately. I finally settled on the solution of adding multiple routes to the same index page. I built route called ‘/logout’ and ‘/expired’, and added that route to the index page:
Where I erred was I put the logic to destroy the credentials in applicationvars inside the index page, which renders after the login bar, so the login bar didn’t reflect the credentials change. I futzed around with trying to get the index page to fire an event when the logout is detected, and have the login bar listen for the event and update appropriately. The better solution was to have the loginbar sniff the url, and when it sees the logout or expired URL, it destroys the credentials and redirects to the appropriate index URL. It was a much more elegant solution than getting the event wired up. It makes me wonder – maybe a new rule I need to follow: for your average business application, if you have to fire an event, you are probably doing something wrong in your design.
This design is working, and so far it has nicely isolated the authentication logic from the rest of the application. One worry is there is no easy way to have the app communicate with the login bar, so I may have isolated it too much. In recent various Blazor blog posts, I have noticed people are moving away from the singleton approach in favor of wrapping application vars around the whole application in the router. This new technique doesn’t change the over concept, so I may adapt that pattern in my next project. But for now, I will proceed with this pattern, and see how many times this paints me into a corner I don’t want to be in.