Securing API with Duende Server (Identity Server 6)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
foreign [Music] and in this video we will take an existing API where I have implemented authentication and authorization but we are using the built-in.net identity right now what we are going to do is we are going to remove the built-in.net identity and we are going to authenticate API endpoints using the Dante identity server this video is an add-on to the.net API course that I have on udemy but if you want to get a rough idea of how to set up the identity server you can follow along that being said let me open the application that we have so far and see how to add identity server for authentication I will just point out again that this video is an add-on to the API course that I have on udemy so if you expect everything from Crown sub that is not what we are doing in this course if I go back to the code here you will see right now we have Villa API and the web project and if we expand that the web project will be consuming the API that we have and in our EPA we are using.net identity for authentication and authorization we will remove the built-in authentication that we add to our API and we will be adding the Dundee server here and we will see how to authenticate our API using the 10 day server version 6. so let's get started with all of that from the next video in our application we have authentication and authorization working with.net identity but what if we want to implement a microservices architecture and let's say we want a different module for implementing the authentication and authorization and for that we will be using 10-day server if you go to dendesoftware.com that is basically identity server since identity server 5 they have renamed that to be done test server and it is no longer free but if you view the pricing here there is a free Community Edition that we can use to learn identity server or the 10-day server qualifies for that for profit companies anything less than 1 million of gross revenue they can use that for free right here so we want to implement the Dundee identity server in our API endpoint for authentication and authorization how should we start for that in order to get started with that we will go to documentation here and we have the Quick Start now we can use the built-in.net identity templates that comes with 10 day software but I want to show you how to implement that in a clean MVC project so we will go back here and inside our project here or rather solution we will add a new project let me create an MVC project we will call that magic Villa underscore identity and then for the version here we have.net 7 now 10-day software has not been released for.net 7 yet so we can use.net6 but later on in the course we will update that 2.net 7 once that is released we want a simple project with none Authentication let me create that perfect now if we go back to our documentation and inside quick start let me click the overview tab you can see the first thing that we have to do is install the templates so for that we will open command prompt and let me copy the command that we have here paste and press enter now hyphen hyphen install is getting depreciated so rather than using.net new hyphen hyphen install we could have used.net new install and then the name tandate.identityserver.templates on my machine that is already installed so it displays that template was already installed it will be replaced with the latest version that's okay for now right here you see there are a few templates that are available if you want to directly use the Entity framework store you can do that but we have an empty project in that project we want to use the login registration pages and all the UI so we have the quick start for the UI which is assets only let's install that let me go back here and we basically need to navigate to our folder so we can right click on the project open folder and inside the root folder here let me create a new folder call it UI we will copy the path there go back to command prompt press CD to change the directory and you can just right click to paste the path that you copied and press enter that changes the path here and then we want the command.net new and the short name that we have is isui for UI only assets with identity server let's press enter for fact it is done if we go back to our UI folder and if we refresh here perfect we have the pages folder and www root now before done test 6 with.net 5 there were models views and controllers available but with thunder 6 they have replaced that with Razer pages that is the default Razer page that comes with dotnet identity as well we will cut this from here we will go to our identity project and directly paste it right here make sure you are in the identity project and we will replace the files in destination perfect so with that our UI only assets have been added in the new project that we created but right now this is only a basic MVC project if we set that as a startup project and we run that you will see the default MVC project we have an error let me see what that is and of course it is using quite a few things with the dentist server here but we have not installed those nuget packages so before anything we will have to install the new get packages that are needed with the Dundee server let me do that first in the next video now in our identity server project it will have its own database we do not want to keep everything isolated in our API project so identity will have its own database and that is a typical structure with microservices architecture each service will have a database of its own that way all of the micro Services can be isolated to configure that we will have to add application DB context right here in the data folder let's add a class file application DB context and we can copy that from the API here let me copy everything right here and of course we will change that paste it right here we do not want to see any data here we will remove that we will remove everything else and we will have the identity DB context when we do that we need different nougat packages so let me do that first manage nougat packages and let me close everything else here we want to work with the Dundee server so we will install the package 10 day dot identityserver.asp.net identity and we will install 6.1.3 now right now 10 day 7 is not released that is why we are using.net sex because microservices are isolated now even though done day 7 is not released we can still have our project s.net7 and that should work so here for the Target framework if we do dot Net 7 and then when we are going to the installed package the Thunder server we will install the 6.1.3 but the other packages we have to install net 7. so what will be the other packages first we have microsoft.asp.net code.identity dot Entity framework core Google install.net7 and we will use the same version that we have let me do that after that we have microsoft.asp.co.identity dot UI let me install that let me use the same version here and let's install that foreign we will be using SQL Server again so we'll install that package and finally for scaffolding we have Entity Framework code.tools and perfect let me install that as well and with that we have all the packages that are needed with our identity project now with those packages installed let me continue from the next video the next video we will set up our identity server for that we will create a.net core MVC project and then on that project we will create the DB context so we will create class for application DB context and extend the built-in identity user we will have application user then we have to configure the SQL Server database we will add connection string and in program.cs we will configure all the setup that is needed then we will add the identity Tables by configuring the identity and pushing the migration finally we will add Razer Pages support for identity server in the MVC project and then we will update the database to push all the identity tables that way we will set up the basic template that is needed for identity server at this point we have basically configured the asp.net identity and not the identity server but that is the basic setup that is needed before we get started with the identity server so let's accomplish all of that in the next video we have nougat packages installed let me open application DB context and add the using statements we do not have application user we will add that in just a second let me copy the class name here inside our models let me add application user we will make it consistent so it will Implement identity user and we will add a custom property of name in that application user that looks great now in our application DB context let me also add the navigation property and we will call that application users now even though we are using identity server it will basically use the same identity tables so all the tables with identity stays the same here in order to add the tables here in the identity we need connection string we will be adding a new section here in there the server will be dot that is what we are using database magic Villa underscore identity trust server certificate and trusted connection and multiple active result set we will set them to be true with that configured let me build the project we might have few errors but let me see that actually everything is successful let me try to rebuild this and perfect so now before adding the new get packages if you examine the program.cs we have not configured identity right here to add identity to our services we will have to do two things first we will have to add the DB context of application DB context where we will pass the connection string and that will set up our Entity Framework so first thing first we will set up our default connection on application DB context after that on builder.services we have ADD identity and there we want a custom implementation of identity user which is application user rules we will use the built-in identity rows and Entity framework we have application DP context now in our project of identity we have added the Razer Pages for that we will have to add filter.services dot add Razer pages and then if we scroll down here where we have the map controller route we have the MVC route we want to map Razer pages and on there we can have the required authorization to be on perfect that looks good with these changes let's add a migration we need to make sure startup project is identity that looks good default project will be identity add migration add identity tables perfect you can see here basically same tables will be created like asp.net user roles and all of them so that looks good let me update the database once that is done if we go back here we should have the magic Villa underscore identity and there we have the tables great now before we do anything let me run the application and show you what we are looking at and great you can see right here on the home page we have welcome to 10 day identity server but we do not have any login logout or those pages all of those pages or rather the page that you just saw is because of the pages right here and we have the index page we change the routes rather than using MVC it is using Razer pages that is great news but right now in our project pipeline in program.cs we have not added the identity server adding that is super simple before we say app.use authorization we can add app.use identity server and with that identity server has been added to the request pipeline but before we add that to the pipeline we have to configure our services to add identity server before filter dot build here we have filter.services.ad identity server and there of course we will have options that we can configure identity server has built in some of the events that it will raise like it has the raise error events raise information failure success events and emit claim audience there are way more configurations in identity server that you can configure but we will keep things simple and I will not go into much technical details of identity server but my goal is to show you how to get things up and running but when we configure the identity server we basically need identity resources API Scopes and clients with the identity server let me show you all of that in the next video this video I want to walk you through some of the common terms with identity server the first one is a client client is a piece of software that will request tokens from Identity server now there can be multiple clients like there can be a mobile application there can be a browser application or there can be some other clients that are using your identity server for Authentication they can request this token for either authenticating a user or let's say they need a token to print access to some resource client must be registered within the identity server before it can start requesting tokens next term is API resource and identity resource now after hearing these two terms you might be thinking what is a resource resource and simple term is a piece that you want to protect with your identity server API resource typically represents an API endpoint that you want to secure identity resource on the other hand is information about a user like let's say if I am saying that I am broken Patel how will I prove myself we can either display driver license or passport that is my identity similarly for a website a user will give their username and password and that will authenticate that user and then there will be some resource about that user like there will be email address there can be their physical address phone number everything related to Identity will be in identity resource so in simple terms identity resource is information about a user API resource represents something that you want to secure like an API endpoint and then when we are securing something we use tokens for that so typically there are two types of token first is the identity token and next we have the access token these tokens will typically be aligned with the resources an identity token will represent the outcome of an authentication process it will contain identifier for the user like that username user ID or something along those lines identity token typically has a subject that will be the username it will have information on how the user was authenticated and it will also have additional identity related information and the next token is access token that will allow access to an API resource clients that have registered to Identity server will request an access token and identity server provides that and then this access token will be passed by the client when they want to gain access to any of the API endpoints that are secure API endpoints will use the access token that client passes and they will validate if the request is coming from an authenticated user and if everything looks good in the access token for the resource then they will return back the resource that is requested these are the basic terms with identity server if everything does not make sense right now do not worry once we build the identity server they will start making much more sense but let me switch back to one of the documentation that they have with identity server on their GitHub they have a nice image that I want to show you can see users will use clients here and they will use identity server to get the identity token or access token using those two tokens they can use to access the identity of a user or a resource so basically there is something called as client that we will create and that will access the scope in an identity server scope will basically have identity and resource now do not worry about all the complications right now what you see here is a 10 000 feet overview we will configure clients scope and resources in an identity server from the next video now in our identity project you examine there is something called a stashed users and that creates a basic user using a test user it will add multiple claims on that and so on we do not want to use a test user that is why we are adding a database and we want the fully functional identity server to be configured but before we actually create user we have to complete the configuration with identity server when we are working with identity server there are few terms that you should be aware of like API scope clients and much more in our identity project let me right click here add a new class file it will be a static class file SD for static details and we will configure all of that right here we go back to the documentation and we have the fundamentals here one thing that we have here is resources and there we have identity resource identity resource is a named group of claims about a user that can be requested using the scope parameter if you remember we were adding multiple claims to identify our user so whatever claims you want you will have to add them to the identity resource if I go back to my project here before we add the identity resource let's assume that in our application we will have two types of roles admin and customer so let me add to constant to hold that now identity resource we know it is a named group of claims that can be requested using a scope parameter so resources will be something that you want to protect with your identity server identity resources are basically data like user ID name email ID of a user and much more so what will happen is an identity resource has a unique name you can assign claim types to that so name will be stored in some claim type and when you access the identity token all of these identity resources will also be provided in order to create that we will have a public static and we want a list of identity resource we will call that identity resources and that is a list on identity resource we are using the built-in identity resources for open ID we have one for email and next one is for profile information there are more defaults here if you want as well like let me show you identity resources that we have address and phone but we will keep things simple we just need the open ID email and profile if you want a custom identity resource that can also be configured let me go back to the documentation here and you can see there is identity resource right here here it is adding the name user claims on what we want in there and a display name but what we are using is a standard scope so there is open ID for that we directly added that standard scope but again as I said before if you want something custom that can always be done as well next what we have is the API scope Scopes are basically an identifier for the resource that the client wants to access in our case client will be the web application because that will be using identity server to retrieve the tokens now there are two types of scope in an identity server one is an identity scope and the next one is resource code identity scope will have an object of the profile itself one example is the profile will have an identity scope and that will include first name last name username and so on we are only using name here so that is what we will be adding in the default identity scope you can see right here it is creating a scope here well it is a static where it is getting the scope and here we have a list of API scope the Scopes that are being added here are read write and delete we just want one scope which will be like Willa API and that is what we will be using so we can copy what we have here let me go back and I will paste it right here rather than get API scope I will call this API scopes let me format this a little bit and right here let me add the scope that we will be using call that as magic and display name will be magic server now based on scope of course you can do some modification that only certain scope can access some of the resources and much more but again we will be using magic here and that will have all the permissions and that is all that we will configure but as you can see there can be different scope for only read permissions write permissions or delete permissions if you want we will only use magic but that is something that can be configured as well now Scopes that we create here will be used by client to access the identity token so the missing entity that we have here is to create a client we go back to the documentation and we have clients right here let me copy the standard syntax to create a client here go back and paste it right here also keep in mind that that can be more than one client or a specific server because a single 10-day server can be used across multiple application now I will be using done day server or identity server but both of them typically means the same thing now clients in an identity server basically means that it is the entity that is requesting tokens from the identity server it can be either for authenticating a user or for accessing a resource example of different clients are like web application mobile application desktop application let's say all the three applications are using a single database for storing all the user then there will be three clients of the same 10 day or identity server right here what we have pasted here it is creating a generic client we can obviously leave that that is not an issue but for our understanding let me create a new client that we will be using for our magic Villa we know this is a list of clients so we can copy this one comma add a new client there client ID let me call that as magic and we need the client Secret here you can have a special secret key but we will use the basic string secret and we will encryptal with sha256 you can obviously add that to your app settings retrieve it here and do all those fancy stuff we will keep things super simple then we have the allowed ground types here you can see the default one is client credentials but we will be using code in our application crime types are basically the flows or protocol flows it specifies on how a client will interact with the token servers next parameter that we have here is critical what are all the allowed scope for this particular client like some client can only have read write delete that we have here we want magic so we can add that here but on top of that if you want to give all of them that's also okay so we have read write and delete based on that you can limit on what a particular client is allowed to do with the Scopes that we have along with that when we are working we need the URL of our main application because basically when the main application will send the request to Identity server for authentication once it is authenticated and authorized the request has to go back to the main application so it has to know what will be the URL for that if we go to our solution Explorer here the web project here and if I open the properties launch settings that is 7002 let me copy that and close it here using that URL we will basically be adding two properties here first will be the redirect URI and next will be the post logout redirect URI now if you have worked with single sign-on or anything this might seem familiar this is the same configuration that we have to do when we configure something on Facebook for single sign-on for redirect Uris we will have the 7002 that is the web project and there we have the sign in open ID connect and for post logout we will say sign out hyphen callback hyphen open ID connect which is oidc post logout basically says once the sign out is successful where should It Go if you make any spelling mistake in here things will not work and you will see an error message with redirect URI so if you see that error message this is where you should come and check if everything is correct now one thing the allowed scope that we have here is Magic read write and delete we are not using that but you can add multiple Scopes like that on top of that when we added the resource here you see we have the open ID connect email and profile we have those identity resource and profile we will use that to retrieve multiple claims as well so when we are actually returning the allowed scope here why don't we add them as well to do that it is super simple right here we have constants so you can basically say something like profile here and that will work but we have constants to avoid the spelling mistake and that is inside the identity server constants at the namespace and there we have the standard Scopes dot open ID connect copy that paste it two more times actually next one that we want is profile and we have email now if you remember we had address and phone as well so those are also available but we will use these three constant if you press F12 here these are nothing but just a constant with the values so pretty basic stuff here so with that our client is looking in great shape now right now what we have done is we have created all the client scope as well as identity resource in the static file but we have not yet configured the identity server to use what we created let me do that in the next video now comes the fun part inside the identity open up program.ces where we added all the events here and we set all of them to be true right now because we're in development later on you can toggle them but when we are adding the identity server we want to add the API resources clients and Scopes that we added right here we will directly use the in-memory API resources and where are those resources that is inside static detail start we have the identity resource now what we have here is identity resource so let me make that its identity resource perfect next we have the in-memory API Scopes that is inside SD dot API Scopes and finally we have the in-memory clients and that is SD dot clients I thought it was clients let me see what I called that and I just called it get here we will change that to be clients perfect we have an error in the API scope here let me see what it is but here we made that as a method here we can use Arrow function here and we do not want the return keyword here and perfect looks good if we go back the adder should go away clients also we have the same thing we just want the arrow function and we don't need the return keyword let me remove the closing bracket here perfect looks much better whoops I think I saw an error there we will have to remove this one and perfect so we have clients we have the API scope and we have the identity resource great we go back and looks good with that we have added the identity server but this identity server we want to use the.net identity that we added right here so to let identity server know that we will be using the dotnet identity we will say dot add ESPN identity and what will be the user we are not using the default identity user we are using application user so we have to explicitly Define that when we are working with the identity server we need some sign in credential for production you will store your key somewhere but for development purpose we can just use the default or rather the developer sign-in credentials that looks good we did quite a few configuration but with that basic configuration for setting up identity server is finally done let me continue from the next video if we open the SQL Server you can see in identity we have asp.net user and asp.net roles but both of these tables are empty to get started what if we want to see our database with two user one for customer role and one for admin role both the rules that we have in static detail we also have to create that role inside the asp.net roles table so we have to seed all of that and let me do that using a DB initializer so right here let me right click add a folder there call that idb initializer in there we will add an interface I will call that IDP initializer and we will add a class there that will implement the idb initializer I will call that DB initializer set the interface we will have one method which is public write and initialize the class here let me implement the idb initializer and implement the interface now inside our identity we have the data application DB context we can use that to toggle the identity tables but when we are working with the built-in.net identity we have user manager and role manager that has lots of helper methods so let me inject all three of them using dependency injection we will get the application DB context at the using statement application user user manager will be on application user and role manager will be on the default role which is identity row perfect looks good then in the initialize method this is not an async method so if we have async methods inside role manager we will have to call the get awaiter.cat result first on the role manager we will say find by name async from our static details we will pass one of the rule which is admin and if the result is null that means that that role does not exist in the database so in that case we will create admin as well as customer role using role manager there is a helper method create async that expects an identity role so it will say new identity role and pass in the constraint that we have for admin and customer they are async method so we will call the get awaitor dot get result in the else part if the rule exists that means that seeding has already been done once so we will just return back simple as that but if that is not being done we are here for the first time let me also create two user first user will be of application user let me call that admin user we will have the username and email both as admin1 at Gmail and we will use the name of Ben let me say pen admin perfect then to create this user on user manager we have the helper method create async where we have to pass the application user and the password that we want for this user it is an async method so we will call get operator.getwizard once the user is created we want to assign this user rule of admin so on user manager we have another helper method add to roll async where we will have to pass the user which is admin user and what role we want to assign it we want to assign that user the role of admin that looks good so with that our user and role will be assigned if we go back to the tables here you can see we have asp.net user claims as well we can add some values to that user claims so what happens is identity will automatically retrieve those claims and pass that along when a user is requested let me create a variable claims 1 on user manager we again have helper method for add claims async there we need to pass the user that is admin user and we have a list of all the claims that we want I am adding two claims here one is name and next is the rule now if you examine these are constants again you can see there are quite a few built-in claims that are available but if you want to add a custom claim you can also do that that is pretty simple let's say you want a custom claim which is for date of birth so you can say dob here and pass the value that you want pretty simple and pretty basic but I'm going to use name and role that will be the two claims that I want we will use the dot result here because it is an async method so that looks good for our application user for admin let me create one more user which will be for customer let me do that right here so we will create a new application user username customer1 at gmail same password assign that the role of customer and when we are adding claims role we have the SD Dot customer so perfect with that the seeding of database looks good but how do we invoke this DB initializer for that we have to do two things here inside identity program.cs we need to add the scoped Lifetime idb initializer and implementation is in DB initializer now previously when we had different startup and program CES file it was pretty easy to invoke that right here but now what we have to do is right here we need to create a method right let me call that see database and there we have to use scope from app.services we have to create a scope and there we have to actually get the service implementation for ITB initializer and on that DB initializer I am invoking the initialize method that is what we have implemented right here so that is something that we have to do because now program.cs and startup.cs are combined together then before we have the user routing we can call the method seed database now let me run the project again and see if the database is actually seated or not when the application starts the seat database was invoked so let me open the database here and perfect we have both the roles here we should have two user as well looks good espnet user rules table will be the mapping table for role and user and we have the asp.net user claims perfect all of that have been added in the correct tables so everything is looking good so far let me continue from the next video now with everything configured let me do some final things before we see identity server in action inside our web project here let me open the app settings.json file there we only have The Villa API but our web project will also use the identity server so let me open the launch settings there and change the localhost to be 7003 then in the service URLs we will add an identity API and we will change that to be localhost 7003 inside the web project we need to modify the program.cs as well we have added the authentication here with cookies default authentication dot authentication scheme right here I can also add one more option which is the default challenge scheme that will be open ID connect so we will have to rather configure multiple options here and the default challenge scheme will be open ID connect now here inside the cookies we have the login and access denied but that will not be needed because everything related to Identity will be done on the 10 day server so we can ignore that for now but this you can also remove it if you want one main section that we want is we have to configure the open ID connect that is the challenge scheme now to do that we will have to install a new get package so manage nougat packages and we will search for open ID connect we have microsoft.asp.netcode.authentication dot openid connect let me install the same version that we are on foreign so I believe what I have to do is let me go we have the package identitymodel.tokens.jwt we can remove that and we can add the open ID connect let me install not that version we are using preview 5 here install that perfect with that configured let me build the web project just to make sure nothing's broken that works here perfect so after the add cookies you can remove that I am leaving that for your reference but we have the add open ID connect now here what will be the challenge scheme that is open ID connect oidc make sure there is no spelling mistake there there we have to configure quite a few options first thing we will be setting the authority so what will be the authority that will give us or Grant the open ID connect tokens and everything that we added inside app settings we have the service URLs and identity API we will retrieve that using Builder dot configuration next we have the get claims from user info endpoint set that to be true because claims will have all the details next we need what is the client ID client secret and response type if you remember that we configured inside static detail client is mango and crime types is code that is what we are using here and the secret we have the plane string as Secret after that we want to retrieve the claims for name and role so an option we will set the token validation parameter name type claim as name and Rule type claim as a rule that will retrieve those two claims that we added in our tables as well right here finally I will add two more configuration add scope of magic and save token and I have a spelling mistake here this will be magic and not mango with that the open ID connect configuration looks good but we will have to make same changes inside the API as well we have the program.cs make sure you are in the program.cs of the Villa API there we were configuring the authentication for JWT better here we can also configure the authority we know the URL is 7003 Port so we will add x dot Authority port number 7003 now we configured authentication in the API we can also configure authorization and add the policy so if we scroll down here we can say builder.services.add authorization we can add a new policy of the name API scope so right here I'm only showing you how to add a policy an option in the authorization you can configure some custom policy like we are giving a name of API scope here and we are saying that this policy requires the user to be authenticated on top of that we require a claim of mango now of course the claims that we have so far are not applicable to this so I will comment this out but you can configure policy and use that for authorization as well for now we will comment that out but I also wanted to show that with that we are only halfway there with the configuration and there are still few things that we have to tweak setting up identity server is not an easy task but we will get there very shortly let me continue from the next video now in our 10 day server if we examine the pages here in account we have login and logout those are the only two that we will work with for now these are razor pages so we will open up the page model for both of them actually let me only work with login for now that way we will not confuse ourselves and if you are examine the code here on the login page it is using the test user store that is the default test user that came when we scaffolded these pages but we wanted to use the.net identity so we will have to change few things here we don't want the test user store we can delete that and we want dependency injection we will have to inject sign in manager user manager role manager and application DB context quite a few things here so I will add four of them here user manager and sign in manager will be on application user perfect let me add that in the Constructor as well here comma perfect looks good we don't want the test user store we will remove that right here we will add four of them perfect we have a mistake here let me see what that is this will be DB perfect now on post we actually need to check if the user ID and password is valid or not if you examine the model here in input model we have username and password and remember login you can also open here index and we have the basic view here where we are asking for username password and we have the buttons so when a user enters and hits the submit button on post Handler will be invoked now these are Razer pages and not MVC if you have no idea about them you can check out my free course on YouTube that will get you up and running with Razer pages but here we need to add the logic on what should happen when the user enters username and password and hits the submit button the first thing here is if a user hits cancel button we don't care about that but if model state is valid we need to check if the username and password are valid right here on the user store it was using validate credentials but we need to use the identity helper method and that is inside sign in manager we have the password sign in async that expects username password remember login and log out on failure we will set that to be false then in the if condition we can say if result dot succeeded that means everything was successful in that case we want to retrieve that user so rather than underscore users we have underscore DB dot we have the application users and there we can use the first our default and we can say here goes to you dot username is equal equal to input dot username we can convert that to be a lowercase to ignore the case sensitivity there perfect that looks good to retrieve the user now once that is done you can see it is raising an event we can do the same we just need to change the parameter username rather than subject we have the user ID and we have username here perfect looks good right here it issues an authentication cookie with subject ID that will be the ID and we have the user name here it looks good now right now it is using the sign in async we do not need that because we are using the method password sign in async if the password is valid this will automatically invoke the sign in async that was invoked right here so that looks good I believe other than that everything else looks good for login next let me open the log out and there is one thing that I want to change there in logout where we have the on post here you can see it is calling the HTTP context DOT sign out async there I want to use the sign in manager to sign out so right here we will inject that on application user and let me add that here as well and if I scroll down to on post here I will say await underscore sign in manager there we have the method sign out async because right now the default pages that were implemented they were not using the dotnet identity they were using test store so we had to make those two changes perfect looks good now we need one last thing in the web project if I examine the auth controller here you can see if someone hits the login page it was taking them to the login page in the web project the web project login and logout pages are no longer needed all of that will be inside the identity server so for now just to test things let me add an authorized keyword here what that means is if a user tries to go to the login page it will be like nope you already have to be logged in so it will automatically redirect you to the schemes that you have defined in program.cs where it knows that hey I have to use open ID connect and this is the authority that is supposed to give me the identity so it will redirect right there let us see that in action for that we will have to set the startup project and we will have to run identity project API and the web project let me run all three of them perfect we have all the three projects up and running here and Dundee looks good and right here let me hit the login perfect you can see it already knows where it had to go it took me to the login page in the Dundee identity server once I enter the user ID and password here it will redirect me back to the correct page but before I do that let me add a debugging point in the auth controller right here and we will run that once again so perfect not here let me try login and let me enter admin1 at gmail and my password was admin123 star hit the enter button perfect now it redirects me back to the same login page we do not want that in that case if everything is successful identity server is authenticated we want to go back to the home page so what I can do is right here I will say redirect to action take me to the index action of Home controller we do not want the login or logout page and same thing when we go to the logout page where is that previously we were using the session token we are not using that now we are using cookies and we have the open ID connect that you can see right here so we will say sign out method that is inside the controller base cookies and we have the open ID connect no spelling mistake there perfect login and logout looks good let me remove this debugging point and run it one more time let me go back here login and let's try to login perfect now even though the user is logged in login and register are still coming up reason behind that is if we go back to the solution Explorer whoops where did that go in there if I go to views we have the underscore layout and share how are we knowing if a user is logged in or not we were using session but now we are using the identity so it is cleaning everything up directly in the user identity we have the is authenticated everything is tightly integrated and we don't need any session let me try this let me click on login here now we see lockout button when we hit log out we have the login and then if you click login again it automatically logs you in you can see it does not take us back to that page what is happening well the reason is once you are logged in if you go back to the Dundee server that is running on Port 7003 and if you refresh here you can see it is already logged in so that way if a request comes in when the identity server already has the identity logged in it will directly pass that and redirect back here but if you log out from the 10-day server here and then if you log out and if you try to log in there you go it will ask you to log in again on the 10 day server so perfect that is something that you should be aware of with that our identity server is working as expected but we need to test quite a few things and make some modifications let me do that from the next video when we were not using the identity server we were examining what was the token that was being passed how can we examine the token that is being passed right here from the identity server that is simple if we go back to the auth controller inside the login here the token will be inside HTTP context with the special name of access token so we can add a variable access token and on HTTP context we will say get token async the special name is access token if you use anything else it will not work so we will make this method async and let me restart add a debugging Point here we will log in here and it hits our debugging point and perfect you can see the token right here let me open JWT dot IO and examine that token great quite a few things here you can see we have the Scopes that we added client ID is Magic sub basically has the user ID but we do not have any custom claims like name what is the role of the user and other details we need to add some configuration to add that to our token let me do that from the next video in the token user we do not have roles or any claims that we added for that we have to do some configuration changes first where we have the static details in the identity project where we are passing the client and all the allowed scope here we want to add one more scope which is for rule and there we have a constant which is JWT claim type slot role that basically has a role we will add that but adding rules and custom claim is kind of a customization that we want to do identity server allows for all the customizations that we want but of course we will have to do some programming for that so here we will have to add a class and I will call that profile service we need to implement the interface I profile service which is inside Dante identity servers.services and there we will Implement that interface here you see we have two methods get profile data async and is active async get profile data will basically load all the profile data that we want on the context here we will have all the entities but from that context we will have to generate claim so in the get profile data we will create a claim based on all the rules or whatever claim we retrieve from the asp.net user claims or the role table so we need to inject few things right here the first two things that we want here is user manager and role manager we know how to get that with dependency injection but on top of that we will have to create a claim right here and for that we will need the iuser queen principle Factory and that will be also on user which is application user so we will inject all three of them using dependency injection and if you remember the token we had something called a subject let me run the application and show that that way it makes more sense I will click login here let me log in we hit our breakpoint let me copy the tokens and I will open JWT paste it here perfect you see we already have something called as SUV which is subject and that is the user ID so that is already there in our context request so in profile service in the context we already have context dot subject and get subject ID that will retrieve the ID now based on the user ID we can retrieve the application user using our user manager there is a method Point by ID async let me make this an async method after that we have to create a claims principle we will press Ctrl dot for the using statement user claims is equal to a weight on the user claims principal Factory we have create async and we will pass the user right there after that we will convert all of the claims that are present here into a list so we will have a list of claims there and then inside the context we have which are all the requested claim so we only want the claims that are requested so we can say claims is equal to claims.where and there we can say U goes to on the context we have something called as a requested claim types if that contains U DOT type then we filter that and we convert that to a new list so that will filter out the claims now on top of that we want to add custom claim if you remember we have the name and we want to add role as well to add something on this claims it is simple we have a list here so claim dot add and it will be a new claim there we basically need a type and a value if you examine our static details and if we scroll down you can see we had the JWT claim type dot row but if you examine where we see that the database in DB initializer we had two of them JWT claim type dot name let me add that so we go back we will paste that as a type here and what will be the value that value will be inside user we have dot name perfect that looks good then we will check if user manager dot if it supports a rule or not so we have supports user role if roles are supported then we want to add that claim as well first we will retrieve all the rules for that user using user manager we have the get rules async that will retrieve all the rules because it is possible that a user has more than one role so we will have a for each for each rule name in rows we will be adding a new claim of jwd claim type start role and we have the role name lastly we have to implement his active async and right here we will retrieve the subject and we will retrieve the user using the user manager let me add a Sync here and based on that user we will set the is active flag that is pretty straightforward one last thing that is missing here is we have added all the claims right here but then before we move forward we will have to append that to this context request so we will say context dot issued claims and we will append the claims that we configured you can be super fancy here and you can add more claims custom claims or whatever you want based on your requirement but this will be invoked because we are implementing the profile service that is in the done day identity server then we need to register this in program.cs this is Magic web we want the program.cs of the identity let me open that right here and we will say builder.services.adscoped I profile service and profile service and since we have a custom implementation of profile service we have to tell identity server about that as well so right here we will say dot Add profile service and the custom implementation is profile service if you run it this way it will not work because we need to add the scoped implementation after we register that on the identity server that is critical so make sure to add this I profile service after the add identity server where you have defined the custom implementation of the profile service with that configured let me run this one more time here let's see if it works this time we will log out here let me go to the 10-day server and log out as well and we will log in perfect let me examine the token this time copy this we will go back to JWT JWT dot IO and paste it here perfect this time we have the name as well as a rule being populated so that is working as expected now of course if we go back to our application let me continue here and if you remember the Villa number create still does not work so something is not valid I believe let me go back and try to see what role is required so in the API here will a number where we have the create Villa where is that the rule is admin why is that not working will a create Villa you are not authorized for this page and yep we did forget one thing I want you to pause the video and try to see if you are able to figure out what is going on wrong we are missing one piece when we are calling the API let me show you that in the next video if you remember inside our token we already have a role but in our web application basically it is not able to determine or rather able to map that claim type so in the program.cs of the web application we have to explicitly Define that in the open ID connect so right here on options we will say claim actions we just need to map the Json key of role to role that way it will do the mapping and the role that we have in claim type that will actually be mapped to the open ID connect role let me run and check that out we will go back here login again and if you are already logged in make sure to log out and log in once again if we try to create Villa here perfect that page is loading but if you actually try to create the villain number this will again not work we press something hit create and exception is thrown here the response here is no now of course you can add more debugging here to make sure that it does not throw an exception but why is the response null pause the video and try to analyze that as well if you said the answer is token is invalid that is correct well rather the token that we are passing right now that does not even exist in auth controller now our token is inside the get token async we have access token that is what we will have to use when we are calling the API now so let me close all the tabs here home controller and Villa controller where we are passing the token we need to replace all of this Ctrl shift F we don't have the SD dot string token we will replace that with HTTP context dot get token async I only want to work on the current project replace all perfect that is done we have the get token async here add the using statement we scroll down foreign looks good and then where we have the base service add a debugging Point here and let's make sure that token is present in the request we have an error there let me see what that is perfect let me run it once again hit continue here let me log in foreign let me see in the API request do we have a token yes we do continue and try to create a villa number I can remove that debugging point now hit create there and perfect that is created we can delete that perfect so all the crud operations are working now because we are working with admin role and that is exactly what we have in our API endpoints if you scroll down here you can see the rule is admin so with that we have replaced everything with Dante identity server now there are a couple of things remaining there let me do that in the next video let me run the application again and if we go to our website go on the login page right here you see we have login and cancel if we select cancel here it takes us to an exception page rather than an exception on this page we can see in the web application that if there are any exception in the identity we want it to redirect back in our web application we have program.ces where we have the open ID connect right here we can configure some events right here so option dot events is equal to new open ID connect events let me add the using statement here and inside there we have the on remote failure we can set many of the custom events right here but here we will use the arrow function we will get the context object here on that context we have response dot redirect we wanted to redirect to the home page we will add context dot handle response and from there we will return task Dot from result the zeroth one basically we are overriding the event on if there are any failures on the remote side with that let me run the application once again let me log in here and hit the cancel button great you can see now it redirects us back to the main application but the main question is when we go to login and if we hit cancel why do we get an exception for that let me go back to the project and inside the identity project we will open up index.cshtml.ces and we will add a debugging Point inside the on post to examine what happens we will hit the cancel button we get on the on post here we should go inside the button is not login that is great and then we go to return redirect and we have a return URL we can directly redirect back to this redirect URI if that is not successful but right now we have handled that exception and it is taking us back to the home page but if you want to be fancy you can modify things right here inside the identity project perfect with that let me continue from the next video now if we run the application our login functionality is working as expected but I have one question we are using the seed users that we created with DB initializer what if we want to register a new user on the login page we need to add a link to a registration page now that page is not present by default in the UI templates we can see that in identity where are the pages we have login and logout but we can of course create those pages doing that is super simple in account we will be adding a new folder let me call that register Now by default the identity is Razer pages so if you are not familiar with how Razer Pages work what is the post Handler get Handler and so on I have a free course on YouTube that you can find on.net Mastery free content so in the register we will right click add a new Razer page we will go with the empty Razer page and we will call that index.cs HTML if we examine what we have inside login we have the same flow here and that is what we will use typically in MVC application we have models views and controller but here we have the UI which is index.cshtml and we have the CES file where we have page model there we have the on get and on post Handler similar to what we had inside the login page as you can see here now the login page had some dependency injection with identity provider scheme but we will keep things super simple when we work with register first thing first we need the view model for our register so inside the registration or inside the register folder we will create a new class I will call that register viewmodel what will be all the properties when a user tries to register we want to add five properties first is email name and password that is pretty self-explanatory on top of that we need a return URL if in case we want to redirect back to the URL that originated the request and finally we will also have a role name here on what role should be assigned to the user so that looks good for our view model the last thing that I want to do in this video is in our main web project views if we go to underscore layout we had login and register I do not want the register URL right there I rather want to add that URL inside the login page so inside login we have index.cshtml right here let me remove this div and local account we will rename that to be login then from this login page we need a link to the register page so let me add that link right here before the buttons we will be using anchor tag and then the tag helper we will be using ASP page because we are working on Grazer Pages if it was an MVC application we would use something like ASP controller or ASP action now you might be saying that hey this is actually an MVC application and that is right but if we take a look at program.cs where we have added the controllers with view for MVC we have also configured Razer Pages for identity so both of them will be valid but when we are working with the pages here these are Razer Pages that's why we will use ASP page and what will be the URL if you think about that from this index page we have to go to one level up to the account folder and in there we have register and then index so we will say dot dot forward slash to go back one folder up now we are in the account folder what is the route to the index page of register from there so for that we have to go in the register folder and we have index.cshtml in there when we navigate to the registration page if there is any return URL we should pass that as a route parameter so ASP route let me call that return URL is equal to we have that inside model dot input dot return URL perfect now within the anchor tag here we will display new user and then register like that let me also add a breakpoint after that perfect let me run the project and see if we are able to redirect we will go to login here perfect we have the new user register when we click there you can see it is not working and there is a very good reason behind that now this is something that is a little tricky to debug so I will show you what the issue is it is going to the correct page and everything is working but if we go down here and if I open the program.cs we have added the Razer pages but if we scroll down where we have added map.reser Pages we have said that all the Razer Pages requires the user to be authorized because of that if a user is not authorized they will not be able to go to the register page we do not want that so we will remove this and then let me restart the application if we go back to login new user register perfect now it is able to open account forward slash register and we also have the return URL right here so with that we have added the register page and in the next video we need to add the view to capture name email phone number and the role user wants to be registered as let me do that from the next video now we need to work on the register page here if I stop the application and open the index.cshtml we are inside the register here we need to add few properties using dependency injection we have helper methods with user manager sign-in manager and role manager so we will be injecting them but before that we need the viewmodel view model for register is the register view model we will create a property and I will use bind property when we use Point Property the advantages if we are posting here typically we have to get the register view model like that but if the property is pointed with Razer Pages this will automatically be populated when a post request is submitted now again that is little bit detailed about Razer pages so if you are not familiar with that you can of course take the free course on YouTube but we will add the bind property for our view model next we need to add dependency injection for user manager sign in manager and role manager the T user for sign in manager and user manager is application user so make sure to add the using statement then next we have the on get Handler this will be invoked when the page is being loaded so when a page is being displayed we need the drop down on the page to be populated drop down will be a drop down that contains all the roles of our application so let me create a list of string call that as a roles and we will add admin and customer in there those are the rules that we have created if you scroll down right here we have admin and customer so rather than magic string gear we can use our static D2 dot admin and static details Dot customer after that we can store this in a view data with the name of roles message when we are working with Razer pages viewpack does not work so we will be using view data and on the UI index.cshtml here we will retrieve that view data and display a drop down for the rules of our website after that the input here will be a register view model let's create a new object and we want to populate the return URL if you examine the index for login where is that right here on the register we are passing a return URL so let me close that and here we will retrieve that string written URL as a parameter and we will populate the returned URL in our register viewmodel it looks good everything is populated we will return back to the page so we will say return page and that looks good rather than white here we will have async task of I action result great that looks good for the cat Handler with that configured we can now work on The View which is index.cs HTML here the model is already defined that is index model and if you go here that will be the index model that we have right here so in there if we have any properties we can directly access them inside the Razer code here we will retrieve the rule list that we added to view data and here make sure the key name is same that we have added which is roles message and then we will convert that to list of string we have that in a local variable that we will use very soon then let me add a div and on this page we want to use the validation so we will use partial name validation summary that we already have in shared folder inside pages inside that div we will be adding quite a few div for Designing purpose we have row then we have some bootstrap classes we will add a div of class card card header which will be H2 of register and after the header we need the main div which will have a class of colored body inside the card body we will add a form tag and here we need all the input fields first thing we will need the return URL as the hidden property so let me type that then inside div with a class of form group we will have label for input dot email and we will use the asp4 input dot email that looks straight forward let me copy that paste it one more time this input is directly accessible here because we have added the point property and if you examine the model here it is index model in that class we have the property so because of asp4 it is accessible another way of accessing that is in model you will have input dot email if this was not asb4 then add model will be needed but with tag helper that is implied next we need the name here let me modify that placeholder will be name asp4 will be name as well copy and paste that one more time we need input.password set the input type will be password Here class form control placeholder to change that to be password asp4 will be input dot password then after password let me copy that one more time the final one that we need is for the drop down which is input dot we have the role name the type will not be password here this will be a select list so let me add select and asp4 that will be input.roll name but where will be all the list that we want that is inside the roll list variable right here let me give this a class of form control as well and we need ASB items for that item we need to create new selected list and that list is inside the variable row list because we have added the add sign here we can directly access row list in there finally we need the pattern for register so let me add that we will add button class of etn BTN primary name button value register and we will have register in there after that in the card footer called body ends here we will add a card footer there and inside there we will add a link to go back to the login page if user wants that perfect that looks good let me run the application and see if the UI is rendered correctly we will go to login here register and great this looks much better inside the role we have both admin and customer now what I can do is this is left align let me make it consistent with what we have so I will copy this div here from our register and let me open the login index we will replace it with this column small 6 and let me restart we log in here perfect that looks good but now if we click on login you will see an error message return URL field is required that is because we are not passing that when we are returning back we can do that as well if we go down here not here inside the register we can have ASP route return URL is equal to and this will be inside model dot input dot return URL and let me run it one more time website closed that accidentally I will have to restart and we go to login register if we go back that is functional if you do not want to manage all of that you can close that and in identity we can click edit project file and we can remove this nullable that is enabled by default once you remove that from the project file we do not have to worry about defining the nullables so make sure you clean that as well with that if we run the application our register page is getting loaded so the on get Handler is working as expected the last thing that we have to work on is when the user hits the register button we need to create that user let me do that from the next video now we just have to work on the register index page model here and we have to add the on post Handler method so let me paste the on get here and this will be on post let me remove everything else here first we will check if model state is valid so if the model state is valid only then we proceed further insert register we need to create a variable user is equal to new application user and we need to convert all the properties to application user from our register view model for properties that we want is username email email confirmed and name we are setting the email confirmed to be true but username and email will be the same then in order to create user on user manager we have create async where we are passing user and we need to pass the password that is inside input dot password we will have to wait for the result here so let's add that once we get the result here we will check if result dot succeeded that means the user was created with the password that is provided right here after the user is created we have to assign role to that user but as a matter of precaution we can check if the rule exists or not so we can check here using role manager dot we have the rule access async and we will pass the role name that is an async method so we will have to call the get awaiter.getwizard if the rule does not exist then we actually have to create the role now right now the rules are already created so this will not be invoked but I want to show you that you can add extra precaution to make sure the rule gets created before it is assigned to create that we first need to create a new identity Rule and populate neem normalized name and we can use role manager dot create async pass the user role that will make sure if the rule does not exist it will create that and then we can assign user the role that has been selected using user manager dot add to role async where we have to pass the user and the role that needs to be assigned straightforward and we have seen that before but now we also need to add claims so if we go to our DB initializer right here we were assigning claims I can copy this go back here and paste that we will have to await but on user manager we have the add claims async here we need the user object we will pass that and what are all the claims that needs to be assigned for name we will be using input dot email let me remove this dot result that is the reason for the squidly lines along with name we can also add an input plane type of email keep that as email now of course you can change this from input dot email to name whatever you want based on your business requirement I will not go into much details but whatever claim you want even if you want a custom claim you can Implement that as well we will be using these three where we have input name and role rather than sd.admin we have that inside input dot row name perfect it looks good and then we can sign in that user in our application for that we can create a variable login result and we can use sign in manager we have a helper method password sign in async there we have to provide username which is email password which is inside input.password is persistent we can set that to be false and lockout on failure we can set that to be true once we call the password sign anything we can see the result so login result dot succeeded that means the sign in was successful in that case we will add if else condition if URL dot is local URL the redirect one then we will use redirect input dot return URL if that is null or empty we redirect back to the home page else we will throw an exception invalid return URL perfect that looks good let me go to the view for register right here where we have the form tag I will also add ASP route to register if you do not add that then the on post will not be invoked let me add a debugging Point here and run the application to see if that works so I will go to login here register a new user call that as admin5 what about say admin 5 password I will keep it the same admin123 star role name will be admin perfect now right here if you notice we do not have any register view model but this input model should be populated great you can see everything is populated correctly here let's debug this create async was successful let me open SQL Server here and I'll have to connect again magic Villa identity asp.net users perfect we have the admin 5 right here ASP Network rules we have admin and customer at asp.net user role we have five records a new one should be created shortly let's continue and that should create this extra record here looks good we will create the claims here and we will try to sign in result is successful it is a local redirect the let's continue and perfect you can see it brings us back to the page and the user is logged in so great with that we have the login and registration successful with 10 day server now with the done day server you can Implement more pages like forgot password and all the other Pages if you want also if I log out here from the 10-day server and if I log out try to log in here the layout of this page you can make it consistent based on your website that is straightforward as well if we go here inside Pages shared we have underscore layout you can make it exactly same with the theme of your website that way it will look like a seamless process but I will not go into those details right now we have both login and registration functional with the Dundee server I hope you guys have enjoyed the free video for more free content you can always go to dotnet masterway.com and there I have free content if you are a.net Developer and you do not know where to start I also have a dotnet Mastery path where I show you what should be all the content that you should take to master all the topics as a.net developer if you enjoyed the video leave a comment and like the video for more free content make sure you subscribe to the channel That way you do not miss the new content that I always upload I hope to see you guys again in some other coding video till then Happy coding [Music]
Info
Channel: DotNetMastery
Views: 21,186
Rating: undefined out of 5
Keywords:
Id: ScapopQurI8
Channel Id: undefined
Length: 106min 33sec (6393 seconds)
Published: Sun Aug 28 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.