Login with Discord & Web APIs in ASP.NET

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello ladies and gentlemen my name is peter and welcome to another tutorial this time we're gonna actually make an oauth uh authorization for our website and our api we're also gonna build an api so what we're gonna do this is this is the final product this is what we're build what we are building so first of all we're gonna have a new route called home secret and if you try to get there it's actually going to ask you to log in with discord and once you do it's gonna ask you to authorize so if we authorize it you're gonna see that we cannot actually access it the reason why we can't access it is because only a user with a specific discord id can see the contents of it and currently um well you'll see the video to see who that is however another endpoint that we have is an api sorry is a login uh get token endpoint which also requires you to log in with discord but they already did that so it's not doing it twice because we store a cookie that we already logged in with discord and we get an api key over here which we can which we can copy to uh then issue a request from in this case from postman to to this endpoint api subscriber of the month current and if you send that you're gonna get json status back so that's for the api so we have an api that only accepts jwt tokens and we have a route a special site on our website um that requires you to log in with discord and in in our case it also checks that you are a specific person you have a spear a specific discord user you don't have to do them maybe you just want to authenticate people all right so let's get right into it we actually have a website published and um in this in this part we're going to talk about apis so you might have consumed a lot of other apis from other websites to get all sorts of data uh for example the weather data right and you might have used it in your discord mod or any other c sharp application that you might be developing and now it's time for us to actually build our own so first of all the first thing we're going to need to know is a tiny tiny bit about asp.net routing a routing basically is the structure of your url in relation to locations so for example you can see that we have two different pages here home and privacy those were generated by default in the uh mvc template if we go to home we just see the basic you know url nothing actually appended to it if we hit privacy however you can see that there is home slash privacy all right so this is the route this the um route now where does that come from how do i edit it maybe i don't want it to be home right so and that's where we're going to open up our project and we're going to open up uh under controllers we're going to open up the home controller right here you can see that first of all this is the first hint right the home controller hence the the home route right the home part of that so that's a controller what about the privacy one well there is a method here called privacy right so that's the second part of that it's a it's a home controller and a privacy method all right so that's um that's all fine and dandy but what if for the topic of this tutorial i want to make a new page right we're going to eventually hide it behind a discord login but for now i just want to make a new make a new action result page called um secret it's gonna be my secret super secret page right i'm gonna return a view in that now you don't really need to need to know or understand what all these means what i action result is or why we're returning a view or what this view method even is all you need to know for now is that hey like that's how you add a page you know because that's how they did it that's the first step in the controller and then the second step is inside our views home we need to have an equivalent cshtml right just like index has just like privacy has right so we're gonna hit right click on the home folder and we're gonna add a new view under so so by the way home folder meeting under views views home right click on that uh new view and we're gonna create an empty eraser view this is gonna add right and we're gonna name it we need to name it the same as we named the controller method right so we're going to name it in this case um secret and there you go it generates some basic uh stuff for us i'm just going to get rid of that and instead we're just going to have a an h1 it's going to be like a this is a very secret page and it's just going to be like good so this is our secret page you could add whatever you can add the funny images or whatever you have now let's test it right so first of all uh you probably by default have an iis express here right so what we need to do first of all is to click the little arrow button next to uh next to the run button and select the second option which is the name of our project why we're doing that um so the reason for it is we want to run it under kestrel which is the same it's the environment that we're kind of going to run it or that we already run it uh on our server so we want to emulate as close to the actual production environment as possible just so just in case there are some specific bugs so make sure to do that because later on you might run into an issue with iis so the next thing let's just print and it might directly open the secret page because we were on the view no it didn't okay good so again this looks normal we obviously don't do not actually have the button there we don't we can't you know there's no button that's a secret because that's not automatically added but we do have the endpoint so that means if we go to home forward slash privacy um oh sorry now privacy obviously if we change it to home forward slash secret we're going to say we're going to see this is very secret this is a very secret page which is what we wanted all right so that's how we make a new um a new page however this is not very secret i mean despite it telling us that it is really not um first of all it's security by obscurity because the fact that you simply don't have a link to it doesn't mean that people are not going to find out about it and even then um that's usually not enough because what if someone sees someone on this url or sees it in their uh history well then of course anyone can get the secret so that's that's the thing we need to add some more interesting uh more interesting protection methods however before we do that let's talk about apis and we're going to start by creating a new api endpoint basically we need a controller just like this home controller really uh except with minor differences so what we're gonna do we're gonna right click on the controllers directory hit add controller and from this selection we're gonna we're gonna select api controller empty you can see that mvc controller empty well mvc controller would be what home kinda is it stands for model view controller and the api controller is what we're after because obviously we're building an api now so let's add that uh and in this case when we're naming our controllers keep the controller uh keyword in there um that's just like a hey don't don't do that i'm pretty sure the asp.net framework looks for the controller name when it when it does some pre-compilation steps so first of all of course you can name it whatever you want i'm just gonna like for demonstration i'm gonna say subscriber of the month controller because maybe that's gonna be the api and the fake api that i'm building right it's going to give you the subscriber of the month for me right so you can see a couple of things that are um very unique for an api control first of all the api controller attribute i mean that's pretty clear but it also adds a route it's like well peter didn't you say that the route is actually taken from the name of the uh controller well that's right however you can override it in fact you can override it with any string that you want um and you can even use like placeholder things like this square brackets controller actually means that that is where the name of the controller will be so it's not just our url forward slash subscriber of the month it's actually our url forward slash api forward slash subscriber of the month that's where the api endpoint will be well let's also generate an api method and even though home controller doesn't really specify the types of uh requests that uh you need to um that this accepts we are going to do that we're going we're going to do that even though we wouldn't really need to to get um to be more to understand better what type of requests we're actually serving so in this case we're going to start with a with an attribute so square bracket and we're going to type in http post you can see that http actually has a lot of different methods like post patch but those are really those are going to be very important if you're building a rest api you can search for what that kind of means but you don't have to it's not necessary for this tutorial for now we're just going to use an http get because uh your browser your normal browser by default if you type in a url it's going to send a get request so that's why we're going to choose get and we can optionally provide a again a template of for the the action right so what's going to be after api subscriber of the month forward slash this right that's the string that we put in here and i'm going to say current right so this is like going to give you like the current uh subscriber of the month and then we're going to make this method public we're going to make it return object i'm going to explain why in a second and we're just going to say it we're just going to call it like current whatever this name will be ignored because we have the the route we have an override here in the in the get users need to you know standard c-sharp rules apply like this has to be unique in terms of other methods you know that sort of thing um it doesn't really what the signature needs to be anyways so current of course that complains because we don't return anything so we're gonna return a new anonymous object what basically anonymous object is is we're just going to specify like a new object as if it exists even though it doesn't so we're gonna i'm gonna come up with some random stuff so we're gonna say like have a status maybe and it's gonna say like okay like it just made up nonsense and then also let's say content maybe it could be like subscribe maybe i could subscriber i could literally just like have the subscriber there and um the subscriber of the month is not going to be drex's it's nepu maru because he commented on the last video and i really don't want to pick helman so that's the first thing um we could make this x an expression body method just to be like cool we don't have to this is perfectly fine so this basically creates like an anonymous object an instance of an object that really doesn't exist it's like you know but it has these properties and these values obviously the instance and that's why we return an object because it doesn't have a you know real type other than object so uh in in a real api you might have a some sort of a model object maybe you have a user object maybe you have a subscriber of the month result object and you would want to return that if you have a type absolutely use it but there's nothing wrong with just like generating an anonymous object for an api response this is automatically by by the way going to be serialized into json when it um returns when it gets back from the api all right now that we have that that's actually all we needed to do to make our first api endpoint if we run the application again and we go to the route and don't forget this this is the the domain forward slash abi forward slash subscriber of the month this is not a case sensitive forward slash current if i do that hey i'm going to get uh i'm going to get an apple motor here it's pretty good um and that's this it's all fine and dandy but can we deploy that well yes we obviously so let's let's get that onto our hosted onto our vps uh so that we can send it to our friends or whatever right so first of all here's a little uh improvement uh workflow improvement i created a little um powershell script the way you create a powershell script is you just create a new text document name it whatever and then change the extension from like txt to ps1 and windows should ask you hey is that really what you want to do i'm going to be like yes and create that's a new uh powershell script now to edit it you can't just double click it that would run it right so we right click on on that hit edit that opens powershell ise it's kind of like an ide for powershell um and here this is the script right it looks kind of scary because we use the two things that you haven't seen from my tutorials yet is push d and popped um it's basically the same as cd except uh it remembers where you were before you before it changes uh directories right so wherever you are it's just gonna it's just gonna remember where you are move to oops yeah okay cool uh it's gonna move to this uh path and then once you call pop d it's gonna go to the previous location right so when i see d i'm just gonna like push d and then right after i'm done with that uh all i needed then i'm just going to bob d so and other than that it's the standard thing we go into our project directory uh remember that's your project directory would be the one that has uh cs proj program cs startup and we're gonna run dot net publish the the release version linux 64 and self-contained false and then after we do that we're going to go to the directory where it is published we could have provided an output for our publish so that we don't have to like really go there but that's that's for future reference uh we just go there we just go to that publish folder and then we use scp to copy everything onto our server where our deployed application sits and then we ssh into our server and uh using systemd we just restart the website so that you know the changes are the changes propagate all right well let's now use it let's actually now use it so i'm just gonna be in i just see it into the directory where my uh redeploy powershell script is and then i'm just going to say redeploy ps1 i'm just going to start the script and that's what it's going to do so it automatically goes into that directory publishes the thing and then copies all of the files and it goes on the server and the the application which is really really convenient um because i don't have to do anything at this point i don't have to remember things all right so now that it did that if i go to um peter. i can see that hey you know that there's my there's my website and now the moment of truth is first of all do we have our home secret we do very secret and do we have our api endpoint api forward slash um what do we have it the subscriber of the month forward slash current yep there we go that returns the um the json and if you think uh this is by the way this is just formatted by um by firefox it if you hit raw data you're gonna see what actually gets returned right like this it's actually what um what the server responded with this is what you would parse in your net applications or any other application for that matter all right so we're gonna go back here and uh we are going to now work on the authentication because well obviously there are a couple of things that we might not want to want other people to see right so what we're gonna do is we're gonna start with the authentication methods and we're gonna start all the way in the startup class and we're gonna do some magic here now keep in mind this is not the simplest thing like it looks pretty scary but the thing is you only do this once you set it up once and then you forget about it honestly so what we're gonna do we're gonna have two authentication methods we're gonna have a login with discord and we're gonna use login with discord to authenticate for a for the secret page and we're gonna check if you are a specific user uh by your discord id and then we're also going to make an endpoint that's also going to generate a jwt token it's basically like a little secret um after you log in with discord and you can then use that secret to access some of the api features why is that why would we do that well first of all imagine if you are in an application like a bot like or like a website and you want to just request something from our api and we need to know that you that that's actually the application doing it well if it's a boss or your application it can't really go through the login with discord it doesn't what do you mean like it would just like fill in the fields like that's not gonna that's not gonna work right so that's why we want to generate that little secret that the that then your applications or whatever can use anyways that's the introduction out of the way so first of all rule number one is hey if you if you need to if you need to um make something secret you use the authorize attribute this is a secret this is a secret uh end point or this is a secret route we're going to add an authorized attribute of course we need to probably add a using directive yeah sb net core authorization makes sense so now we have an authorized attribute that basically means that hey like if you try to get there it's going to be like oh you need to it's not going to call you a hoe that was an o um it's like you need to be authorized what you can also do you can apply the authorized um attribute to an entire controller so you would like to put it here to make all of the end points require authorization but you can then choose specific ones and say allow anonymous which would then make this one public but everyone else so the rules are it takes the most specific one first right so allow anonymous is the most specific one because it's the closest to the method but if you can't find that it's going to use the closest thing that it has right and so not there's nothing on the method but there is something on the contr on the controller itself on the class so that's basically how the attributes work and it works the same way for apis exact the same thing authorize right of course you need to be using at the using directive that would mean all of our endpoint including my current subscriber of the month require authorization and again you can also put it here right and the standard thing a law anonymous also works we're going to delve a little bit more into the authorized and authorized attribute in just a bit all right so now let's go into startup and let's delve into that magic so first of all let's scroll all the way into our configure method where we added the headers and here we're actually going to start by uh enabling that uh enabling authorization by default so so what we're going to do is at the very top we're just going to say well we could probably add it like here after the forward headers uh we're just going to say app dot use authentication now remember this is authentication that we want to use it also has use authorization but we're going to use we're going to uh we want the the use authentication you're going to read the differences on msdn they have a really good explanation of that anyways so we're going to use authentication and then in configure services again in startup this is where we're going to configure the whole thing so first of all i'm going to do it after the controllers with after adding controls with views so we're going to do is we're going to say services and we're going to say add authentication again authentication um we're going to say options and options is going to be for sure it's an object right so it has yeah authentication options and it has so this is where we're gonna um configure three things we're gonna configure options dot defaults challenge scheme actually so we're going to configure default challenge scheme we're going to configure default authenticate scheme and a sign in scheme for the for the default challenge scheme we're going to pick cookie authentication cookie authentication default dot authentication scheme yep uh which basically means uh the browser when when you log in with your browser you're already logged in and the store's a cookie for you and uh at that point it's like oh you don't have to re-login like you already have a cookie that verifies like you you have logged in before which is good it's the first that's the first thing another option is going to be the default as i said uh the default authentication scheme and for that one we are actually going to use the jwt bearer token but i think that's a uh that's probably a nougat package uh let's hope that it's actually just a oh yeah that's gonna be a nougat package um so what we need to do is go into dependencies uh manage to get packages and we're going to browse for the package probably jwt microsoft yeah there we go microsoft sb net core authentication jwt bearer we're going to install that package pretty good pretty good all right so once we have that installed we're going to go back to our startup and we should be able to use this um let me just add the using directive like he sees it he's just like having a little hissy bit oh defaults right oh uh it's not default it's defaults my bad um oh and by the way this is a method so there's no comma that should it's an expression all right options the third one that we want to configure is again default uh well sign in scheme and for that one we're actually going to use the cookie authentication again so basically after you log in once after you go through either a bearer configuration or sorry either a bearer authentication or um the discord sign-in that we're gonna set up you get a cookie so you don't have to do it every time so since we're using cookies we have to add cookie obviously um and the next thing we're also using the jwt bearer token and for this we're going to do a bit of configuration but let's add a jwt bearer and it has its own options that we want to change um it's basically going to be like this yeah um so there's a couple of things that we want to actually this is i think more complex because i'm pretty sure this has a validation parameter yeah token yeah yeah token validation parameters that's actually what we want to set up and we're going to create a new instance of that new instance of token validation parameters but can we just use this can we just like add a using directive for this i don't like that yes please thank you and that's how we're going to configure that all right basically so for the parameters it's it's just a couple of settings for our um token validation so we're going to say validate issuer true which means like when when you get a a token which is it's just like a string it's like a secret it's kind of like your bot token if you're familiar with this cardboard so it's going to take a look at it and it's going to be like okay do i need to validate who created this token make sure that it was me we're going to say yes do that another one is validate audience i'm going to say false here so this is do i need to validate or make sure that um whoever is using this token whoever whoever is sending me that token is the target audience and by the way both the issuer and the audience is defined as a url so it could be oh it's so like the issuer could will probably be for us um peter.rest right that's the issuer that's who is creating the the token now the audience obviously would be your front-end maybe it could be it is possible that your audience is the same as uh the issuer right maybe it's peter.rest and it can only be used by peter.rest right that would be good for for me i'm just going to like actually put false even for the issuer because i don't really want to deal with um configuring it on server side but we're going to do that at the end of this video hopefully if i don't forget if i do forget it let me know um either in comments or better yet in on our discord servers post.net forward slash discord um so we're gonna also so we're gonna say valid date um uh issuer signing key that's gonna be true because well it's just basic security there and we're gonna need a valid issuer and valid audience that's that's how we defined define those things those things uh a valid issuer normally we're gonna like we're gonna set it up for now actually oh we're gonna use it let's use it do we have config yeah we do all right so we're going to use it from the configuration so let's talk before we do that because we're going to set up this and we're also going to say valid audience that's what we're going to set up and then we're going to get an assigning key which we're yeah all right so what we're going to do is we're going to talk about configuration you may have seen appsettings.json over here right in your in your project directory it's basically like hey you could it already comes like asp.net already comes with like a basic json settings there are two more five there are well plenty of other files that you can create in terms of settings um one of them that we will create right now is let's just right click on the project hit add new item probably just text or json doesn't have json yeah oh actually app we're creating an app settings one um yeah actually let's just select app settings files for for that matter and we're going to call it appsettings.development.json it's already part of the project oh didn't didn't know that all right so let's uh open folder in file explorer oh it already has one yes all right no need to create it i just didn't see it because it's not i don't think it's listed oh it is under abs this is crazy right wild anyways um sure all right so what we want to edit is the development one so in amp settings this is where we would like define the structure but we wouldn't fill any secrets and app settings development is where we would actually have the secrets this is app settings development is something that we wouldn't add to like get all right so if you if you have a repository if you don't then obviously you don't have to really care about this but um if you have a if you have a git repository repository just like i do it's worth going to your get ignore and somewhere it doesn't really matter where adding app settings.development.json just so it doesn't get just so you don't accidentally commit this file into your repository because this will contain all of your secrets and tokens all right so that's a quick update now here's the thing we can create our own uh our own things here our own parameters and we're going to create our own section first and this let's call this jwt this is where all of our jwt information is going to be and we need for we need issuer and by default uh that would be and i'm editing the base app settings not the development one at first here i'm going to use the the the local host issuer basically where we're going to use what we're going to use for testing so https localhost 5001 that's going to be the issuer oops and we're also going to use the audience and https oops again auto space https localhost 5001 um so again we're using both the issuer and audience is the same for us although they will be ignored but maybe at the end we will enable uh authentication for that or valid validation of that uh the next thing that we're gonna need is uh an encryption key and it's just kind of like a secret that it's gonna be used to to hash our gwt token um uh it needs to be a fairly long string so i'm just gonna use my password manager to generate a passphrase uh yeah actually just a password let's put it like let's give it like 128 characters it's gonna be fine copy and let's paste that so this is the this is the encryption key uh keep that secret obviously actually now that i say that uh this one in app settings we're gonna say uh generate a long generate long string here and then i want to keep that i want to overwrite it so i'm just going to add it here as a comment we're going to copy the whole thing that we just created and we're going to paste it into the development section the development app settings so here i'm going to add a comma paste that in there you go i'm going to go back copy the string that i generated and i'm going to paste that here right so now we have the same new values in both app settings right in app settings json there's the default one the without anything secret and then in the app settings.development.json we have the same thing but but uh with real values so to speak a real test values in this case because it's now production we could also we could and would oh that's actually really we will also have amp settings.production the json and if you remember no app settings.release.json i'm pretty sure um that one is going to be applied for our server right so you could imagine that the issuer and an audience is going to be different for for that let's get back to our configuration and now we can use now the question is you know how do i get this data how do i get these um settings so you can use this little configuration object that we have here and the way you use it is you say configuration dot get value and you need to specify the type of it which in our case is a spring and then you provide a path um for the value inside the the config which for us is the category the first thing is jwt so we're going to start with jwt and then we need to put a a colon to get the inside that and the issuer i think is the yeah issuer is sure so that's the path inside the uh the config the app settings so that's the first thing oops i'm just gonna copy the configuration part uh the next thing is valid um audience and we're gonna do the same thing for audience i'm gonna double check that then yep and the the third thing is the uh issuer signing key which uh oh that needs to be a new instance of a symmetric security key which yeah that's fine and uh we need to add an encoding of utf-8 and get bytes of uh the key that we generated uh encryption key right all right so we're going to get get the bytes of that um of that utf-8 string and uh we're going to feed it into our symmetric security key and that's going to be our issue issuer assigning key and that's the configuration for jwt now one more option to go oh that's it and that's add o off because now we're gonna add blogging with discord so uh the second is probably options right options i think close that right it is although it's probably we want it like this all right so this is where we configure all of the disker related stuff well this score unfortunately doesn't like let you well the part of the oauth scheme is that you have to have an application you have to be registered with sort of discord as someone who can ask people to log in with them right so what we're going to do is we're going to go to discord we're going to go to discord.com forward slash developers forward slash applications and here we're going to create a new application it's going to be asb it's like well it's going to be peter rest peter rest peter rest i don't know man and we're going to hit create now this is the same way we would like create a new bot but we're actually not going to bother making a bot account so um let us pick an icon because i think i have one in the c dev right oh yeah there you go cool there you go all right so here at our bot page what we're interested in is the client id and client secret don't worry i'm going to delete this app so um don't you know you don't have to actually i think i'm going to regenerate the secret uh eventually so um hopefully you're not going to be able to get that so we're gonna go into our app settings and we're gonna edit a couple of things again so we're first going to edit uh add a new discord section and in it we're going to have our client id which is going to be something and client secret which is going to be something as well it's like your id here well your client id here and then your client secret here right that's gonna be that um let me think if we need anything else i don't think so i think that's good enough so i'm going to copy that into our development into our development app settings and we're gonna fill it with real data so client id very simple paste it here client secret over here copy paste that here please don't steal my client secret um then what we're gonna go what we're gonna do is we're gonna go to oauth2 and we need to set up a couple of things so first of all number one thing is um we need to like specify what we're going what we're going to use you know in terms of information about the user and the only thing that i really want to use is the identify and they this these are scopes we're going to use those later and the only one i want is identify how did i figure it out right what if you're not doing login with discord what if you're doing login with slack login with whatever any service that logging with google doesn't matter so they're going to have documentation and discord is under oauth 2. learn more about oauth2 this is the holy grail of our information this is all we're going to need keep this open because we're going to copy paste a couple of things from this so now that we have these settings that's fine let's go to our startup and we're going to uh start configuring a couple of things so first of all we're going to need the authorization endpoint and we need to it's like well that's discord authorization endpoint it's like what's that well let's go here oauth2 urls authorize base authorization url this is what we need for our authorization endpoint easy next um next we're going to define the scopes so we're going to say options.scope.add and we're going to add a scope that we like and i really like the identify because it's going to allow you to get the at me section without an email so we're going to get an id of a user their username uh that sort of thing so i'm going to use the identifier i'm going to add the item if you wanted to add more if you really want like someone's uh i don't know email then you would add an email like that right you would add another one you would add as many of those as you want do not change them that doesn't really work um all right so that's thing that that's something next up uh we're going to have a callback path it's like so so we send so the way this works by the way probably should have mentioned kind of how how oauth works is that we're going to take a user we're going to redirect them to discord and discord um you know when the user authenticates he generates like a little secret for us and sends the user with the secret back to us we're going to use the secret to get the information about them and now they're authenticated we're going to set up a callback path we're just going to make a new path string and that's going to be the end point this really doesn't matter we're going to use that actually it does but let's yeah it's like all off maybe and then i don't know oauth callback is a common one uh you could you could come up with your your path here we could maybe yeah yeah this is good enough so so he here is where we need to take this right so whatever you generate you could stick with off oauth callback that's fine you take that and then you go back to discord to your [Music] application page and here when it says redirect let's add our redirects first of all we're going to add the one that is for testing oh by the way if you try to redirect someone back to a url that is not in here uh discord's not going to let you it's going to be like hey i can't send that information to like a random url so we only can discord can only redirect people to https uh localhost 5001 forward slash sorry forward slash off this is this is where that uh this is where this value comes into play right so that's the that's one of the valid ones but we also accept https um peter.rest uh off because we actually want to use it on the real live server so if you try to redirect to anything other than those two you're not going to be allowed to because that's good all right so that's that let's continue with our settings the next thing is obviously client id and secret so we're going to again use configuration getting the value those are strings as well and again this one is not under jwt this one is under discord client id again that's coming from the app i'm setting discord client id that's how that works and we're going to do the same thing basically for the client secret client secret that's pretty good and then we also need to specify the token endpoint and again it's like hey what's the token endpoint that is something discord has here token endpoint let's put it there pretty good now the next thing we're going to use is oh user user information endpoint um this is basically where we're going to get all these information from and this is a bit sketch this is a bit different i'm not going to say sketchy um because uh we need we're going to get the identify uh we're going to have the identified scope so we're going to be allowed to use users at me which after clicking on it is like oh well this returns a user object and this when it says users at me it actually means https discord discord.com forward slash api forward slash users at me right that's where we get information uh from uh discord and then we also want to know what the information is like so we're gonna create they say hey it returns the user object it's like okay click the user object and we have an example example user returned back right so nelly over here we can see what we're interested in from this jason that we get back is the id we need to know the id and the username that's all we that's all i really care for you can care for way more uh remember you're not gonna get all of it you're not gonna get email unless you have the email scope as well this is just not going to be there it's going to be empty so keep that in mind so what we're going to do here is we're going to say options dot [Music] claim actions and we're going to use uh yeah we're gonna use like the json method so here you can use map json key which is basically going to now you can define uh the different types of claims we're gonna talk about claims later on to values in that response so we're going to use a claim type uh claim times dot i'm going to use name identifier for the id and for us it's just id because in that object it's just id and then we're going to use something very similar which is going to say claim times dot name for the username what is it username it's just username okay all right what if you have an object in there what if there's another object well what you can do is say options.claim map jason sub key which is going to allow you to go uh one step forward one step deeper right so you can have some some object which would be inside this and then another key inside that right if it's nested anyways for us it's good enough to get an id and a username we get an id and a username it's all we care about at least for nelly over here um i think we still need let me see oh of course yeah access denied pat would be probably useful discord off failed right that's what we're gonna have as a as an end point to that and we're gonna create that endpoint just going to say it's going to be a public eye action result returning access denied oh no sorry what am i typing discord all failed and return a view there you go and we're going to make that view in home again and view uh empty razor page here and it's gonna be called the same thing right it's gonna be discord off failed and we're just gonna maybe have an h1 it's like uh listen listen here we cannot authenticate you unless you give us basic discord permissions so so the user goes here if they go through the oauth and when it asks hey do you want to allow this app to use your data when you say no you go here and we say listen here listen here your little snitch um all right so that's good that's going to be pretty good and then the next thing is going to be options uh we're oh we're going to define the event for getting actual getting the actual um information so we're going to create a new off events instance which i think comes from uh oh yeah yeah oh makes sense and in it we're going to configure a couple of uh things and one of them is on creating ticket which basically means like hey we got response from from discord but we want to get some um information so we want to actually parse the claims so it's going to be an async context anonymous delegate so we're just going to do something like this and in it we're going to just create a request because we need to just like genuinely ask so this is after discord gets us back we get a token we uh we actually no it's one yeah it's once we get the temporary token and we ask for the real token and then we ask for the information about nelly over here so we're going to make a new http request message all right it's going to be a new instance of that uh we're gonna make a uh get method http method that get yeah and then we're gonna get options from from our context which is basically like accessing information that we defined here um and we're going to use the user oops user information endpoint right basically we're going to now try to create a get request we're now going to try to create a get request to oh my flip and what's up with that um are you sure is that genuinely in isn't there a different use for that uh we'll have to actually put in the the full path to the http method for this anyways now that we have the request um we need to add a couple of headers request headers um we're gonna add the accept header we're gonna make a new media type with quality header value are you serious can we not you can you like simplify that i'm getting i'm going crazy oh boy oh boy can we add a using direct yes we can thankfully because that would be quite unruly all right and that's gonna be application json because we that's what uh that's what we need and request headers so we're going to add an authorization header which is going to be a new uh authentication of the value yep and it's going to be a bearer token oops [Music] and that's going to be our oops that's going to be our context access token that's the thing that discord gave us when someone logs in all right once we have that we're gonna get a response by sending the request we're gonna use the context back channel to send the request request http completion options and we're gonna get uh where are there oh yeah yeah sorry i'm stupid uh we need the headers read not the content right uh oh there's a cancellation token is going to be context http context um request aborted which means hey if we're in the middle of authentication here and the request has been imported for whatever reason we want to uh pass that into this async call so that it can be canceled if we're still waiting for that all right now we're going to get the response and ensure that there's a there's a success status cut i know this is like a bit magical but bear with me we're almost there we're almost done with this we're going to get a user and we're going to use oh we're going to use this is where we could use newton's up json bar i'm going to just use system uh text json uh i don't know no reason really and there's a json document you could use newton's of jason here if you have it already at it um oh wait but i mean i'm just like trying to use what's in dot next response content and we're going to read it as a string yep and get the root element okay so that's gonna get us our user and we're gonna oh run claim actions of course yeah yeah we're gonna run claim actions on the user so that's the little that's that little magic thing here so what we're doing here basically is we're asking that user uh information endpoint which by the way is that little at me and we're going to give it the we're going to give it a bearer access token because we got it from discord and we're going to send that and as soon as as soon as we get it we're gonna we're gonna read all of the information in terms of json and we're going to um run the claim actions which basically is this it parses that json it gets the id out of it as this claim username is this claim that sort of a thing alrighty that should be it for the authentication methods um we got a uh bearer authentication we got there a gwt bear authentication and a discord authentication now now we're gonna start with restricting a single page the secret page with discord right so what we're going to do is we're going to go to our secret thing here and uh around the author after the authorize [Music] after all the authorized attribute we're going to add an authentication scheme and we're going to pick the discord one discord means basically the same as we typed in here right we gave it a name here discord so that's it's like hey whenever someone tries to get the secret authorize them um with uh discord and that's gonna force us to do the oauth flow so hopefully gonna let's try it let's try it i mean i was trying to think what i forgot but maybe maybe nothing maybe everything who knows all righty so that's fine and now let's uh go through the flow and i'm gonna use instance of edge because i'm pretty sure i'm already just logged in with discord on firefox so we have a home secret and it points us to discord a discord is like hey you gotta you gotta authenticate so i will and after i log in it's like hey uh peter rest wants to access your account it's like signed in as spelus not you yeah it's me um it gives us a little bit of uh a rundown of like what we can actually access and in this case like hey once you authorize you were redirected to localhost 5001 as the domain and we're going to say yeah actually authorize and there you go now we're in this in this very secret page because we actually authenticated with discord now it's good to keep in mind that here's the thing if i stop here we can actually actually here's the thing maybe we don't want to allow anyone who has a discord account maybe we want to actually um only allow me only me my discord account is allowed right so in that case i'm going to say we can get those two uh the the id and the username um we can get that in this method as long as we've been authorized uh with discord authenticated with discord so we're gonna say we can get the id which is going to be the user claims so you remember when we said run claim actions right it builds those claims that we can access here now right so it says user claims and we're just going to link get first [Music] first claim that is of type uh i think we i think the type was name identifier right and then dot value which is going to be a string um that's fine we could parse it as a you along because discord ids are view logs but meh whatever and then we can get the name or the username uh it's this basically the same thing except instead of name identifier we just get name right um that should get us uh the the currently logged in user's uh id and username right and here what we can do is like hey if the id is not um well what could we oh yeah sorry if it's not my id which i have ids here like me right if it if it's not that sorry if it's not that and of course you would have probably a service that gets this from like a persistent storage and you know instead of but for any as an example you know it's like hey if my id is not that you can return unauthorized which is going to be like hmm you can't do that you can't view this page um in our case at that point because i have my id believe it or not um it should still allow me in i refreshed it and it looks like it still allows me however if we change that to someone else's id in this case [Music] we're going to use my favorite subscribers id which is a different id if i run that now that should reject me that should be like hmm but that's not you or sorry that's not your id so we're gonna try that bam and it says hey this page isn't working right now it says 401 and we know 401 is unauthorized okay so that's how you can limit it to specific discord users right so hey if this is uh if this is you you know or you could be like sorry if your id isn't bad or your uh username is you know is like hellman right like you could be like very creative about the different restrictions you could put on different things right it's like hey i don't i you know i only allow users with this id and as long as their username isn't hellman you know it's like hey crazy stuff anyways so we're just gonna at this point we're just gonna like i'm just gonna keep it as uh you know what for the hell of it um i am going to allow uh this id which i you know i already had it in there which means uh nepu maru can actually view the secret on the published website um and nobody else crazy huh all right the next the next part or uh of our authentication scheme is getting a jwt bearer token and um using it to access an api endpoint so here's a here's a little thing we can create a um to make a new conv oh i could have just changed it whatever um let's make a login api controller but this one is actually not going to be this one is just going to be like it's not going to have the api proof it's just going to be like login uh which i think is default so i can just like get rid of that it's not authorized it's not authorized because you know for login you need to you know you need to authorize with a discord but specifically specifically after that so we're going to say we're going to have a uh thing that returns an object that's um let's call it um get get uh token by discord oh actually let's let's have a get token like that it's gonna be good and we're gonna add and this is why we're going to be a an http get on top of just like yeah get token it's gonna be the same thing which is the same thing and i'm pretty sure i don't need to specify that but i am i'm gonna do that um and we're gonna again use the authorized thing uh authorized header and we're again yet again going to use the authentication scheme of uh discord right so if you want to if you want to get a token you need to authenticate with this card which is pretty easy because that's gonna go through the whole flow and then uh all we really care about is the user id in this case so i'm just gonna go through the claims and find the first [Music] claim that is of type uh name identifier all right and we're gonna get the value of that and then here's the thing we need to generate a uh key and a jwt key so what we're gonna do is let's just get the encryption key first uh oh um we need config for that now here's the thing here's an interesting thing well you want to use config but you actually don't have it here when you set config with capital c you were referring to this property uh i configuration an instance of icon for something that implements eye configuration right and they just injected it with dependency injection so we're going to do the same thing it's not scary it sounds scary but it's just it's not all right just we're just going to create a constructor here and in the constructor we're going to request that we need um eye configuration which by the way we need to add a using directory for and we're going to make a make a private read-only instance of that like this and then we're going to assign config like this right so basically we require it in constructor as soon as we get it we set it into this private read-only field just so we can use it from other methods such as for example this one and we're going to use this config to of course get value for our encryption key so we're again referring to app settings and we need the uh we're going to actually need all of these three we need the issuer audience and equipment and an encryption key that's a mouthful so we're go we go to jwt encryption key um that's the key i'm gonna need an issuer and an audience so issuer issues i have issues issuer and an audience audience again this refers to the amp settings make sure that it fits you know if you named it something else you'll need to name this differently all right so that that's we get the information that we need and then we're gonna make a secure security uh key we're gonna make the new the same sort of symmetric um uh security key symmetric security key and yet again we need to encoding utf-8 get bytes of i want to get the bytes of the key and that's how we get our security key and then we also need uh credentials and those are uh for that we are going to create assigning uh credentials and the credentials to design uh to do our signing method is going to be the the security key we need the security key uh we're going to need the algorithm specify the algorithm which is going to come from security algorithms and we're going to use uh well we're gonna use hmacsha 255 256. now we're also going we're almost there we're like halfway through this like it's fine it's not and like it's not a horror it's not as horrific as this you know what to start up was let me tell you now perm claims i'm going to make a new list of claims and here's the thing your jwt token that little token they give people you can put information into it you can put whatever info you want um we are going to put um like a generate like a whatever generated guid no like real reason for that that's like if you were to create a user account and you had that guid you would want that in there we're also going to put discord id in there as a so so as a demonstration you know so for the claims i'm just going to add a new uh claim instance and the claim has like two parts really it has the uh so we use this type and value there are some types uh the default name so it's like jwt like register claim names it has a lot of names for common things we can use jti it's part of the specification apparently so if we copy that oops jti can we get the intellisense to like help us a little bit because i'm like interested in that link but it yeah it's gonna just like go away and i'm not not copying it by hand so actually screw it and then uh so for the for the jti which i'm just going to like generate a new guid and to string it because i don't really care for that uh well it's like peter why are you adding it it's like yes that's a very good point i wouldn't but i just want to show you how um how to add multiple different claims right so and then for example i'm going to make my own claim that's going to be like a discord id right and that claim is going to uh get my user id which is defined here right that's gotten from the claims uh coming from discord right and that's how i know maybe based on the discord id i can just like get my own stored user instance and he has maybe or she has way more information about that who knows right so i'm going to make the token it's going to be the new jwt security token uh it has a couple it has a lot of things honestly we need to provide so we're gonna do something like this and we're gonna give it an issuer um can i find the actual yeah audience we're gonna give it perm claims uh we're gonna skip that so we're gonna go to expires we could say add datetime.now.ad just have it valid for a day right so maybe your your api token expires within you know in a day well maybe actually like 30 days actually no a week right so you have a week until your token that you request this way expires uh and we need sign in credentials uh credentials right now we have that now we have this token so what we're gonna do is we're well actually we have the security token but we don't have it written now we need to i'm gonna say yeah create a gwt token this way i'm gonna say new gwt security to security token handler that's the one and we're gonna use write token and we're gonna use the token here and this is going to generate like an actual string an actual token that we can use what's the problem with this oh it again conflicts pretty good i'll um like like that are you serious what did i do that it like started to conflict eh whatever you can i can probably resolve these namespaces if i were careful about oh actually i'm pretty sure oh oh if i do that and then get rid of that is that going to work yeah so so basically what i did is i added the thing that it wanted to i removed unused using directives and then i got it back because there was an unused using directive that collided with that that's that's why people are like well i don't why would i like remove unused using director yeah well this is exactly a reason why you might want to do that period periodically if not you know automatically well and then in the end we're going to return a new um an anonymous object incident uh and we're just gonna say that there is an api token and it's a jwt token right we kind of do that we respond with a json that has an api token and it has that's it right so however let's have an end point that now let's no actually let's go to the subscriber of the month and say that actually this um subscriber of the month uh endpoint is actually under authorization right so you cannot actually get it until you're authorized so here that should be basically it so what we're gonna do is we're going to so that returns that and it's just a get so we're gonna see that we're gonna see that there okay good so let's test it let's give it a give it a test i'm gonna say get token that's gonna be i thought it was implicit apparently isn't let's add the route attribute we shouldn't really shouldn't be a problem maybe maybe it is maybe apparently that could be enforced as well now the more we know now we're gonna do we're gonna try api a login and then we're gonna say uh get token that is a 404 that's weird that shouldn't happen oh no that was fine that was fine because i did yeah i'm stupid whatever no no sorry i'm stupid whatever no no no it was fine it was fine i just like forgot that i don't need the api and i need to log in so i'll log in so now i'm gonna give it access and there you go that's it right so here's the thing now um this is the response it says hey this is your api token and i'm going to copy that i'm going to copy that i'm going to store that before i lose it this is my token for like adding adding information sorry authenticated for the api because if i just go to api dot uh forward slash um subscriber of the month and i do current even though i'm logged in even though i'm logged in um with this card it's still it's just going to pretend like that doesn't even exist right because it it can't authenticate me for that so he's going to pretend like it doesn't exist it's a 404 however i'm going to use something called uh postman it's an application you can install you can download it if you just do postman download um there you go you can download it from here it allows you to test apis by sending different requests so what you can do here is uh i'm going to change the theme i'm pretty sure the dark one was unreadable we can basically try to issue a request right so if i try to send this get request it's going to respond with 404 not found however if i go to authorization and i add a um not an api key a bearer token and i paste in that oh this is and i paste in that token i'm pretty sure it auto pasted it for me um and i send it now i get the status back i get it right it's gonna be it's gonna be valid until um until a week passes right so it's gonna be valid for seven days it's the only way of getting uh the info from that uh from that end point well that does it right that does it for um the authentication method now we need to think about how do we deploy we need to create a new app settings for for deployment for like a release with information that are not going to be compromised that's option number one option number two is you're gonna keep um there are automatic ways of doing this but i'm not gonna i'm not gonna do that i am going to uh have a different method the different method is going to be i'm going to keep a i'm going to keep it completely out of this repository so i'm going to take the app settings the app settings.json i'm going to copy that i'm going to go to dev i'm just going to paste it here and this is where my real one is going to be for the i'm gonna copy the contents of app settings development the one that's filled into this uh newly copied one i'm just gonna have that be the thing except i'm gonna change a couple of things this is gonna be peter dot rest this is also going to be peter that rest actually the audience i'm not gonna validate audience but if oops it would be peter rest because i'm not going to validate audience because i want you to use a jwt bearer token from different things you could use it from different applications i don't really care so that's that's a thing and then what i'm gonna do is i'm gonna edit my deploy script and i'm gonna right after i do that right after i uh after i copy with scp after i copy that [Music] i'm actually going to pop d and i'm gonna go into dev yeah that's it just that because that's where my app settings is real amp settings and i'm going to um scp the app settings json um onto my server into yeah there right so i'm gonna then copy the app settings chase on the real one into the directory of the project right so that's how i keep it managed outside of um of my repository it's not the best solution there are way better things but for now i feel like this is going to be all right the difference is you obviously need the issue or an audience um and we're also going to change in startup we're going to now validate those things so we haven't been doing that so here in jwt we're actually going to validate the issuer making sure that it is going to be us we don't need to validate the audience because we don't care who has the token as if you have the okay okay if you have the token you can use it that's it so that was it that was it so now we're going to try to deploy that redeploy let's see all right you can see that the last thing that was copied was app settings json which should be this one yeah all right so now we can potentially try it out i can go to beater.rest and there you go it's just my website now if i go for an anonymous edge [Music] and i try to go to secret it should yeah it redirects me to to authenticating with uh with this card i'm going to say no i'm going to say no for this case and it points me to listen here your little sh uh yeah and then so so and you can imagine what would happen if i authorized it right it would just go back and obviously figure out that it's not my uh discord id which is telling me unauthorized right but i want to test the api thing so let's go to login uh get token this one also oauths with uh discord as well except this time i press authorized and it tells me oh okay that's fine so here's your token here's your api token and speaking of it because i already authenticated and i have that cookie most likely i'm i can now go to home secret and it's going to just tell me that it's 401 unauthorized it's not going to ask me for discord because i actually logged in with this score properly so that would tell me yes all right you're authenticated with discord it's fine and if i of course want to go to api um subscriber of the month current that's going to tell me the same thing it's 404 i don't even know what you're talking about it just denies it if fl flat out denies that something like that exists because you don't have that jwt token however if you go to postman and you have the token in here this is a new one this is a newly generated token and we don't do localhost except we do theater.rest if we do this and we send it then there you go i get the i get the subscriber of the month now that's that's mostly it like we did it right like the thing that i'm gonna do right after i stopped the recording is that i am going to um change my i'm going to refresh this thing i'm going to change my secret so that you guys can't like make apps with that um and that's it we got it deployed so now we have proper authentication with discord for our web and we can do you know all sorts of stuff and play around with uh different things so i hope you guys liked the video if you did like it if you want to follow this asp.net tutorial then subscribe now please showcase your changes in the uh your asp.net core discuss channel tell us how you did it how you got it one thing i'd like to mention is that we went through the oauth flow and not necessarily through like extensions there are packages that make it super easy to actually just you know have all of oauth with discord we chose to do it manually why well because as i said you can use different services you can not you don't have to log in with discord you could log in with google with facebook all sorts of stuff even some obscure websites that just have the oauth flow right so you can log in with whatever um and there you go maybe you have a little button that says login with discord and it points you to maybe um one of those endpoints maybe a completely plain endpoint that just has the authorization right and that just makes sure that you're logged in and then you can based on that specifically show different uh different stuff have secret have secrets have fun and i'll see you guys in the next video
Info
Channel: Peter
Views: 6,062
Rating: undefined out of 5
Keywords: asp.net, auth, authentication, login with discord, 3rd party auth, OAuth2, WebAPI, introduction to webapi, how to build an api, JWT, Bearer token
Id: P1zo-uQCfwg
Channel Id: undefined
Length: 85min 46sec (5146 seconds)
Published: Fri Jul 24 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.