ASP.NET Core Authentication Simplified | .NET Conf 2023

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] all right I am so excited to be here to share what our team has been working hard on over the past year to simplify the authentication experience I'm a product manager on net web backends and I'm here with Stefan hi yep and I'm an engineer on asp.net whove recently been working on Blazer and off awesome so I'm going to jump right in and talk about what we've done here so this is not the only reason we decided to look at o but it's a very visible issue it's by far the most upvoted issue in our repo and the question is about better options for authentication now authentication has a lot of different flavors and so we weren't able to tackle every single permutation but I do want to talk about the two obvious things that that we discussed one is the idea of a full oath 2 oidc server I know that's a big request and and the team looked at this and it's such a large undertaking and there's so many options that are already out there we've got paid Solutions like our own Microsoft intra or the DND solution with identity server and there's also free and open source solutions for this like keycloak and open idict and so what we decided to do was focus on these projects that use the aspet core identity that's built in it's a large set of projects and it really is for dealing with that scenario when a developer has a single app that maybe has a mobile or a desktop client and doesn't want the overhead or complexity of configuring the server so we proposed this we got some feedback on it and what we created was this set of identity apis and these apis are designed out of the box with data transfer objects to make it straightforward for you to build those identity pieces in your single page applications and Blazer web assembly applications that require a user to register and log in and perform those basic identity tasks now the full identity system is still there and available on the server side these are a new set of apis that we expose for consumption by clients and I just want to point out and we'll see this in the examples that these also provide things like validation feedback with problem details in the responses so you can programmatically parse what's going on and uh display that result so what I want to do is just jump right into some code and show you what it looks like with these apis to secure a web API endpoint and then I'm also going to look at consuming it from an angular and a blazer web assembly client and then I'll turn it over to Stefan so let's pop over to visual studio and so what I've done here is I've just created a basic open uh sorry a basic ASP net core web API this has that default weather forecast example that's built into it and I'm going to open up the project file to show you two packages I'm going to add identity is actually built into aspnet core but if I want to opt into the features I'm going to show you where we're using Entity framework core to maintain all the data for the users we're going to add two packages and one of those is the identity Entity framework core that's sort of the glue that marries the two pieces together and then the other is the implementation of V framework core what database do you want to use SQL Server SQL light another relational database so you have to choose that provider because I want to limit the amount of time I spend on this I'm using the in-memory provider which is there for demos it's not there for production use but we're going to open up the the program.cs and this is the default code that is uh generated and we're going to go down to the bottom and I'm just going to add what's called a DB context and this just tells in framework core what we expect from the database that it's going to model and and interface for us and I'm inheriting from a built-in identity database now you can customize the identity user and you can customize the database so we you these hooks but I'm just going to plug into the default out of the box and override the Constructor so that I can configure some options for that so let's uh take that class and now we're going to pop up to the top and I'm really going to add just three little sections here so the first one tells me that I want to use authorization the second one configures that DB context that I just set up and the third one is actually activ ating the identity API endpoints so we're basically opting into exposing those endpoints and it also does a lot behind the scenes for configuring support for both tokens and cookies and we'll see that in a second now if I pop back to the bottom there's just two more things I'm going to do in this simple application I'm going to require authorization on that endpoint so that we've secured that uh API and I'm also going to expose those endpoints so we activated them earlier but we need to Route them and map identity API actually Maps them so that they're available so now if I hit F5 and build and I'm going to spare you waiting for the build to go through we pop up on our Swagger UI screen now because I'm in development mode and uh debugging the application it's showing me this UI that has introspected my apis and given me definition so I can expand the weather forecast definition for example and see exactly what's expected from this API both input and output and then I've got this lovely try it out button that I can click and that gives me this execute so if I had parameters I would set my parameters in this case I'm just going to click execute and because I secured that endpoint what I'm getting is this 401 response that's telling me I'm not authorized to the endpoint so how do we as a client application get that authentication set up first thing I'm going to do is go over to the register inpoint now this inpoint defines really just two parameters right the email and the password of the user so what I can do is click that try it out button and put in my super complex password right here and click execute and what it's going to do is come back and give me a list of validation issues and this can change it's completely configurable based on the password policy that you follow so I'm going to come back and give it a better password which has non-alpha digits and uh capital letters and everything else and this time I get a 200 okay so I'm registered in the system so I should be able to log in we'll walk over to the login piece and you'll notice that we've got a couple query string parameters that we can pass as well as a schema for what we're going to send in the body I'm not going to cover two factors so I'm going to ignore those parameters and I'm also not going to talk about session cookies right now the important thing for me is that I set use cookies to true that's our default experience that's the most secure way to use this built-in identity system and then I'm going to put my email and password in the body just the same way I registered them so I click execute and I get that nice 200 Response Code and because I'm using cookies there shouldn't be any other work for me to to pop back over to our weather forecast API and I'm going to go ahead and open up my network settings so you can see what happens on the wire and when I click submit I actually get a response body this time which is great I get that nice 200 code and I get results back so it's recognized I'm authenticated and if we look over at the network side you can see it's sent a cookie inside of of that uh request now let's say that you have a client that for whatever reason can't support cookies we do provide a proprietary token that basically I just say use cookies equals false or I don't even set that parameter and by default we'll generate a set of tokens and there's an access token that you can use for authentication and there's a refresh token that will allow you to extend the session without forcing the user to log in again and if we look at the way those are used this is a the new http P format that you can run web reest from within your browser and you'll notice that I simply set that header and pass the token in the header to make that that pass now let's say I have an angular client how would I consume this in the client here's a simple client this is in our samples by the way so you're able to view the source code for this today and when I click on that weather forecast I've set it to redirect to signin so let's zoom in and actually register so that we can access this application I'm going to give it a bad password at first so you can see my angular client has parsed the validation errors and displayed them they came from the server now I'm going to log in successfully and finally I get my weather forecast and notice that my sign-in button has changed to a sign out button and then I can log out so if we look at the code real briefly I know not everyone's an angular developer but I've built an authentication Service that the angular app can can use and if we look at the login piece the key here is that I'm using the cookies and if I have a successful login or not I raise an event to notify the rest of the application that my authentication status has changed so it knows if I've signed in or signed out now because of that and the things that rely on that service I can create something called an offguard which an angular basically establishes whether a route can be navigated to or not and so this case I'm not only saying that you have to be signed in if you're using the offard but I'm redirecting you to the signin page if you're not and using that offard is as simple as just adding this can activate property on your route definition and then finally when we get the weather forecast we have to do one small thing in the angular application and that's make sure that it sends their credentials because it doesn't do it by default now you can use something called an Interceptor to override this and make that the default behavior for everything so in our Blazer web assembly Blazer web assembly has a built-in set of uh components that work with authentication regardless of the type of authentication you're using so to use the new identity apis I basically just customized something called the authentication State provider you'll see that in my login it looks a lot like the angular service I'm basically on success raising an event to note that it changed and then in that request that ask for my authentication state I'm calling an inpoint that's authorized so if I'm not logged in this is going to fail if I am logged in I can build a a set of claims based on the users's identity and authenticate them this is all activated throughout the app using this cascading authentication state that I wrap in the app. Riser and then I have this authorized route View and this just makes the authentication work so that when the events fire all of your components update and then you can do the simple I'm going to protect this with authorized so if they're not signed in they can't access it and you can also use a view that allows you to specify a different fragment of UI based on whether they're authorized or not authorized so that's a more flexible way if you don't want to block access to that entire component and then here's the sample app if I log in with a bad well I'm trying to register with a bad password you can see that's also parsing the results and then there I am completely logged in now that was just a very simple example of what's uh possible but we've done a lot with the Blazer web assembly I'm sorry with the Blazer web app template and Stefan is going to walk you through all the new changes with a brand new blazer identity UI that we have and I'm going to turn it over to Stefan well thank you Jeremy U that was a great demo from the past uh you know I've been working on things like c signal and I got to work a lot on this map identity API and I've been thrilled to see the feedback people like being able to submit Jason requests and not have to deal with antiforgery and tokens and stuff and uh I like how you called it a proprietary token that sounds fancy um but you know I like to call it opaque it's encrypted can't read it on the client but you can do what Jeremy did and then use the with credentials to make sure the cookie gets to the server and the server can tell you whatever you want and um after I worked on map identity API like Jeremy said I worked on the formerly known as Blazer United template to add off to it so if we want to look at this we got uh just released um update to visual studio 2022 with all the net 8 goodness and we're going to do the Blazer web app template which I'm sure you saw a lot of yesterday if not please go back and watch it um and there's some great demos so um while this is an authentication simplified talk I'm going to make this as complicated as possible by choosing the auto interactive mode so this means that we have web assembly rendering server interactive rendering with a circuit and server pre-rendering and all of these need to be able to get this Authentication state that Jeremy was talking about earlier so the question is what's the best way to do that so I'm going to like a cooking show take this pre-baked template out of the oven and I will show you um what we have going on um so I made a few edits to this um that I commented out um just to show you how you can modify this template but otherwise it's pretty basic um and compared to the U normal non- authentication template that the biggest thing you're going to notice is that you have this account folder um and this defines all of the identity related raiser components um like login register um allows you to manage your account change email things of that nature um but to support this we did a bunch of things um so we added cascading authentication State um this is just another way to do what Jeremy showed you earlier with a tag we can also put this in our program CS um since we chose the auto interactivity mode we have both a server and client project if you watched Steve's demo yesterday you will have learned that the client components like this off required component can run on the server during pre-rendering and also rendered interactivity via web assembly or server interactivity um so maybe this should have been called a DOT everywhere assembly um or do everyware project but it's really important to know this um just because say this is from the client project doesn't mean this component is solely rendered via web assembly so this leads to the question of what's the best way to authenticate this historically with Spa applications you only have to authenticate on the client side um and because you don't have to pre-render sensitive data um but if you do want to be able to pre-render data that only an authenticated user can see you basically are forced to use cookies right because that's the only thing the only credential a browser is going to send uh Norm I mean there are like certain flows and so forth but we're not going to focus on that um so that's exactly what we'll do a lot of things are going to seem familiar with this template compared to what you just saw with that map identity API uh sample this is individual off so it's using aspet core identity we're registering our DB context uh which gives us our EF identity Stores um and we have this application user which you can then add custom property to um and then um furthermore by default we require that you have a confirmed email account so to help with that um we showed you how you can register an I email sender this is New Inn 8 the generic I email sender of application user so this means that any properties that you add to your type you can now access as you're sending people confirmation emails so if you want to include any extra information you have about that user um in your email that is not possible um so that's exciting we're using cookies on the server um but what about the web assembly rendering how how are we handling that does the client have to authenticate separately doing somewhat like oidc flow um we decided not to do that we are doing something simpler so first we have the authentication State provider which we're adding to the DI container in the server project um so this is a lot like the cookie authentication state provider you saw before in the WM project but this is running on the server um and it's using persistent component state to take the authentication state from the server um and then transfer that to the client via a user info option so since we choose interactivity Auto um sometimes there is a signal R circuit that can be long running so if you'd ever run the individual off with the Blazer server in previous net release you might have seen this um validate security stamp logic so that means that you know if someone say changes their password while someone is still um connected in you know another browser session this will log you out as it sees the security stamp changes and by default you know it's checking that every 30 minutes but perhaps the more interesting thing is that we have this onp persisting function which takes the authentication state on the server um which we hook VI authentication State changed and then we persist that as Jason using user info so to be clear here we do not take your entire claims principle and serialize this this is all in your um Blazer project from the template so if you want more information available in the client claims principle via the client authentication State you will need to add that to this user like Poco that we're serializing as Jason so this is one half so this is already uh exposing the authentication state to um the server um most of the implementation is here in this framework defined um revalidating authentication State provider which then um you know hooks the um normal authentication events on the server so if you have authentic iated your app the way you've authenticated a typical razor Pages or MVC app um you will have uh that authentication State available to your server side bler component but then when we take that to your client side Blazer component you have another authentication State provider so one thing to note is that on the server we do not have uh any client side rendering of any of these account components so since they're accessing what's known as the user manager so if you're to take a look at like login. riser for instance where you know uh injecting the signin manager which uh is associated with the user manager and all of these services that are available at identity are only available on the server um so so we render that there um but um once we transition from uh pre-rendering to the client um we also use uh persistent component state to then um read so you see we have that as a Constructor parameter that's dependency injected so we read that same user info that we wrote on the server and we configure this authentication State pass that we then make available to you things like the authorized View and stuff for rendering so without further Ado we have an app we're going to just do a quick register there are minimum password requirements like Jeremy told you earlier it's more or less the same um you'll see that you have to confirm your email account um since that was something that we opted into on the server um when we set up at identity cor so that's part of the template um if you look at the register confirmation razor you'll see that we are um rent rendering a link um to configure your account only if you haven't configured a new email sender so um that's what we're going to use right here we're just going to click that link that's the same link that would have been emailed and then we can now log in um and that's exciting what we can also do is with the did I MPE my password I hope yes and now yes I'm logged in test. example.com on the off required page test example exciting um if you want to look in the um you know F12 browser tools and we refresh and we look at the console you'll see that we have uh transferred um to web assembly rendering so there's a pre-rendering stuff and then it got rendered and web assembly and the same user still there that's very exciting um and then so what if I want to be able to use an external login right um I already am using Microsoft arra or whatever I kind of gave it away early when I showed this common. code I used user secrets to already configure the client ID and the client secret um I'm running this from here so I'll just restart it after making those changes and you'll notice that with just adding this call to add Microsoft account on the server project and then we did also add a new get reference we should if all goes according to plan um be able to link um external log to our account so we have this Microsoft thing um the same is true you can log in directly with the Microsoft account and then it will have you basically create an account um while you log in for the first time so here we have it set up um I did the portal things um I I'll use my corporate account and instead of being test. example.com hopefully now um I'm still test. example.com um but uh link to Microsoft and if I wanted to have a Microsoft login specifically um that works too um but it sees that I'm Associated already so um I think we're running kind of low on time how much time do we have left sorry should all right well um that's mostly what I wanted to show um we also support tofa I had I had a little something exciting to show there with uh setting up a I'm using net um or it used to be active now it's a polyglot notebook to act as like the fake QR code authenticator app on your phone but we got that too um so all sorts of features um and so is it time for questions
Info
Channel: dotnet
Views: 32,132
Rating: undefined out of 5
Keywords: .NET
Id: c__Sf9j_Q2Y
Channel Id: undefined
Length: 24min 47sec (1487 seconds)
Published: Fri Nov 17 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.