Creating your First IdentityServer4 Solution

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi and welcome to this talk on getting started with identity server 4. my name is kevin jones from rock solid knowledge so in this talk we'll show how to install identity server but we'll do it using an in-memory store just to keep things simple initially we'll write an api client that we can use with identity server that will need protecting and we'll write a web client where the user can log on we'll also have that web client called the protected api and we'll show how to tie all of these together now this talk is part of a series of talks and in the other talks we'll see how to update identity server to use entity framework stores rather than the in memory stores we'll also update identity server to use the asp.net identity but it's user store and those two topics will be covered in one tool we'll then have a talk on hosting identity server on azure and then finally a talk on adding admin ui to this instance of identity server that is hosted on azure okay so let's move on to installing identity server using in-memory stores so the simplest way to create an identity server instance is to use a.net template to do that we first have to install the.net templates to do that we run dot net new minus i identity server 4 dot templates and here we can see the templates that have been installed and we can see that are things like is4 in mem is4 ef so if i run dot net new is4 in mem this creates me an instance of identity server as it says here with in-memory stores and test users however we aren't going to do this as we want to understand exactly what's needed when we create an instance of identity server instead we're going to start from scratch so here i'm in a new directory called ids and from here i'm going to do net new web and this will create me an empty web project based on net core and if i look in this directory we can see there's not a lot to this we have a program cs startup cs and a project file so let's go and open that project file and add the things that we need to make this an instance of identity server okay so here i've created a new solution using jet branch rider and into this i've added our project simply called ids as we can see we just have a program cs file and a startup cs file in here and nothing else the only thing i've changed here is that in launchsettings.json i've changed the ports to be running on so this project will run on port 5443 for https and 5000 if we were using http so the first thing i need to do here is go to manage nuget packages and add the identity server 4 package to this project and then when i've done that if i go into startup.cs it's here that i'm going to configure identity server so in my configure services call i call services.add identity server and then here i'm going to tell identity server where to find things like its clients and its resources that we'll use when we do our authentication so initially to set this up i'm just going to add these calls so we add a list of in-memory clients that's currently empty similarly a list of in-memory identity resources api resources and scopes and also an empty set of test users and we'll come back and add data to these in a moment i'm also going to call add developer sign-in credential here we do this because various things in the tokens that identity server delivers for us needs to be signed and this developer signing credential provides that signing material for us once i have that in my configure call we can add identity server into the pipeline so remember the identity server is a piece of middleware so here i can call app.use identity server and we're now ready to go now at the moment we have no apis defined we have no clients defined and we have no users defined but we can still run this so we run it and the application runs at the moment we have no controllers and viewers here so it's simply printing out hello world but in here i can ask identity server for the open id connect discovery document and we get to that by going to dot well known open id configuration and indeed we get the discovery document there's some defaults in here so we get some default grant types and default response types but notice for example there are no claims here yet and the only supported scope is offline access so let's fix that for this in-memory setup so before we go any further and add things like clients and resources what about these credentials so here we called add developer sign-in credential so what does that mean well if i go and look at the identity server documentation there's a section here on key material i'll notice it says that for add developer sign-in credential this is for dev scenarios only and it says as for when we don't have a certificate to use instead we should be calling add sign-in credential or add validation key and for things like add citing credential we provide an x509 certificate to use to provide our own signing material so be aware this is for demo purposes only okay so with that out of the way what are these things that we have here called clients and resources so before we get into the detail of these let me show you the clients and resources we're going to add here so i mentioned earlier that you can create an instance of identity server from a template and that template provides some data that's used to populate these values i'm just going to use that data in this demonstration so i have a file called config.cs that i'll copy into the project and then in here we have a few things that we're going to use so first of all users so users are obviously going to be users of our applications and here we have two one called alice and one called bob and then further down here we have a couple of clients so these are the client applications we'll be talking to identity server to be asked to be allowed to use our applications and here we have two we have an mtm client that's machine to machine that's an api client and we have our interactive client so that's essentially our web client and there's some configuration associated with both of these things we also have some resources and scopes so the resource is something that we're trying to protect so here we have an api resource that's called weather api that has two scopes associated with it whether api dot read and where the api dot right so obviously this means there's something that can read from the weather api and something that can update the weather api add update or delete items using this api and we also have some identity resources as well and these are things associated with a given identity so the first two identity resources here open id and profile represent some standard open id connect scopes that we want identity server to support and the open id scope for example is always required if we're using open id so given that we have these resources and scopes and clients and users how do we use them so in my code here rather than providing an empty list of clients we're going to say config.clients and this is a static property within that config class i can enter the same thing for the resources and the scopes and for the test users so let me update those now so now we've added our identity resources api resources api scopes and the test users so if i rerun identity server and go back to the browser and refresh we can now see the various scopes and claims have been added to our discovery document okay so now that we have this how do we use it so the way an application would use this is that it would request a token from identity server and then use that token to communicate with our api for example so if i look in our config file here we have a couple of clients and what we're going to use first of all is this m to m client so notice the client has an id which is m to m client and it has this thing called a secret and when we add the secret into identity server we hash it so the secret is not very secret it's super secret password but it's stored in identity server as a hash so the client knows this value and uses this value and its id to ask identity server for a token and the way we do that is something like this this is a curl command we'll use as an example so we're going to send an http post to our endpoint which is localhost 5443 but the connect token endpoint to request the token we specify the client id which is m to m dot client we specify the client secret which is super secret password and we specify the scope that we want to use which is where the api dot read and we also specify the what's called a grant type if in this case we're saying i'm a client and please provide me a token for that client so if i take this command and go to my shell and paste it in and send it to my identity server indeed we get back a token so we get about this json object that contains an access token and this is the value of the access token and we'll see what our value is in a moment we also get back some other information as well so it tells us how long this token lives it tells us the token type and this is known as a bearer token and it confirms the scopes that we've asked for so in this case where the api dot read so this token is known as a json web token or a jot a jwt and if i take this token and copy the value there are a couple of websites i can go to that will decode the token for me so things like jot dot io or this one jot.ms if i paste the token into here then it will decode the token on my behalf and notice the token has three parts to it and the part we care about is the part in blue and this contains the claims that are contained within this token if we look inside here to get some more detailed information we can see the things like the not before claim the expiration date claim the issuer claim the audience claim and also things like the scopes that this token contains so once a client has this token we can then call a protected api using this token so for the next part of this talk we'll write that protected api and then show how to call that api using such a token so we've seen how to get a token so what i'd like to do now is to show you how to use that token so to do that i'm going to create an api and that api will be protected and so to use that api we'll need to ask identity server for a token and then have the api check that token so from the shell here i do net new and use the api template and this creates me an asp.net core web api and again i've created a solution inside jetbrains rider and i've added the project to that solution notice the directory in which i created the project was called weather api so it's also called the project weather api and again like the identity server project i've updated my launch settings.json so this thing listens on https port 5445. and if i run this application and we hit the browser we get back some temperature data and this is just randomly generated within the application itself okay so i want to protect this application using what's known as bearer authentication so we saw when we created the token from identity server we got back something known as a bearer token so any client we use will need to grab a bearer token and send it to this application to be authorized to use the application so to do that if i go to manage nuget packages i need to add a package called identity server 4 dot access token validation and we add it to this application then once i have that inside the applications startup cs where we call configure services i need to add two things i need to add a call to ad authentication specifying the scheme and it's going to be the bearer scheme and then we add the identity server support for this and i then call add identity server authentication and again we specify the scheme which is the bearer scheme and we pass in some options and these options tell this application how to call identity server we specify the api name which is the resource that's been protected and that's weather api and the authority is the address that identity server is listening on so https localhost 5443 if you remember from a few moments ago so we need to add one more thing so here we call use authorization and we also need to add authentication into the pipeline so i need to add use authentication here as well now be careful here this seems to be a bag in dot net core 3 where you have to add use authentication before use authorization otherwise you get into a weird redirect loop with identity server so before we use this i need to protect the api so if i go into my controllers and to the weather forecast controller i need to add the authorized attribute to this controller so the controller is now protected so if i rerun the application and go back to the browser and refresh we get a 401 so we're trying to hit the api without a bearer token so initially to access this api i'm going to use curl from a shell script so to do that if i go back to my shell and run the original curl command and remember this gets me a token so i'm going to grab this token and copy it and then i'm going to run this curl command so this cool command is a get and it's going to send a get to localhost 5445 weather forecast so that's my api endpoint to get the details of the weather forecast but to this i'm going to add a header and it's the authorization header the authorization type is bearer and this is the bearer token we just got back from the initial curl command where we asked for the token from identity server so if i grab this command and paste that into my shell and hit return sure enough we now get back the temperature data if i try the same command without the bearer token it fails we don't see the failure details here but it comes back again with a 401 so to access this api now i need a bearer token and we get the pair a token from identity server okay so now that we have that i'm now going to add a web application and then show you how to get this bearer token using that web application and how to access the same api so this time let's add the project from within rider so i go to explorer right click add new project i want a web application that i'm going to call weather mvc this will be my client folder it's a model view controller application c sharp no authentication if i click on create it's going to create that project for me again in here i'm going to make sure this is running on the right ports for this demonstration so i update this so we're going to run on port 544 if you remember if i look back at my identity server setup and look at the client settings here for my interactive client we have some redirect uri setup and they indeed are pointing at port 5444 so this is the settings for this particular client so to make my life slightly easier here i'm going to add a new package and the package i'm going to add is identity model and this just contains some helpers that i'm going to use from this application so for this application i want to do two things i first of all want to be able to call the api application and to do that i need to be able to set the bearer token so we'll need to make calls to identity server to get that information to for example get the token and then once i've done that i want to allow us to log in using this application as well so i want this application also protected so when a user tries to hit this application they'll need to enter their user details to allow them to be authenticated so first things first let's add the ui that's going to display the weather information and then show how to get that weathered information when we have a protected resource so in my controller i'm going to add another endpoint called weather and from here i'm going to call the api get back the weather details and display those details so to display those details we need to have a view and that view will look like this so in a moment we'll create a model called weather data and then inside here we'll simply have a table and then for every item in that model just display the date and the summary and the temperature both in fahrenheit and celsius so this model where the data will be in the models folder and it will look like this so a daytime for the date celsius temperature and fahrenheit and a summary okay so from within the controller we create a list to hold the weather data we will get back from the api and we're going to use an http client to call the api so inside this using block we'll call get async against the api endpoint and get the result of that call and then we'll do one of two things if the call is successful we'll get the data convert that json into a c sharp list and return the v with our data if the call fails we just throw an exception which says unable to get content okay so let me do a couple of things here let me go back into my api code in the controller and remove the authorized attribute and rerun the weather api application if i then take my weather mvc project and run that and go to slash home slash weather sure enough we get the data so we know this call is working so if i go back to my weather api project and put the authorized call back in and rerun the project and then go to the weather mvc home weather endpoint and refresh it now fails we're now getting an exception which says unable to get content so we need to be authorized so how do we add this authorization so we know the way we do this is that when i call the get async call here i need to add a bearer token as part of the request so i need to add this header so the way i'm going to do this is i'm going to introduce a token service so a service i can plug in anywhere where i need to do this from which i can get access to this token so in here in my weather mvc project i'll add a new directory called services and then in here i'll add three files so the first one is a file called identity server settings and this is information i need to use when i call identity server so things like the url to access the server the name of the client that i need to get this information about and the password for this client now in this case the client is going to be the m2m client so again if i go back and look at my identity server setup this is the m2m client and the password is going to be called super secret password and i've configured this to have these settings stored in app settings.json and it's this identity server settings section here i'm not going to go into detail exactly how i get these values out of here but it will be in the demo code provided with this video so the service interface looks like this here is one method called get token so to get token we pass it a scope it returns me a token for that scope and we'll see how exactly how this is called in a moment so what about the implementation of this so the way this works is the same way the curl command works we need to send a request to the token endpoint and as part of that request we need to provide the client id the client secret and the scope so here we have an api called request client credentials token async and this comes from the identity model package these are extension methods provided with that library and extension methods on http client so we get the client name the client password and the scope from our settings where do we get the token endpoint from well we can get the token endpoint from the discovery document and that's this document here so well known open id configuration and we can see in here the token endpoint to get the discovery document we can use another helper api called get discovery document async i'm doing this in the constructor for this service and again we get the discovery url from our settings so we call get discovery document async that gives you back the discovery document i can then take the token endpoint from the discovery document the client name the client password and the scope that we need then from that get back a token and i can then use this token as the bearer token when i call the api so to use this in my controller i need to inject a token service and store this in a variable and then when i create the client i get the token response from the token service and then on my http client use another extension method called set bearer token to add this token to the request so i need to register my services so in my configure services method i have the token service as a singleton and i also add configuration to extract my identity server settings into this identity server settings instance so with that in place if i rerun my weather mvc and then in the browser go to slash home slash weather it all works again so we are now getting the appropriate token to send to the api to allow us to be authorized and to access that data so just to go over this one more time in the controller we inject a token service that token service has a get token method once we get the token we add it to our http request as a bearer token the token service gets the discovery document and then from that discovery document gets the token endpoint and then from that token endpoint gets the token specifying the client name and the password and the scope we're asking for here is the read scope so we're saying i want a token that allows me to read from this api okay so a client is now protected but this application the mvc application itself isn't from here if i'm on this page i can always request this weather data what we'd like to happen is that when a user comes to this page we'd like to authenticate the user so we're going to show you how to do that using identity server to do that we first need to add a user interface onto our identity server instance so i'm back in the identity server project here if i'd built this from the template this would have come pre-configured with what's known as the quick start ui but if i look in this project at the moment that's missing but we can copy the source code for that quick start ui directly into the project and you can do that by going to the github repository so if i go to this url so github.com identity server slash identityserver4.quickstart.ui this is the code for that quickstart ui and for this we need the quick start directory the views directory and the www root directory and copying those into the project they look like this so inside quick start we have various controllers and other models to do with things like account management so for example login and creating accounts we have some consent information so when the user wants to consent to certain things we'll see this in a moment some things around diagnostics we have the various views for these so these for the accounts we're doing the consent and then in deb deb root we have the styles on the javascript that's used for this user interface so now that we have the ui code in place i need to do two things to get identity server to make use of these controllers in my configure services i call add controllers with views to add all the controllers to the services collection and then here what i'm calling use endpoints i need to call endpoints dot map default controller root and finally i need to add a call to app dot use authorization with that in place i can restart identity server and go back to the browser and refresh we now get the identity server user interface so now that we have that in place i can update my mvc application to get it to use identity server to do my authentication okay so let's start here so within the controller i'm going to mark my weather action as needing authorization so mark is authorized and then if i go back into my startup code i can now configure how we do that authorization so to do this i need to add a few things to my services collection so i say services dot add authentication and this is past and options and in here we need to set a couple of things so the first i'm going to set is what's known as the default scheme the default scheme will be called cookie and this becomes the name of the cookie that's going to be used to maintain the client's authentication state so to make sure we have a cookie we add a cookie and the name of this is also cookie we then need to add what's called the challenge scheme so i say options dot default challenge scheme let me give this a name and we'll call this oidc so we're going to use oidc as the challenge mechanism for our user and what this means is that we're going to call off into identity server and get identity server to do the user authentication for us so to do that we have to configure oidc so before we do that we need to add a nuget package so for the mvc project i go to manage nuget packages and into here i add the microsoft asp.net core authentication open id connect package so we install that then once i have that i can do add open id connect to my services we pass in the name of the scheme that matches the default challenge scheme above so that's oidc and again it takes options and this is where we configure the open id connect server we're going to use so let me just show you my app settings.json first of all so in here i have this interactive service settings section and these are the settings we're going to use for this interactive client and here we have things like the authority url the client id which is interactive the client secrets and the scopes that we're going to request as part of our oidc authentication so back inside where we configure openid connect we first of all add these three things we specify the authority we get it from configuration we specify the client id and the client secret and we're also getting those from configuration we then use these three options response type use pkc and response mode to specify the flow we want to use when talking to identity server and this specifies that we're using the authorization code flow we then specify the scopes that we're asking for and again this comes from the interactive server settings scopes section so that will be weather api dot read and then save tokens causes the identity and access tokens to be saved and that makes these available to other parts of our code for example if we call httpcontext.gettoken'sasync so i need to make one further change i need to add authentication into the pipeline so here where we say app.use authorization i need to say app.use authentication and now that we have this i can rerun the application okay so now if we have this if i restart the application and go back to the browser and i'm still in the home weather url and i refresh then it takes me to this page but it's asking me to authenticate so here i type in the username and password if you remember we had an alice user with an alice password and click on login and that then takes me to the consent page this is the consent ui and here's telling me the name of the application interactive and it's telling me what permissions it's asking for if i click on allow i get back to the home weather url so i now have access to this and that's calling the api and that has access to the api okay so we've seen how to add an in-memory instance of identity server we've seen how to build an api how to access that api using a bearer token how to build an nvc client and how to access the api from that mvc client and then how to add authentication to that mvc client so i hope you've enjoyed this video the next one in this series will show how to add entity framework into identity server so rather than using in memory data our data will be stored in a database we'll also see in that video how to add asp.net identity to identity server to help manage our users you
Info
Channel: IdentityServer
Views: 71,749
Rating: undefined out of 5
Keywords: identityserver, saml, wsfed, fido, adminui, entityframework, entity framework, ASP., ASP, ASP.NET Identity, Kevin Jones, IdentityServer4, IdentityServer3, identityserver5
Id: HJQ2-sJURvA
Channel Id: undefined
Length: 30min 23sec (1823 seconds)
Published: Fri Sep 18 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.