Blazor Server Custom Authentication [Blazor Tutorial C# - Part 11]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hi, welcome to Coding Droplets and  thank you for watching this video. This is a complete course to learn .Net Blazor  development. So this video is part of a series and this is part 11 of dotnet blazor tutorial  series. You can check out the playlist link that is mentioned in the video description for  finding the other videos in this series. Before starting the implementation, let me show  you the final output of the blazor server project with authentication and authorization. Now here  in this home page or in the index razor component, you can see a greeting message, hello guest. Also we  have a login option on the top right corner of the page. Currently there are no users logged in and  that is the reason it is showing hello guest. Now let me click on the login option and you can see  a login page or razor component in which we have options to provide the credentials. Currently there  are two different users with two different roles. So first let me login by providing the credentials of the first user. Both the username and password is user. Once the user got authenticated you  might have noticed the changes in the UI. Now the greeting message changed to hello  user. A new display greeting alert button got displayed. Also previously there was  only the home option in the left side menu. But now it is also showing counter option in the  menu. There is also one more change in the UI. Now instead of login it is showing logout option. The users can log out by clicking that. Now let me click on the display greeting alert  and you can see it is showing an alert, 'hello user'. The reason for giving this button is to  demonstrate how we can access the logged in username or other user information in the onclick  event or in the code section. Now let me navigate to counter razor component and you can see that  this user is able to access the counter page. So now let's logout and login with the  second user. The username and password is admin. This user is having a different role. Now you can see it is showing 'hello admin' and there are three options in the left side menu. Fetch data was not available for the previous user. The alert message will also  show the name of the new user. You can see it is showing 'hello admin'. Admin  user can access counter razor component. Also admin user can access fetch data which  was not available before. Now let's see how we can implement this type of authentication  and authorization in a blazor server project. Here we are using role-based authorization  for changing the UI based on the user roles. Don't miss the upcoming videos in this channel. Please subscribe the channel named CodingDroplets and don't forget to press the bell icon so that  you will get notified once we upload new videos. I have opened visual studio. First let's create a  new blazor server project. So I am clicking on create a new project. Here I can search for  blazor server app and select it. Then click next to continue. Providing the project name as  blazor server authentication and authorization. Again clicking on next. I'm using dotnet6  framework for this project and just unchecking the configure for https checkbox. Now clicking on the  create button. So the project will get created now. It got created and we are able to see the project  files in the solution explorer. So the first thing what i need to do is, creating a folder named  authentication under the project. We'll be keeping all the classes related to authentication in  this particular folder. Now we are going to create a new class named custom authentication  state provider. We have to inherit this class from authentication state provider. We have to  import 'microsoft.aspnetcore.components.authorization' in order to use authentication state provider. Now  let's see what is authentication state provider. In blazor authentication state provider is  the built-in service for blazor server apps that obtains authentication state  data from the asp.net core's 'HttpContext.User'. Now we can implement the  abstract class and it will override a new method 'GetAuthenticationStateAsync'. This method  will get executed when the application get opened or the page got refreshed. Here let me declare  private 'ProtectedSessionStorage' object. For that we have to import 'microsoft.aspnetcore.  components.server.protectedbrowserstorage'. We are going to save the login user details in  the protected session storage. Also let me declare private claim principle object. For that  we need to import 'system.security.claims'. We'll be using this object for anonymous users. Now I'm creating a constructor for this class and provide protected session storage as a  parameter. We will be adding protected session storage in dependency injection. So that we can  receive the object here in the constructor. Next we can assign the value for the private protected  session storage object from the constructor. Now let's move to the program.cs class and  do the dependency injection for protected session storage. So we are now ready to implement  the 'GetAuthenticationStateAsync' method in our custom authentication state provider  class. Here first we can try reading the user session details from the protected session  storage. So session storage dot get async of user session. We have to create a model class  named user session. We will do it soon and here the user session in string represents the key of  the protected session storage. Protected session storage will keep data in key value format. So we  are going to save the logged in user details with the key, user session. Also we need to make this  method async as this session storage function is awaited. Next let's create the model class named  user session. I am only providing two properties for this model class - username and role. You can  provide more if you need. Now assigning the value to a variable named user session. User session  storage result dot success will be a boolean value based on get async method. If the value is  successfully fetched it will be true. Otherwise it will be false. So here we are assigning a null  value to the user session variable if it is false. Next we are implementing an if condition  to return the anonymous user authentication state if the user session is null. If it is  not null, we'll create a new claims principle object with two claims in it - name and role. Also  we have to provide an authentication type string value. It can be anything. If you are not providing  anything, the application will consider it as an anonymous user. So here I have provided custom auth. After that we can return the authentication state with the newly created claims principle. Now  I am providing a try-catch method and placing the code in it. This can be helpful if a user try  to modify the encrypted user session details from the protected session storage. If a user  modify the encrypted value, the application will not be able to fetch the user session from it  and the application will throw an error. So we can return the anonymous authentication state in  the catch section. Now let's create one more method for updating the authentication state.  We'll call this method when a user login or logout. I have provided the user session object  as a parameter for this method. So we can pass the user session object from the UI when a user login. First I am declaring a claims principle object. Then checking whether the user session object is  null. Here we will pass a null value from the UI when a user logout. So the else part means the  user has logged out. First let's implement what to happen if a user is logged in. Session storage  dot set async of the key user session and value is what we have received as the parameter. We  are assigning the value of user session in protected session storage. Then we create a new  claims principle with two claims username and role. We are assigning it in our object. Now let's  move to the else part. So we just need to delete the user session value from the protected  session storage. Then we make the claims principle as anonymous. Finally we are calling notify  authentication state changed method which is a part of blazor authentication state  provider and we are passing the authentication state along with the claims principle. Next  let's implement the dependency injection for our custom authentication state provider  class in 'program.cs'. It is a scoped dependency. builder dot services dot add scope authentication  state provider which is the blazor service. Then comma custom authentication  state provider which is our class. Now we need to fetch user data from the database  for validation. Currently in this sample project I am not doing any database implementation. But you  can use any database and implement the method for fetching user data from your database here.  I'll be hard-coding user data. First I'll create a model class named user account and it is  having three properties - username, password and role. Next creating a service named user account service. I am creating a private list of user accounts for saving the user data temporarily in memory. So  you don't need this private list of user accounts. You can fetch the data from your database. Now  as I am not using a database, I am using a list variable to fetch the data. So in the constructor  of this user account service class, I'll hard code two users - admin and user. You can see both of the  users have different roles - administrator and user. Now we need a method for fetching the user data by  filtering with their username. This 'GetByUsername' method will return the user account which matches  the username provided in its parameter. After that I am adding this service in dependency injection  and registering this as a singleton service. We also need to add 'builder.services.AddAuthenticationCore' in dependency. Now we have completed the configuration  part for blazor server authentication. Please don't forget to give me a thumbs up for  this video if you are enjoying it. Also let me know your feedback in the comments section. I  would like to hear from you. Now let's move to the UI development. In UI, first we need a login  razor component with which the users can login. I am creating a new razor component and naming it as  login. Now assigning the page directive '/login'. So that this page can be accessed with this URL.  Next let me add some of the injected dependencies - UserAccountServer, IJSRuntime,   AuthenticationStateProvider and NavigationManager. I have pasted the design for the login component. It includes two inputs - username and password and we have one button with the text login. This  is the model class for binding the values provided in the inputs. I am also creating an object of  the model class. Next I am providing a method named authenticate which has been provided in the  onclick event of the login button. In this method we'll fetch the user data by calling the 'GetByUserName'  method in our user account service. As a parameter we are sending the username  which we got from the input. Next we are just verifying the user account is not null. If the user  account does not exist with the provided username we'll get a null value here. Also we are validating  the password with an or operator. So if the user account is null or password is invalid, we are  just showing an alert to the user by invoking with IJSRuntime. Now what if the username and password  is valid. I am creating an object of the custom authentication state provider by casting it from  the injected authentication state provider. Then we can call the update authentication state method  which we have implemented. So this method will save the value in the session storage. Finally, we are  navigating the user to home page or index razor component. Next we are making some changes in the  index razor component. So in the home page we need to show a greeting message along with the username. For that I am implementing blazors authorized view component. Inside authorized view component we can  provide different designs for three authorization statuses - Authorized, NotAuthorized and Authorizing. Authorizing means the application is executing 'GetAuthenticationStateAsync' method in our  custom authentication state provide class. But the execution is not completed. So here we  only need two separate designs. One for Authorized and another one for NotAuthorized. We will not be  showing anything if the status is authorizing. We'll greet the user with their username if they  are authorized. Otherwise we'll just display 'hello guest'. Now we need one more authorized view for  displaying the greeting button. Here we only need authorized design. We don't show anything if the  user is not authenticated. Next in the code section we need to implement method for button onclick  event. Just before that I am opening 'App.razor' file and changing the RouteView to AuthorizeRouteView. We can only use authorized view in the razor components if we have mentioned authorized  route view here. Then only the razor component will receive the user authorization details. Next we need to add one more cascading parameter. That is cascading authentication state. This is for  getting the user authorization details in the code section. Now in the code section we can declare a  cascading parameter - task of authentication state. You can provide any name for this cascading  parameter. Next we can implement the onclick event. First I'll get the authentication state by  awaiting the cascading parameter. So the message to be displayed is hello and whatever value we have  in the 'authState.User.Identity.Name'. Then finally, invoking the alert javascript  function using IJSRuntime. For using IJSuntime, we need to inject it. Now we use IJSRuntime. Let's  invoke alert using 'InvokeVoidAsync' method in IJSRuntime and providing the await keyword. Next we  need to make some modifications in the left side navigation menu. We are showing the menu options  based on the user roles. So let me open the nav menu razor component in the shared folder. Then  implementing the authorized view razor component by mentioning the roles parameter. We need to show  the fetch data menu option only for the users with role administrator. Hence we can move the fetch  data menu option to the authorized component of the authorized view with roles administrator.  Next we need one more authorized view for counter menu option. Counter menu option should be visible  for users with both administrator and user roles. We can provide multiple roles by just separating  them with a comma. Now we can move the counter menu to the newly created authorized view. These are  the changes we need to do in the left side menu. Next in main layout, we can add  option to login and logout. And under NotAuthorized we can place the login option. For logout, we can provide an onclick event to remove the user session details from the session  storage. So let's implement the logout method. As we did before I am parsing the  custom authentication state provider from the authentication state provider. We  have to inject the dependencies as well. Now we can call the update authentication state  method in our custom authentication state provider and pass the parameter value as null. After that  just navigating the user to the home page. The next important thing we need to do is to provide  the authorized attribute in the razor components. The users will only be able to see menu  options based on their user roles. But still they can manually enter the URL in the browser's  address bar and access the page. So let's restrict the unauthorized users from accessing the razor  component itself. In fetch data razor component, I have provided the authorized attribute which will  allow only administrator users. Then in counter razor component, I am providing the authorized  attribute which will allow both administrator and user roles. Now let's run the application  and see whether it is working as expected. Let me login with admin user credentials  both username and password are admin. Display greeting button is working fine. User is  able to view all pages from the menu options. Let's logout and login with the second credentials.  Both username and password are user. You can see that only counter option is available in the menu  and display greeting button is also working fine. Now I'll show how we are saving the user session  details in the session storage. If you open the developer options in the browser, you can navigate  to application tab and inside session storage you will be able to find the details. Here you can  see the user session details are stored in an encrypted format and that is how the protected  session storage save the data. Now I'm trying to modify the encrypted value. Let's refresh the page  and you can see that the user got logged out. Next I'll show you few more things. In '_host.cs'  file, you can see an option named render mode. By default it will be server prerendered. So let  me give you a brief idea of what is renter mode. Basically there are two types of server render  modes. The first one is server prerendered. Renders the component into static html and  includes a marker for a blazor server side application. When the user agent starts it uses  this marker to bootstrap a blazor application. The second one is server. Renders a marker  for a blazor server side application. This doesn't include any output from the component. When the user agent starts it uses this marker to bootstrap a blazor application. If the render  mode is server prerendered we'll receive an error in the 'GetAuthenticationStateAsync' method of  our custom authentication state provider class while refreshing the page. Because the application  cannot process IJSRuntime which will be used to access the session storage. But we'll not see that  error as we have implemented the try-catch method. If you need to remove that error you  can use server in the render mode. Now let's run the application and you can see  everything works fine. I'm trying to login with credentials and authentication  got succeeded. So all are working fine. Now without authenticating let  me try to access fetch data page and you can see an error message 'Not Authorized'. We can even customize this message or we can show a different design  instead of this message. Let me show you how to do that. In 'App.razor' file we can provide  a different design for 'NotAuthorized' state. So i am providing a custom  message 'You are not authorized' and this is a custom message in brackets. Also we can show custom design for  authorizing state. I am providing a custom message for that as well - 'You are getting  authorized' and custom message in brackets. Now in order to display the authorizing message, I  am providing an awaitable task.delay of 5 seconds. Let's run the application. It is getting  compiled. Uou can see the authorizing message now. Now let me try to navigate to fetch  data by entering the url manually. So it shows the authorizing message and after 5  seconds it will show the not authorized message. Now I am authenticating with admin user and  accessing the fetch data razor component and you can see it is working properly. So  that's it for this video. Hope you enjoyed it. Please like, share and comment the video. See you all in the next video. Thank You!
Info
Channel: Coding Droplets
Views: 48,829
Rating: undefined out of 5
Keywords: blazor server custom authentication, blazor authentication and authorization, blazor auth, blazor authorization tutorial, blazor authorizeview, blazor authorization, blazor authorize attribute, blazor server auth state provider, blazor authorization policy, blazor server authorize, blazor server custom authentication state, blazor server auth, blazor server authentication state provider, blazor server role authorize, blazor server authentication tutorial
Id: iq2btD9WufI
Channel Id: undefined
Length: 25min 0sec (1500 seconds)
Published: Tue Mar 15 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.