Angular Security Using JSON Web Tokens


  1. Review and Install the Sample Application Course Introduction and Goals Hello everyone, Paul Sheriff here with Pluralsight. This course is Angular Security Using JSON Web Tokens. This module is Review and Install the Sample Application. Now the goals for this particular course are to create two different security scenarios. One we're going to first start out with applications with small security requirements, then we'll turn our attention to enterprise applications. That's where we're going to get into the JSON Web Tokens. But first off, we're going to learn how to authenticate and authorize users. We're going to then learn how to secure UI elements, and we're going to learn how to protect navigation with route guards. We're then going to create a Web API and secure it using the JSON Web Tokens, and then finally, we'll learn how to bring it all together with claims-based authorization.

  2. Prerequisites and Modules in this Course To take this particular course, I'm assuming that you are an Angular developer, that you're familiar with Angular, TypeScript, and, of course, the Web API. If you're not, there are many Pluralsight courses to help you out. Here are just a few. Angular: Getting Started, Angular: Forms, Play by Play: Angular RxJS, and Angular: Fundamentals. Take a look at those if you're not familiar with Angular at all. Let's review the various modules that are in this particular course. This module, review and install the sample application, is going to talk about the starting application that you're going to secure. I've already got a sample application already built called Paul's Training Company, and that's the one that already has data going back and forth, but we need to learn how to secure that. It already uses the Web API for data modification and retrieval. The next module is authenticating a user. This is where we create a client-side user authentication system, and we return a user authorization object that we use to secure various UI elements. The next module is secure UI elements and guard routes. We're going to actually use directives to secure UI elements, such as menus and buttons, and we're going to add route guards to secure navigation, so people can't get directly to a path if they're not authorized for it. Next, we're going to create a Web API to authenticate and return that user authorization object. So we'll actually do the user authentication via the Web API after we learn how to do it on the client-side, and we'll return the user authorization object now from the API instead of doing everything client-side as well. The next module we'll use JSON Web Tokens to secure our Web API methods. So we're going to learn how to use the JSON Web Tokens, talk about what are bearer tokens, and how to generate a token using the JSON Web Token system. Next we'll talk about working with the bearer tokens in Angular, and we'll talk about how to pass those tokens back and forth, and we're going to make it really easy by creating an HTTP interceptor. Our last module is using claims-based authorization. We're going to build more of an enterprise security system now in this particular module where we create an array of user claims from a user claim table, and then use that set of claims in a structural directive that we'll create in Angular that's now going to help us secure our UI. So, let's get started.

  3. Security Goals and Security Architecture When we talk about building a security system, we need to think about what we need for our application. Well, the first thing, obviously, is we don't want to let just anyone in to our application, so that needs to be one of our goals. We also maybe want to keep certain users confined to certain areas and not let them get into everywhere in the application. We also want to create a security authorization object, and this will help us for each person decide where they can go in the application. We also need to protect routes using route guards, so people can't type in directly on the address bar and get to an area they're not supposed to be in. And we also need to take care of our Web API methods as well to ensure that only people that are using our application and have been identified as valid users are allowed to call our Web API methods. We're going to build three different security architectures in this course. Our first one we're going to build a login page and bind that to a user object that has a username and password. It also then builds a security service and that security service is going to build an array of mock logins. So we're just going to use mock data at first. Now we're also going to build an authorization object. So, after the user has been validated, we're going to go ahead and fill in some properties, like canAccessProducts, and that will then be able to determine whether or not they can see a menu item called Products, and fill in a property called canAddProduct, and we'll set it to either true or false so that it turns off and on this button, Add New Product. And maybe we have a categories menu, and we want to bind that up to a property called canAccessCategories. So all of this is simply going to use mock data at first to get us used to the idea of building a security system and turning different UI elements off and on. Our next iteration of the security architecture is our security service will change to now call a Web API. A Web API will use a couple of tables in the SQL server to validate the username and password, and to generate our user authorization object. Now this user authorization object is actually going to be populated by reading data in the UserClaim table, and then we'll fill in the same properties that matched what we had in Angular, but now they'll be returned back from the Web API into our security service, but still use the same authentication system that we build in the previous example. For our third security scenario, what we're going to do is still use everything that we had in place, so security service, the Web API, the SQL Server, and the User and UserClaim table. What we're going to do is change the authorization object and not have individual properties that we map to each individual UI element. Instead we're going to have an array of claims, so we're going to read directly from this UserClaim table and just grab all the data and build an array of claims for that particular user. That array then gets sent back through the Web API to the security service. We'll then build a structural directive that we can use to actually read this array and determine whether or not the user can see that UI element or go to that route.

  4. Machine Setup and Getting Started Let's talk about the required tools you're going to need to run the samples for this particular course. Obviously we need all the things for Angular, Node and Node Package Manager, Angular, the Angular CLI, and TypeScript. But we're also going to need ASP.NET Core, Visual Studio Code and some Extensions, and since I'm using the database, we're going to need SQL Server, or you could use SQL Server Express. Now the code extensions that I typically use, I go to the Extensions activity bar on Visual Studio Code and I select Angular v5 Snippets, I add C#, and since I use Chrome, I'm adding the debugger for Chrome, but feel free to add the debugger for your browser that you like to use. You're also going to have to download the sample project at pdsa.com/Pluralsight. Click on the Download Starting Sample link. When you get the zip file download, simply unzip those files into a folder, and then follow the instructions in the README file. So, let's take a look at reviewing the machine setup procedures, so I have all the machine setup procedures for getting all these required tools installed on your machine, and we're going to go ahead download and setup our sample application. Once you have the zip file downloaded, go ahead and take that zip and copy all the files out to a special folder that you create. I created mine under D:\Samples, but place it wherever you like your stuff. Underneath here, you're going to find a README-1st.Setupinstructions.pdf. Now inside of here I've got instructions that if you're new to Angular, you need to set up your machine, I've got all the instructions here for downloading Node, installing ASP.NET Core, installing the Angular CLI, install Visual Studio Code, the debugger extension, all the other extensions that you need, C#, setting up SQL Server or getting SQL Server Express, and I actually have all the files for the SQL to install, or I have an MDF file for you for SQL Server Express. Next I have the instructions for creating the sample project that I sent you, and we'll go through that next.

  5. Create the Sample Project and Workspace If you look inside the folder that I supplied to you, you'll find a few folders. First one is PTC. This is where all the source is for the sample application. However, it's not a real Angular application, because I didn't want to have to worry about versioning of this software, because you may download a different version of Angular. So I just created the files that you need to run this. So that means we need to build a new Angular application and then drop these files into it. Same thing with the .NET Core API that we're going to create. We're going to also just have a few files here that you'll drop in. Other than that, we need to build everything ourselves. So let's come back up here to the Samples folder and I'm going to bring up a Command Prompt. I'll go to my D drive and I'll go to the samples folder, and what I'm going to do is I'm going to type in ng new PTC and I'm going to prefix it with ptc. So you do have to do this in order to get my sample application to work, because you need to be able to get the latest and greatest Angular version that will run this particular sample application. So this is going to take a few minutes. I'll come back when it's done. So the new project has been created, and this is exactly what I wanted to show you here. Things change very quickly in the Angular world, in the Node world, things like that. So you can see there's already an update available. So this may happen to you, and that's why I didn't want to give you all of the files that are needed for a new project, because then it would have been kind of hinged on one particular version, and you probably want to always use the latest and greatest. So that's why we did it this way. That's why I'm only giving you a few of the files. Now let's go ahead and build our next one, so let's go ahead and make a directory called PtcApi, and let's go ahead and go into that particular directory, and from here we're going to create our dotnet webapi project. So dotnet is now going to go ahead and create its .NET Core Web API project. At this point, go ahead and load up Visual Studio Code by typing in code space dot. That will load the current project, which in this case is our dotnet webapi project. Let's go ahead and say File, Add Folder to Workspace. Let's go out to PTC folder that we also just created that's the Angular project, and let's add that in. So now we have two folders in here, and one of the things it's asking, it says, hey, there are some required assets to build the PtcApi. Do you want to add them? Yes. You should go ahead and add those. So that'll just make sure that everything is going to be working. At this point, if I were you, I would probably save this as a workspace, so we could just create this here, and we'll just call it PtcSampleApplication, or something. It doesn't matter what you call it. We now have a workspace with these two projects in it, and we're ready to now start building the rest of this and getting this sample application to work.

  6. Add Sample Files into Sample Project The first thing we want to do is add Bootstrap to our PTC Angular application. So we've got the PtcApi, which is our .NET Core Web API project, and we have our Angular project PTC. Right mouse click on that, and say Open in Command Prompt. What we want to do is npm install bootstrap3. I'm using version 3 in this particular case. And also we want jquery. So let's go ahead and install those into our Angular project here. Once we have those installed, we're now going to start copying in the sample files that I gave you from within the zip file that you downloaded. So let's come over here to your explorer window, find this folder, and there's the PTC. Go ahead and copy everything from the PTC to the clipboard, go back up, come down into the PTC, and paste those in. It's going to tell us that there's some files with the same names. That's fine, let's go ahead and replace the files in that destination. Go back over to the folder you downloaded, go to the PtcApi and let's do the same thing. Copy these, and let's paste these into the PtcApi project that you created, again, replacing any files with the same names. We've now got all of the src for our sample application inside of here. The only thing we're really missing is the database. And again, if we go back to the folder that you downloaded, there's a SqlData. This folder has a .sql file if you're going to install into a local SQL Server or maybe one on your server somewhere. It also has a SQL Server Express .mdf and .ldf file. So let's copy this folder. I'm going to put it in my samples folder, so that' it's at the same level as my other two projects. So now there's one last thing we have to do, and that's modify the connection string. So if we go and we look into the Model folder, you're going to find a PtcDbContext. So this is the entity framework here. And I've already got a connection string right here. It's just one that's saying I'm going to use LocalDb. So if you're using SQL Express, you can modify this. All you have to do is maybe modify the path here. So I'm using D:\Samples\SqlData. Yours may be installed somewhere else. Just modify this and you should be fine.

  7. Run the Web API and Angular Project Okay, just a couple more steps and we should be ready. First off, go to the PtcApi. Go down to the debug area here. And let's go ahead and start the debugging on that. This will restore all the packages needed for the .NET Core Web API project, make sure everything builds correctly, and then it should run. And what this will do is help us check out our connection string and make sure that everything's working. So it goes to localhost 5000, I'm going to do a /api/product, and if I'm able to connect up to that database, I should get a JSON array of product objects, which we did. Great! Our .NET Core Web API project is working just fine. Let's now close this down. Let's go back over to our PTC application here and open in the Command Prompt, and now you can type in npm start. And it will then go through the compile process now for the Angular application. So it's just going to take a few seconds here to actually get this thing going. Great. We should have compiled successfully. Go back to the browser. Type in localhost:4200, and if you've done everything correctly, you should see our home page. We then have a products list, so this is retrieving the data from your SQL Server here. We're allowed to add a new product. We can edit a new product. We can delete a product. We can see a list of categories. This button doesn't do anything, it's just here to show us on how to secure buttons. But this is our sample application that we're now going to start learning how to secure.

  8. Module Summary In this module, we saw what our security architecture is going to look like throughout this whole course, so we've got three different security architectures we're going to be working with. We also learned how to set up your development machine and the sample application, and finally, we took a short tour of the application that we're going to secure. Coming up in the next module, we're going to start creating the client-side user authentication system and returning a user authorization object. I hope you'll join me for the next module.

  9. Authenticating a User Module Introduction and Security Architecture Hello everyone, Paul Sheriff here with Pluralsight. This module is Authenticating a User. Now the goals for this particular module are to create a user and a user authorization class, create our login mocks that we can authenticate against, create a security service that will return our authorization class, and of course, create a our login page. Let's get started. Let's review our security architecture using mocks. We're going to build the login page and we're going to build this user class that has a username and a password in it. We're also going to build our security service and we're going to build an array of mocked logins that we can validate against. We're then going to return an authorization object from this security service, and we're going to use that then to turn menu items off and on, like the Products menu, the Add New Product button, and the Categories menu.

  10. Angular User Classes The first Angular class we're going to create is our user class. We'll give it the name AppUser, then we'll add a property called userName, and a property called password. It's these two properties that we'll bind to the input fields on our login page. The next class we're going to create is our user authorization class. We'll give it the name AppUserAuth. And in this one, we're going to create some general properties, bearerToken and isAuthenticated. We'll fill in the username with whoever he gets logged in. The bearerToken we'll use a little bit later in this course, and of course, have they been authenticated? We'll change that to true once they have been. The next set of properties, canAccessProducts, canAddProduct, canSaveProduct, canAccessCategories, and canAddCategory, each one of these properties are used to bind to some sort of UI element on our different pages. So when we want to turn one on, we set this property to true or to false if we want to turn it off. Now obviously that's why for each property here there's a UI element. It's very appropriate to use this type of style for a smaller application, whereas later on we'll talk about an array of claims when you have a large amount of UI elements you wish to control. The next class we're going to create is called LOGIN_MOCKS. Now this is for the client-side authentication and authorization. We're not going to connect up to the Web API right now, we're just going to do everything client-side. So I'm going to create some mock data. And this one is going to have userName PSheriff, a bearerToken, just some sort of made up numbers, and then isAuthenticated we're going to set it to true. And for this particular object in this array of mocks that we're creating, this one is going to set a few of these properties. Most of them are going to be set to true and the last one will be set to false. Then there'd be another object for additional users. So however many users you want to mock up, you can add to this LOGIN_MOCKS array of objects.

  11. Build Angular User Classes Let's go into our Angular application and build our user classes. Back in our Angular application, the PTC application, let's expand src and let's expand the app folder here, and what we're going to do is we're just going to create a new folder called security. It's in this particular folder we'll add a new file called app-user.ts. And we'll create our class called AppUser. And it's in here we'll create our userName property and just assign it to a blank string, and well create our password property and also assign that to a blank string as well. The next one we're going to create is app-user-authentication.ts. Now this particular class, this is the one that's going to hold all of our information about the authentication for this particular user that's logged in. So, we have the userName, the bearerToken, isAuthenticated. Then we have however many UI elements or routes that we're going to secure, we add the appropriate properties. So in this case, I'm going to have access to the products path, and the button Add Product, and a button canSaveProduct. I'm also going to have access to the categories route and the button on the categories screen canAddCategory. Pretty simple to lay these out. You just need to think about all the things that you're going to secure and write the appropriate property. And the last user class we're going to add over here will be for our login-mocks.ts. Now it's in here you can add whatever you want, but I'm just going to export a constant called LOGIN_MOCKS. It's of that type AppUserAuth, so that means I need to import that from the file that I just created. We're going to create an array of these, and the array starts out and we're going to have a single object, and this first object here is for the userName PSheriff and the bearerToken here is just some made up number. They are authenticated if we get to this point, and we can access products, add product, save product, access the categories, but we cannot add a category. We then put a comma, and we add our next AppUserAuth object, filling in the userName BJones, some sort of made up name for the bearerToken, then the various things here, authenticated is true, the canAccessProducts in this case is false, can't add products, can't save products, and then canAccessCategories is true and canAddCategory is true. So this gives us a couple of different users to work with, so we can test out turning on and off various UI elements.

  12. Security Service With our user classes in place, let's now generate a new service using Angular CLI. So we'll execute this ng command in a Command Prompt and build a security service class. What we'll do with this security service class is we'll actually create an instance of the AppUserAuth object inside of there. So that will give us a property that we can access with the current security object that we get from logging in. So, we're going to need a login method that will pass in the AppUser object from the login screen, and we'll return an AppUserAuth object. We'll also set the security object property. In the logout method, all we're going to do is call a method called resetSecurityObject, and it's in this particular method that we will initialize all the security object properties to false or to an empty string, basically create a brand-new AppUserAuth, which will turn off anything that's been bound to anything, and that gives us then kind of a logout feature. In the login method, the first thing we're going to do is just re-initialize that security object, so we'll set it back to not authenticated and we'll set all those Boolean properties back to false. That way if any UI elements are bound to those properties, they will be automatically reset. Then we're going to look up in the LOGIN_MOCKS array and find the current userName where it matches the entity object that we passed in. We're then going to assign that into that security object property that we added in our security service. Now we're going to use Object.assign. I know that it's not the most efficient method, but remember, we're only just logging in really quickly, it's not like we're calling this over and over again. The reason we're doing this is we don't want to recreate the security object, because if there's any bindings to this property in this security service, it actually invalidates them, and now we aren't bound anymore. The other thing we're going to do, and this is for later when we start talking about the Web API calls, we're going to store that bearerToken into local storage. So just one more thing we're going to do, and we'll see the reason for this a little bit later in this course.

  13. Build the Security Service Let's go ahead and build our security service. I saved and closed the three previous files we created. Now I'm going to open another terminal window here, and I'm going to type in ng for the Angular CLI, generate a service, I want to put it into the security folder, and I want to call it security service. I'm going to use the flat option, because I don't want it to create another folder underneath security, and I want to register this new service with the app.module. I press Enter, and it generates the appropriate files. So it gives me a unit test file, and then the SecurityService class itself. Inside of here, I want to import a couple of new classes, Observable and the of. So these come from rxjs, and we'll see those, why we use those, in just a minute. So I'm going to use securityObject, I'm going to create this object that we talked about, this public property that I can reference from the SecurityService, and it's going to be of the type AppUserAuth. Now I haven't imported that yet, so I'll hit Tab and let code do that for me. And then let's just create a new instance of that AppUserAuth class, and there we go. We now have our property that's ready to go. Another method we're going to add is resetSecurityObject. This is the one that I told you gets called from the logout, and it also does get called from the logged in method that we're going to create as well. As you can see, all it's going to do is reference the securityObject property and change each one of its properties to a default value. In this case, userName and bearerToken get set to an empty string, isAuthenticated gets set to false, and then canAccessProduct and all the other ones gets set to false as well. And then the last thing I do is I remove from localStorage that bearerToken. Next let's add the login method. Now, our login method, it's going to accept an AppUser object here. So we need to fix that up and import that in. There we go. Now it's going to return an observable of the AppUserAuth, or authorization object. As I mentioned, the first thing we're going to do is call this.resetSecurityObject. Now we don't have LOGIN_MOCKS. We need to import that as well, so we can use our little light bulb here and import that guy. And now we're going to use this Object.assign, and the first argument then is the name of the property that we want to assign to, and the second one is what we're assigning from. So in this case, we're going to access that LOGIN_MOCKS array and find where the userName is equal to the userName that got passed in. If we find it, great. We're going to check and make sure that we found it by checking the userName, make sure it's not equal to empty string. And if we found it, we're going to go ahead and store the bearerToken into local storage. Now as I mentioned, we're going to look at why we do that a little bit later when we talk about the Web API. But at this point, we now have the bearerToken stored in local storage and we've assigned into our securityObject property, so we now have everything we need to kind of bind this up to any UI elements. The last method we need is our logout method, and this one's really simple, we're just going to call this.resetSecurityObject. Remember that's going to just wipe everything out to some default values, not wiping out the security object, so all the bindings are still going to be in place with anything that's bound to this security object, which we are going to do, but it's going to reset all of these so that means anything that's bound like, it says, hey, I'm looking to whether to make this invisible or not, it can actually make that go away once this resets to false, because that's probably what you'd want to have happen when somebody logs out. You don't want to take menu items away, for instance.

  14. The Login Page We're almost ready to try out our authenticating user. But we need to build our login page, so again, we'll use the Angular CLI to create a new component. We'll create a page that looks like the following, this will just use some Bootstrap styling here, and then we're going to bind the inputs of that user object to the inputs on that screen. So, we're going to use the banana in a box with that ngModel and assign that equal to the userName and also bind up the user.password. Now we're going to add two properties to the login component. First off, we're going to add one that creates a new instance of the AppUser, we call it user, so that's what we use to bind in the previous slide, and we're also going to use the user authorization object, so we're going to bind up that guy as well. And I'm doing this just to show the return data. We don't really need this property for the working application, I just want to show you the authorization object that comes back. The way we display that securityObject is simply in a bunch of divs with a label. We're going to do securityObject piped to json. And that will actually display the json stringified version of our securityObject. Again, we don't really need this for the working application, but it's a good way to show the authentication and the authorization happening. The last thing we have to do is open the app-routing module and add a new route to the login page. So we'll add a new path and a new component.

  15. Build the HTML for the Login Page Let's take a look at creating our login page and trying out the authentication. In our Angular application, go to the terminal window and type in ng g c for component, and let's put the login component into our security folder, keeping the structure flat, and registering with our app.module. Press Enter, and as you can see, it creates four files for me. Those are now under the security folder. Let's bring up the login.component.html and let's build our page. The code we added into the login.component.html consists of a series of rows. So the first row, the second row, and then the third is the form. Now the first row simply has a div in it here that has an alert, a Bootstrap alert. We're using a structural directive, the ngIf, to make sure the security object exists and not isAuthenticated. If they're not authenticated and the security object exists, which means you've clicked on the login button and it came back as not authenticated, we're going to display a message called Invalid User Name/Password. So that's the first row, pretty simple. The second row is again not needed for our production application, but I'm using it just to point out what comes back from our security service. We want to just pipe out the securityObject as a json string, so we can take a look at it, and that's all we're doing with that particular line of code. Let's take a look at the last bit, and that's the form. Now this is the most important part, because this is what the user's going to really interact with. So again, I've got a Bootstrap row, a Bootstrap column here, we have a panel, we then have a heading for that panel that says Log in, so this is going to make it look exactly like the form you saw on the slide there. We got the panel-body. What's really important here, of course, is binding to the user object that we're going to create an instance of and binding to the userName property for this input field, and for the second one, it's then binding for the password. So basically each one of these is wrapped up in a panel. We've got a panel and inside of the panel-body we've got a form-group, and this form-group is, the first one is for the userName, and the second one then, form-group here, this one is for obviously the password. So again, we have a label, we have the input-group, we have the password, input field that's bound to the user object we're going to create, and the span. Then down in the footer, we're going to have our login button, and we're going to map that to the login method, we're going to create in the LoginComponent class.

  16. Build the Login Component Let's now go over to the LoginComponent class and let's create the objects we need to bind to the HTML. First off, we wanted a user property that's of the type AppUser. Press Tab to import. Create a new instance of that AppUser object. We also are going to temporarily add our securityObject that is of the type AppUserAuth. Again, hit Tab. And make sure you set this one to null. If you remember, we want it to be null when we first come in, so that this p tag is not displayed. Only after we hit the Login button do we want this to show up if the user typed in an invalid userName or password. To be able to get this security object, we need to get and use the security service. So let's create a private property here that we can get by using our SecurityService and using Angular injection to have it automatically inject the securityService for us, and inside of here right now that we've got that, we can now add a login method inside of this LoginComponent class. So this one, we just simply use our securityService, call the login method, passing in this .user. Remember that's going to be bound with the userName and the password that we get from the user, and as long as everything happens okay in the subscribe, we're going to get a response back that we can then simply say this.securityObject is = our response object that we get back. Pretty darn simple. So there's our whole component that is now matched up to the HTML page.

  17. Add Login Route and Login Menu Well, we're almost ready. All we have to do now is add a new route. And then we'll be ready to display this thing. So let's create a new route, let's just copy an existing route, and then give it the path of login. Let's choose our LoginComponent, hit Tab, and it'll import the appropriate file. Then let's go over to our app.component.html. This is where our menu system is. You can see the menu system right here. But let's add a new one underneath here. So we're going to add a new ul, and we're going to give it again some styling, just like we did on the other one, nav navbar-nav, but we're going to add on navbar-right. We want to pull this login menu item to the right. So let's do an a routerLink="login." And the word that we want to have displayed will be Login. So now that we have the route, we have the menu system, let's go ahead and save all of our changes here. Once they have been changed, we should be able to flip back over to Chrome here, here we are. We see our log in, and there's our login screen. Now you see the null up here. So the null is there, because that's that securityObject which we assigned initially to a null value. Again, this isn't needed for the final production application, but it's nice to be able to see this so that when I log in with some username-- remember, the password doesn't matter right now, we'll fix that up later when we do the Web API-- but what happens is when I log in, I now get that user authorization object returned. So there's our PSheriff, there's our bearerToken, we can see these values are set to true. And let's see, the canAddCategory for PSheriff is false. Now if we change this and we log in as bjones, you'll see the userName is changed, the bearerToken is changed, and some of these values now have been changed as well, because he has a different set of claims or authorization that he's allowed to do. And again, if we put in some bogus name that isn't in our LOGIN_MOCKS array, now we're going to get an empty security object and that message that we created in that first row in the HTML is going to be displayed.

  18. Module Summary In this module, we created the user auth classes, we created our security service, we created our login page, and then we viewed the authorization object after successfully logging in. I hope you'll join me for the next module where we're going to talk about using directives to secure the UI elements and adding route guards to secure navigation.

  19. Secure UI Elements and Guard Routes Module Introduction Hello everybody! Paul Sheriff here with Pluralsight. This module is Secure UI Elements and Guard Routes. The goals for this particular module are to make menus invisible or visible, based on that user authorization object we created in the last module. We're going to also look at making buttons visible and invisible. We're going to also prevent direct navigation to a route by adding in route guards, and we're going to redirect to a login page if the user tries to access a route they can't get to in order to ask them for credentials that could be used to get to that particular route. Let's get started.

  20. How to Secure Menus In order to secure menus, we're going to modify the app.component.ts. We'll add that security object, right? So that's that AppUserAuth class, we're going to create an instance of that here in the AppComponent. We'll inject the securityService that we created and we'll grab the securityObject from that securityService and put it into the securityObject that we create here in this component. This is what we can then use to bind up to the menus. We're also going to add a logout method, and that logout method then will call the logout method in the securityService, so that we can clear everything, and then that way the menus that we bind up to may change based on that logout. Once we have the securityObject on the app.component.ts, we now open the app.component.html page, and this is where we can now add the structural directives to access that security object and then the appropriate property that lines up with that particular menu. So as you can see here, we've got the routerLink for products, where we are accessing the canAccessProducts, and we have the routerLink for categories where we access the property canAccessCategories. So all we're doing is binding up those properties from the AppUserAuth object to the appropriate menu items. Another way we're going to manipulate menus on our app.component.html page is to toggle the login words from login to logout. So what we'll do is if it's not authenticated, right, so we're going to check our securityObject here, isAuthenticated property, if it's not authenticated, we'll display the word login. If it is authenticated, so that means we've already logged in, we'll toggle this menu so that now this new one shows up that says logout, and then uses the userName of whoever's logged in. We'll also, as you can see on there, add the onclick ="logout" and we'll call that logout method that we talked about earlier.

  21. Secure the Menus Now that we've talked about what we're going to do, let's go ahead and drop down into Visual Studio Code and secure our menus. Let's open the app.component.html. If you remember in the last module, we added a new menu item here for login. Well, we only want that login menu item to show up if the user is not authenticated. So let's add a structural directive, and inside of here, we'll check the securityObject.isAuthenticated property, and if it's not isAuthenticated, we'll display login. Otherwise, let's add another anchor tag here, and this anchor tag will have the structural directive that accesses the securityObject's isAuthenticated, but makes sure it's true. If it's true, it means they have been authenticated. Let's go ahead and display now the logout, and let's add on the userName. We can also then modify these two menus as well, and we can also check our securityObject. Now if you remember, our securityObject, that's the one that has all of those properties like canAccessProducts. So we add that one to turn off and on the products based on whether or not this value is set to a true or a false, and we'll also add the same thing here, but canAccessCategories. Let's now go over to the AppComponent.ts and add our securityObject property that's of the type AppUserAuth. Hit Tab, so it imports the appropriate statement there, and let's go ahead and just set this to null for now. Then let's add a constructor. And in the constructor, we want to inject the securityService that's of the type SecurityService. Hit Tab again to import. And then we can access and set our securityObject property in this component by grabbing the securityService.securityObject property, and that then assigns that. Once we have that assigned, that is how we bind up now to the structural directives here in the HTML. The last thing we need to do is add our logout method. And in our logout method, we're simply going to call this.securityService.logout. And as you remember, that resets the securityObject property, and it resets all of those values so that the isAuthenticated would go to a false, which means our menu system would change. Let's go ahead and save our changes. Let's go over to Chrome, and, as we can notice, the products and the category menus have disappeared as expected, because the canAccessProducts and canAccessCategory properties are initially set to values of false. We can click on the login and we could type in psheriff, any sort of password, and click Login. We immediately get our securityObject property displayed, the products and categories menus do come up, and our logout menu now changes to Logout PSheriff. If we click on the logout, it goes ahead and redoes everything. It actually resets all those properties. And then let's go ahead and log in now as bjones, and now you can see that the products menu is gone, and we just get categories. That's because the canAccessProducts property in our authorization object here, right, is false. So that means that menu item is turned off, and again, our userName is now displayed next to Logout here. The last thing we're going to do now is we're going to go back in, I want to go into the security folder, go to the login-mocks. I'm going to change BJones so that you can access products. We're going to do some other demos here in a minute, where we want him to be able to get at the products menu, and then we'll show you some other ways that we can secure other UI elements.

  22. How to Secure Buttons Besides securing menu items, we also might want to secure other UI elements on a page. For example, let's open up the ProductListComponent.ts, and let's do the same thing we did in the AppComponent.ts, where we add an AppUserAuth object, call it securityObject, just like we did before. Inject the securityService into this component, and assign the securityObject from the securityService into the securityObject. Then we can open up the product-list.component.html and we can add the same structural directive like we saw on the product menu to the button for Add New Product. This time we're going to access the securityObject.canAddProduct property. We might also want to secure the Save button on the product detail page. To do that, we'll open up the security detail component and add the securityObject property that we can then bind to the Save button. We'll inject the securityService, so that we can retrieve the securityObject from that service and assign it to the securityObject property on this page. We'll also do the exact same thing for the category list, where we want to turn off the Add New Category. Adding securityObject property, injecting the securityService, and retrieving the securityObject. This the same design pattern we're going to see over and over again, but a little bit later on in this course, I'll show you how to get rid of all of that injecting of the securityService and we'll build our own custom structural directive. But for now, this is a very quick and easy way to get things going.

  23. Secure the Buttons Let's jump down into Visual Studio Code and secure our buttons. Open up product-list.component. Locate the Add New Product button. Let's add our structural directive, securityObject.canAddProduct. We can then go to the product-list.component.ts, and we can add our securityObject that's of the type AppUserAuth. Be sure to hit Tab there to import the appropriate statement. Then let's add private securityService of the type SecurityService and let's inject that into this component and set this.SecurityObject equal to securityService.securityObject. Next let's go over to the product-detail.component, locate the Save button, the Save button is all the way at the bottom of this particular file, and let's also add our ngIf, our structural directive, securityObject.canSaveProduct, and let's then go to productDetail.component, and let's add our securityObject property that's of the type AppUserAuth. Again, hitting Tab to make sure that you import the AppUserAuth class there. And let's also inject our securityService here as well. Again, hitting Tab, and then assigning to the securityObject the securityService.securityObject. As our last one, let's go to the category-list.component and locate the Add New Category button, add our structural directive to access the securityObject.canAddCategory property. Move to the category-list.component, and let's add our securityObject property that's of the type AppUserAuth. Let's inject our securityService, again, always making sure you're hitting Tab so it adds the appropriate import statements, and let's go ahead and assign to the securityObject the results of the securityObject from the securityService. Let's go ahead and test everything out by saving all of our changes, and let's go over to Chrome, let's log in, and let's log in as psheriff first and get our userObject here. We should be able to now go into the products and see the Add New Product button. If we click Edit, we can see Save, but if we go to Categories, we can't see the Add New Category button. Let's log out as psheriff, and let's log back in as bjones. Go into Products. We no longer see the Add New Product button. If we click on Edit, we can't save anything, and if we go into Categories, we do see the Add New Category. And again, all of this is simply because in our LOGIN_MOCKS, each of these different users that we log in as has different property values set true or false to each of these different properties, and then that allows us to control the UI.

  24. How to Create an Authorization Route Guard Besides securing UI elements, we also need to secure our routes. And for that, we'll create an auth guard. Now this auth guard that we're going to create we're going to then add to the app-routing.module. So we're going to add to the canActivate property our AuthGuard that we generate using Angular CLI, but we're also going to pass in some data. We need to tell the AuthGuard which property to access to make sure that they can get to this particular path. To do that, we use the data property, and we pass in our own object. And our object will have a claimType property and what we pass to that property is simply the property to check in our AppUserAuth object. We then inject the security service into our AuthGuard so that we can access that security object. We can grab the claimType property from the data property of the next object, and that's the ActivatedRouteSnapshot, and we put that into a local variable called claimType. We then check and make sure that the security object's isAuthenticated property is set to true, so have they even been logged in, and then we access that property name in the security object to see if it has a true value.

  25. Create the Authorization Route Guard Let's go back to code and create and connect our route guard. The first thing we're going to do is open a Command Prompt on PTC, and use the Angular CLI to generate a guard. I'm going to put it into the security folder, and we're going to call it auth. We're going to keep the structure flat, and we're going to register this new guard with the app.module. Now you can see our auth.guard has been created. I'm not going to do anything else with that right yet; instead what we're going to do is we're going to go into our app-routing.module here, and let's locate the products. Products is one of the paths that we wish to secure. So let's add on the canActivate property, and it is an array, so you can pass one or many guards. Let's go ahead and use our new AuthGuard that we just generated. Now as we need the name of the property to use to secure this particular route, we use the data property to pass in any object that we want. So in this case, I'm going to simply add a property called claimType and I'm going to pass to that canAccessProducts. So this name here needs to match up exactly with one of the names of the properties in our AppUserAuth object. So we can then copy all of this here, and we can paste it down into the product detail as well, because we need to make sure that the product detail route is also guarded, and we can use the same canAccessProducts. I mean, if they can't get to the product list, they certainly can't get to the product detail. And then the last one we'll do here is the categories, so canAccessCategories. So again, we're just looking for the name of the property in our authorization object that gets returned because those need to line up, because we're going to use this string here to access the property in our AuthGuard. Let's now go and modify our AuthGuard, so that we can secure the route. So first thing we're going to do is create a constructor, and inject our securityService, like so. Then down in the canActivate-- so the canActivate method is the one that gets called because we added the AuthGuard to the canActivate property here in the App Routing module. And inside of here, instead of just returning true, first off what we're going to do is grab that data. So let's let claimType as a string equal to next.data subscript claimType. So we're using the ActivatedRouteSnapshot here to grab the data, and that's this data object that's being passed to us. We're then specifying the name of the property we want to retrieve, claimType, and we want to grab this value, canAccessProducts, or canAccessCategories. So we grab that and we put it into the claimType. Now what we're going to return then is first off, let's check and see if the securityService.securityObject.isAuthenticated is that equal to true? So we can't even get to the route if we're not authenticated. And this .securityService.securityObject dot-- or, not dot, we're not going to use the canAccessProducts or canAccessCategories; instead what we're going to do is we're going to use the value that comes from the claimType. Right? Remember we can use JavaScript to access a property via a string value. So that's why it's very important that these names here match directly up to the appropriate property names in the security object. So that's canAddProduct, canSaveProduct, canAccessProducts, canAccessCategories; so those names must be exactly the same, so that we can find out if the value is set to true. Let's save all of our changes, and if we've done everything correctly, we should be able to go to Chrome, and we've not logged in or anything, we're at the login screen, but let's try without being logged in just directly to products. Now if we've done everything correctly, nothing should happen. We can't get there, because the route guard is saying, sorry, you can't get to that because you're not logged in, which means that you don't have that permission set. Now it'd better if we were to redirect to the login page instead of just giving them a blank page here. Let's do that now.

  26. How to Redirect to Login Page As I mentioned, what we want to do is if we're not authorized for a route, instead of just getting a blank page, let's redirect that login page. We'll pass the page that we requested to the login page as well, and store that requested page in the login component. We'll ask the user to enter their credentials on the login page, and if valid credentials are given, we then redirect back to the requested page. If not valid, we simply redirect back to the login page. The way we accomplish this is we modify our AuthGuard that we created and inject the Router class. Then we modify the return statement that we had previously to an if and an else statement. We first use the same exact code that we had before, but we just check that and then return a true. In the else portion is where we grab the state.url. This has the url of where we are trying to get to, the route we are trying to, and it adds it to the queryParams object. We then navigate to the login page, passing in that query parameter that has the return URL set to the route we were trying to get to. The last thing we want to do is then modify the login component and add a returnUrl property, add in the ActivatedRoute and the Router objects. So have Angular inject those. In the ngOnInIt, set that returnUrl by accessing the route, that's the activated route, .snapshot.queryParamMap.get and accessing that returnUrl property that we created in our AuthGuard. Then, if everything is successful after we've logged in, we have valid credentials, we're going to use the Router object to navigate back to that returnUrl. Let's give it a try.

  27. Redirect to Login Page Open up the AuthGuard and let's inject the Router object. Hit Tab to make sure it's added to our import statements up here, right there. Now once we have that, we're going to change our return back down here, and we're going to check all of this, and we'll return true now if all of that part was correct. So that's what we were used to doing. But we're going to add an else now, because what we want to do this time now is use our router object to navigate to the login page, like so. But we don't want to just navigate to the login, we want to tell the login page where we're coming from. So we can use an object here, specify queryParams, and what we put into here is an object. We specify the name on the address bar that we want to put, returnUrl, and what is the URL. Well, we can grab that from the RouterStateSnapshot, the state. So the state.url. This will add that to the address bar when we navigate to the login screen. Well, if we've done everything correctly, let's save our changes. Let's go over to Chrome. Again, let's type in products, and now we can see here that we redirected to login, but we added the query parameter now returnUrl set equal to where we are trying to get to, products. Very nice. Same thing. If we did categories, the returnUrl now is specified as where we are trying to get to, in this case, categories.

  28. Redirect Back to Requested Route Open the login.component.ts and let's inject two new services, the ActivatedRoute, hit Tab, and the Router, hit Tab. So we now have injected these two new items. Let's add our returnUrl as a string, and in the ngOnInIt, let's set that returnUrl by accessing this.route.snapshot.queryParamMap.get and then access our query parameter that we passed in, returnUrl. In the login method, all we're going to do now is as long as everything's successful here, we'll check and make sure that this.returnUrl is filled in, and if it is, let's go ahead and use the router and navigateByUrl to this.returnUrl. So again, we've simply added on this ability now to redirect back to the page, as long as the credentials are correct. So let's give this a try. Save your changes, go over to Chrome, let's try to redirect to products. We get to the login page. Let's go ahead and log in with someone that we know has credentials to get to products, and click Login, and we're right to products where we wanted to be. Excellent. If we try to get to categories, same thing. And again, any one of those usernames that we have allows us to get there, so we'll automatically go. If we had one that was not allowed to get to that route, it would simply stay on the login page.

  29. Module Summary In this module, we added structural directives to secure menus and buttons. We created a route guard to protect navigating to a route that we're not allowed to get to. If we weren't allowed to get to that route, we redirected to the login page, and once we were authenticated, we redirected back to the requested page. In the next module, we're going to talk about user authentication via the Web API and we'll return that user authorization object from the Web API. I hope you'll join me for the next module.

  30. Call Web API to Authenticate and Authorize Module Introduction and Security Architecture Hello, this is Paul Sheriff with Pluralsight. This module is Call the Web API to Authenticate and Authorize. The goals for this module are to look at the SQL Server security tables that hold our users and our claims. We'll build Entity Framework classes to access those SQL Server security tables. We're also going to build an application user authorization class that will get returned from our call to the Web API. We're going to build a security manager class, and this is the class that actually goes out and gathers the data from SQL Server, validates the login, things like that. We're also going to build a security controller class. And we're then going to call all of this from Angular to be able to authenticate from Angular through the Web API. Let's quickly review our security architecture that we're going to use for the Web API. We've already created our login page and our user object in Angular. That's not going to change. But we are going to modify our security service now, and that security service is now going to call the Web API instead of using those mock logins. The Web API is going to access our SQL Server, in which there are two tables. The user table, and the user claim table. Then we're going to build an authorization object. This object looks exactly like the one that we built in Angular, and this is what then gets returned from the Web API back to our security service. So, let's go ahead and get started.

  31. Entity Framework and Authorization Classes This is a diagram of the security tables that we have in SQL Server. Now, we have a user table, which we're going to just create very simply right now. It's just going to have a UserId, a UsaerName, and a password. Of course, feel free to add on anything else that you want. We're also going to have a UserClaim table. Now this layout is very similar to the ASP.NET Identity tables. So if you've used the ASP.NET Identity system before, this should look very familiar. So each user simply has a set of claims that they can be assigned to. So that way we can assign claims like canAccessProduct or canSaveProduct to each user. It's just that now they're stored into separate records in this table. Here's an example of the user and the UserClaim table. Now the user table contains user information for logins, so we have a UserId, a UserName, and a password. Now, of course, I have plain text here for the password that's not secure, and if you're using like the Microsoft ASP.NET Identity system, of course that's going to be secured by hashing or by encryption or whatever you choose when you set that up. I'm just trying to keep it simple for this particular project because that's now what we're focusing on here. The UserClaim table, what we have in here is a set of ClaimTypes for each user. So we map each user's ID to a set of ClaimTypes. These ClaimType value matches the property names that we created in that AppUserAuth class. You want to make sure they match exactly, because we're going to use reflection to map these ClaimTypes to each individual property, and then we'll assign a ClaimValue of true or false or some other value to each one of these ClaimTypes. Now if a user does not have a ClaimType, you can just leave it off, and it will be assigned a default value of false. And we'll take a look at that a little bit later. We're now going to create the classes that map up to each one of those tables. I'm going to create an AppUser class. It's going to then map to that user table through the use of data annotations. We're going to put those user and the UserClaim tables into a security schema. We then add the appropriate properties and the appropriate data annotations to map the properties in this class to the fields in that user table. Next we create an AppUserClaim class. We map this up to the UserClaim table, and again, add the appropriate properties and the appropriate data annotations to do the mapping.

  32. Create Entity Framework Classes Let's go ahead, drop to Visual Studio Code, and create our Entity Framework security classes. If your PtcApi project is still running, go ahead and stop that now because we need to add in some new classes. So go to the Model folder, right mouse click, and choose New File. Type in AppUser.cs, and let's create our Entity Framework class. You're going to add a few usings here. Most of these are for the data annotations. We're going to put it under the namespace PtcApi.Model, and this is where we add our data annotation for the table to map it to the Table User and to the Schema Security. And we've got a public partial class AppUser. We add our appropriate data annotations and properties to match up to each of the fields in the SQL Server. So this is mapping to each of those fields that I showed you in the slides for each of those tables. Next go to the Model folder, add another new file, this one called AppUserClaim.cs. And in this one, you're going to add the same using statements that we had before. Let's put it under the same namespace, PtcApi.Model, add our data annotation for the table to match this to the UserClaim table and the Schemas in Security. Add a public class here called AppUserClaim. And again, add the appropriate properties and data annotations to map each one of the properties here with those fields in the UserClaim table. To finish our Entity Framework, go ahead and click on the PtcDbContext. We need to add those two new classes, we need to add them now to our DbContext. Best thing to do, just copy one of the existing DbSet properties here, call this one AppUser, and give the property name of Users. Copy again. Go ahead and do AppUserClaim. Now you notice this one didn't show up. I'm actually glad this happened, because this does happen every now and then with code. It doesn't always get the class for whatever reason. So a couple things you can do is if this happens to you, you know that you just added everything correctly, that is the same name, you could copy and paste that name there and you see it's exactly the same. Go to Tasks and say Run Build Task, like so. And just make sure that everything compiles. As you can see, 0 Errors and 0 Warnings. At this point, simply close code and reopen it and everything should be just fine. I'm going to go ahead and do that offscreen.

  33. The User Authorization and Security Manager Class Now that we have the Entity Framework classes created to read all the data from the SQL Server tables, we're going to use those to fill in our AppUserAuth class. Now this class is exactly like the one we built in Angular where we use it to control UI elements. So we're going to have all those same user information properties, user name, bearer token, is authenticated. Plus we're going to have our UI control properties. These are the ones that we use to turn on and off menu items and buttons. So make sure these all match the same names in our Angular class. It's also important that each of these map to the claim type in the UserClaim table that we saw as well. We want to have the same property names as the ClaimType, and I'll talk more about that when I talk about how we build this AppUserAuth class. To create the AppUserAuth class that we just saw, we're going to build a Security Manager class. Now this class is going to have a few methods. The ValidateUser method is going to validate the user name and the password against the SQL Server table, and it will return the authorization object back to the security controller that we're going to create. We're going to have a GetUserClaims method that does exactly what it says. It's going to return the claims from the UserClaims table for this specific user that's logged in. And the BuildUserAuth method, this is the one that actually maps the claims in the claims table to our authorization object.

  34. Build the AppUserAuth Class Let's go ahead and build our authorization class and our security manager class. Go to the Model folder, right mouse click, create a new file, AppUserAuth.cs. Put it under the namespace PtcApi.Model. Create a public class, AppUserAuth. Let's create a constructor where we fill in the UserName to be Not authorized and a BearerToken of string.Empty. Let's then fill in and create all the rest of the properties that we need, the UserName, the BearerToken, IsAuthenticated, and all of our UI mapping elements.

  35. Build the Security Manager Class Let's now go back to the Model folder, create a new file, and create SecurityManager.cs. So let's go ahead and fill in kind of the outline of all of this, which is we have a few using statements here that we're going to need. We're going to put this under the namespace PtcApi.Security. Create a public class called SecurityManager, and we got our return value of our AppUserAuth class that we just created, and ValidateUser as the method name. Now we are going to pass in the user class that we get from Angular. So Angular is going to pass the User class to us with the user name and the password. We'll pass that to the ValidateUser. We'll build the UserAuthObject method, but inside of here is where we'll call the GetUserClaims method. So all this is just the outline of what we're going to create, and then we'll start creating each of the individual methods. Let's build the GetUserClaims method first. What we do inside of here is let's create a list of AppUserClaim objects, let's just call it list, create a new instance of that. Within a try catch, let's go ahead and do a using on our DbContext, and let's access the Claims property. If you remember, we created that in our PtcDbContext earlier. Apply a Where clause, so that we can look just for where the UserId is equal to the authorized user UserId that we pass in. What's going to happen in the Security Manager is we're going to authenticate that user and get their UserId from the database. We then use that to get their list of claims. And then we return this list from the GetUserClaims method. Let's now go build the BuildUserAuthObject method. In this one, we're going to create our return value. So our return value is that AppUserAuth object. We need our list of claims. We're first going to set the User Properties so we're passing in the authenticated user here, we're going to grab that UserName and fill it in to our return value. We're going to set the IsAuthenticated to true. And we'll just assign an empty GUID to the BearerToken property, but this value will be set to a secured BearerToken in the next module. We're then going to get all the user claims. So we've got this claims list now. And now we just simply loop through each one of those claims, and I'm going to use a little bit of reflection here to say let's get the property for the ClaimType that we read in from the SQL Server table. Let's get that from our AppUserAuth object and let's set that value on our authorization object that we're returning by converting to Boolean the ClaimValue, right? So that ClaimValue field has the true or the false in it. So we simply loop through each one of those, setting the property to the specific value. If anything's not set because it's not available for that user, it gets the default value, which in this case is always going to be a false, because all Booleans are always initialized to false. So if for a specific user, they don't have the add product claim in that table for them, then this property is going to be set to false. So that's how we build up our user authorization object to return back to Angular. And finally, we're ready to build our ValidateUser method. The ValidateUser method is the one that we're going to call from the security controller that we'll build in just a minute. It's going to be passed in the user object that comes from Angular. And inside of here, we'll do a using on our PtcDbContext. We'll locate within the users where the UserName is equal to the UserName that's passed in from Angular, and the password in that user's table is equal to the password that's passed in from Angular. Of course, this code is not secure, as this is just using that plain text password that I created. In a real system, you would be using the ASP.NET Identity system to authenticate the user against the encrypted or the hashed password. We used the FirstOrDefault here to give us back either a valid user object or a null, if it doesn't find the one. If it does find that user, then obviously we're going to call the BuildUserAuthObject to build our AppUserAuth object. And that's what gets returned. We've created a new instance of this, so that everything is defaulted, so if we don't find that user, then the UserAuth object's IsAuthenticated property is set to a false value, which tells the controller that the user was not authenticated.

  36. The Security Controller Now that we've created our Entity Framework classes and we have our Security Manager class and our AppUserAuth class, we now need a controller class that can be called from Angular, and then this class is what uses all of those other classes to return a status back to Angular of whether or not that user is authenticated. So, let's go ahead and build a login method here, which accepts the User object from Angular, and that's the User object that gets filled in by the user typing into the login page the UserName and Password. It then calls the security manager to authenticate that user. So it calls the ValidateUser, passing in the User object, and what's passed back is that auth object, that AppUserAuth object. If everything's okay, we return a status of 200 and a payload is the valid AppUserAuth object. You can see the IsAuthenticated property is checked after calling the ValidateUser method. If we don't find that that user's been authenticated, which means that the user name and password was not correct, then we're going to return a status of 404, Not Found, and we can just pass back the payload of Invalid User Name/Password.

  37. Build the Security Controller Class Let's go down to Visual Studio Code and build our Security Controller class. Go over to the Controllers folder, right mouse click and choose New File, and create SecurityController.cs. The code we're going to write in here, we need a few using statements. These help us build all of the controller type stuff. Let's put it under the namespace PtcApi.Controllers. Add a Route attribute, and the name is SecurityController, and it's going to inherit from our BaseApiController that we have right here. This just has things for like handling exceptions. We create an HttpPost called login, and this is our Login method. We're accepting from the body our AppUser class. This also matches the Angular class called AppUser. We create a few different declarations here, so our action result that we're going to return, an instance of our AppUserAuth class that we're also going to make as the payload that comes back from this particular login method, and our SecurityManager class. We call the ValidateUser method, passing in the user object, that's the UserName and password, and then we get back then this AppUserAuth object. We check to see if that user has been IsAuthenticated. If they have been authenticated, we're going to go ahead and return a status code of 200, and our payload is the authorization object filled in with all of those properties set to true or false based on the UserClaim types. If they're not authenticated, we'll simply return a status of 404 and just pass back a message Invalid User Name/Password. And that's our SecurityController that we call from Angular.

  38. Changes to Security Service to Call the Web API With the Web API in place, we can now go back and modify our security service class. And we're going to create a constant to point to where that Security Controller is located, and we're also going to create a constant that we need to tell the HttpClient service that we're posting JSON login information. We inject the HttpClient service into that SecurityService, and then we modify our login method. So the modified login method is now going to call the Web API instead of using the login mocks. We pass the AppUser entity object and the http constants to the Post method. We then assign back into our securityObject located in our security service with the response that comes back from the Web API, and we take that bearer token that we generated and we put that into our local storage.

  39. Call the Web API from Angular Let's take a look at calling our Web API from Angular. Expand the PTC Angular application. Under src, app, security, locate the security.service.ts file, and we need to add just a couple more import statements. We need one for the HttpClient and the HttpHeaders, and we're going to use the tap operator from rxjs. Down in here, right before the injectable, we're going to create a constant for the Security API service, and we're going to create a constant for our headers. The headers as the Content-Type, we're telling it that we're passing JSON data. Next we inject the HttpClient into our SecurityService, and we then come down and find the login method, and inside of here, this is where we wipe out what we had before, where we're using the login mocks, and instead we put in our call to our http client. So we do a post, tell it that we're passing in a type of AppUserAuth, specify the name of the URL, add in login, because remember we created a login method in our Web API. We then pass in our entity object, which is an instance of the AppUser, and our httpOptions. When this comes back, we're saying that, hey, we want to tap into the return value coming back, take the response, and assign that response object, which in this case is the AppUserAuth object coming from the Web API, and let's use our Object.assign to assign that into the securityObject. We then take the bearerToken that is returned from the Web API and we store that into local storage. Again, we'll take a little bit of a look at why we do that a little bit later on in this course. So there's our recreated login method that now calls the Web API. It's possible that this HTTP post will return a 404, so let's modify the login component to handle that scenario. So down here in our login component in our login method, we subscribe, and the subscription says, great, we might come back with something, but we also need the other part of this. And the other part of this says, hey, you know what, we may have an error. So the subscribe method, the next parameter on that, is to handle an error. So, what we're going to do is we're just going to initialize the securityObject to a blank AppUserAuth object. When we do that, what does that do? That sets the isAuthenticated property to false, which then means that this object has been not nulled, and isAuthentication property is set to false, so that means that right here, this if statement, this structural directive, takes effect, and it says, hey, you know what, we need to display this message, Invalid User Name/Password. Well, we have made a lot of changes, added a lot of classes. Now the moment of truth. Is this going to work? Go ahead and save all of your changes. Let's start back up our .NET Core Web API project. Once that's launched, if you don't have it already running, make sure that your Angular application is running as well. So we'll do an npm start. Let this start up. And if we've done everything correctly, we should now be able to log in. So I'm going to log in as psheriff. Now the password is an uppercase P, at sign, lowercase s, s, w, 0, r, d. So they only one that's uppercase is the beginning P, so it's P@ssw0rd. Let's go ahead and click Login. Now it's calling the Web API. So we come back now, and you can see that we've got a bearerToken, which is just an empty GUID, which is what we assigned it to, and that's what we wanted for now. We're going to generate a bearerToken a little bit later on. But you can see we've now been authenticated against the Web API. Everything still works as it was supposed to, based on the data that's now in the SQL Server. Let's log in now as bjones. Same password, P@ssw0rd. Again, empty GUID. That's fine. We're going to talk about that next. But then we still can see now he can't add products, he can't save products, but he can add categories. So it's all now based on the data that's in the SQL Server, no longer those login mock that we created earlier. Since it is no longer relying on the login.mocks, we can delete this whole class, go into the Security Service, and make sure you remove the import statement from that class. Save everything. And we now have everything working and authenticating against the Web API.

  40. Module Summary In this module, we learned how to authenticate the user by calling a Web API method instead of using our local mock data, because this is a little more real world now. We also returned that authorization object from the Web API back to our Angular application, and we saw how to use reflection to map the claims in our ClaimTable to the properties in our authorization object. Coming up in the next module, we're going to learn to use JSON Web Tokens. We'll talk about what are bearer tokens and how to generate a bearer token using the JSON Web Token system. I hope you'll join me for the next module.

  41. Use JSON Web Tokens to Secure Web API Methods Module Introduction and Goals Hello, Paul Sheriff here with Pluralsight. This module is Use JSON Web Tokens to Secure Web API Methods. The goals for this particular module are to secure the Web API with the authorize attribute, set up JSON Web Tokens, read JSON Web Token settings from a configuration file, build a bearer token and send that to Angular. Let's get started.

  42. Add Authorize Attribute Our first step is just to secure the methods within one of our controllers. So we're going to add the Authorize attribute. And I just want to show you what happens when you add this. So let's go down to Visual Studio Code, secure a Web API method, and watch the error as it happens. If your Web API project is still running, go ahead and stop that now. Open the Controllers folder and open ProductController.cs. Just above the Get method, add the Authorize attribute. Choose our little light bulb here, and have it add the appropriate using statement. From here we can go ahead and restart the Web API. Once this builds and gets running again, we should be able to go back to our regular application. Make sure your Angular application is still running; if not, go ahead and start it. Then just log in as either psheriff or bjones. Once you're logged in, click on the products page and nothing's going to happen, nothing's going to come up. If you go into the console, you'll see that we're receiving a 500 Internal Server Error. The reason why is we don't have any way to authenticate back to the Web API that this person that we're requesting data, hey, you know what, we're not authorized. We don't have any authentication, so it doesn't know who we are, we're basically anonymous to it at this point. So that's what we have to add, and that's the purpose of the JSON Web Tokens is to do that authorization and the authentication of course as well. So, let's learn how to do that now.

  43. Add JWT Packages to Web API Project We have quite a few steps to accomplish in this module. First, we need to add the JSON Web Token package to our Web API project. We have to add the JSON Web Token bearer token checking package to our Web API project. We have several settings that we have to use to configure JSON Web Tokens. We'll store those in a configuration file. We're going to register JSON Web Tokens as the authentication service for our Web API. We're going to add bearer token options to validate the incoming token, and we're going to build the JWT token that we put into that bearerToken property and return that in our authorization object. The first two steps are to use .NET Core to add these packages to our Web API project. The first one we call dotnet add package and we use System.IdentityModel.Tokens.Jwt. That adds the Jwt token system. Next we add our JwtBearer token checking system, and that's using this command dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer. Let's take a look at adding each one of these packages. Before you add a new package, make sure you stop your Web API project. You can then come down here and add a new terminal window for the PtciApi folder. This will allow us to insert some new packages into the Web API project. And we do that by specifying dotnet space add space package System.IdentityModel.Tokens.Jwt. Press Enter. Now it goes through, it grabs some things from the internet, brings them down, and writes some information into the PtcApi.csproj. It then comes up and says, hey, you know what, there's some unresolved dependencies here. Let's execute the restore command to continue. Click on the Restore button. It should just take just a couple of seconds here and we're done. Next go back to the terminal, and this time add dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer. This is the bearer token checking package that we're going to add. Again, it goes up, grabs some appropriate packages, installs them into the csproj, and then tells code that it needs to restore some packages, so click the Restore button. Click on the Restore button, again, it just takes a couple of seconds, and we're now done.

  44. How to Configure JSON Web Token System In order to use the JSON Web Tokens system, we have to configure it. And there's a few pieces of information that we need. We need a secret key that we used for hashing the data that's sent to the client, we need the name of the issuer of the token, the intended audience of the token, and how many minutes to allow the token to be valid. Since we're going to need these four items throughout our application, let's not hard-code them into the application. Instead, let's store these items into the AppSettings.json in the Web API project. We'll also create a class called JwtSettings in which we're going to have the same properties for the same fields that we created in that configuration file. So these will just hold all the data that we need for generating the JSON Web Tokens. Of course, we're going to need a method somewhere in our Web API project, and we'll put it into the startup.cs, and we'll call this method GetJwtSettings. And of course it does exactly what you would think. It creates a new instance of that JwtSettings class, and then reads each of the configuration items from the config file and places them into the appropriate properties in that class. And then it finally returns the settings from this method that we can then use throughout the application.

  45. Add Settings to JSON File and Read the Settings Let's go back to Visual Studio Code and store those JwtSettings into the AppSettings JSON file. Let's create the JwtSettings class, and create the method to read those settings. Our first step is to open appsettings.json. And as you can see, they've already got a couple of different settings in here, but we're just going to add a new one to this object. And it's going to be called JwtSettings. Into this new property, we're going to create another object that has properties, a key, the issuer, the audience, and minutesToExpiration. Now the key can be whatever you want. Please use some sort of very long convoluted string so no one can guess what this secret key is. The issuer is the url of this Web API project. The audience can be whatever we want to call it; in this case, I'm using PTCUsers, and how many minutes until this particular token then expires. Next we need a class to hold all four of these, so come up here to the Model folder, right mouse click, and create JwtSettings.cs. And this is where we'll create the public class JwtSettings. We have a string that's the key, a string that's the issuer, a string that's the Audience, and finally, an integer property MinutesToExpiration. Open the Startup.cs. And in this particular class, we can see we've already got a few methods in here. This is all standard ASP.NET stuff. But we want to add one more additional method in here. And the method is GetJwtSettings. And it's going to return an instance of that class we just created. So, create an instance of it, I just called it settings, and we're going to set into each of those properties whatever we get from the configuratnoi file. So we use the Configuration object, JwtSettings:key, Configuration object JwtSettings:audience, JwtSettings:issuer, and for the MinutesToExpiration, just make sure that you convert that to an Int32. Once all of these properties are set, we can just return this new instance from this method.

  46. How to Setup Authentication in the Web API Project The next step is to register that JSON Web Token system as the authentication provider in the Startup class. So in the ConfigureServices method, we're going to add a new instance of this JwtSettings by calling the GetJwtSettings method we just created. The next thing we're going to do then is add the Authentication object to the services. So the services are passed in from ASP.NET Core into the ConfigureServices method. We type in .AddAuthentication, and in the options we set the DefaultAuthenticateScheme and the DefaultChallengeScheme. In this case, we're going to be using both the same, the JwtBearer token checking service. Just below that AddAuthentication, add on .AddJwtBearer. We pass in the name, the token, JwtBearer, and then we set the JwtBearer options, and this is where we set up now all of the different parameters. Basically use that Settings object that we just got an instance of and we grab the key and the issuer and the audience and the MinutesToExpiration. And all of these go in to make up what's called a TokenValidationParameter. And this parameter then has all of those settings that we need to be able to generate a bearer token that gets sent back to Angular. The last thing to do to register this service is in the Configure method we have to tell the Web API project to use the authentication that we just configured. So in the Configure method, we call app.UseAuthentication.

  47. Setup the Authentication in Startup.cs Let's go to Visual Studio Code and set up JWT as the authentication method, add all those bearer token parameters that we just talked about, and tell the Web API to use this as our authentication method. Open the Startup.cs, and locate the ConfigureServices method. In here we're going to add some code. This code, first off, declares our intention to use the JwtSettings class that we just created, and then we call that GetJwtSettings method that we created to get an instance of that. Then to the services, this is the parameter that gets passed by ASP.NET Core, we're going to add on authentication. And to this options we're going to create an object that the options.DefaultAuthenticateScheme is JwtBearer and DefaultChallengeScheme is JwtBearer. We then add our JwtBearer with the same name here, and we set our options. Now the options are an object, and inside of that object, it's a JwtBearerOptions.TokenValidationParameters. So we're going to create a new TokenValidationParameters. You will have to fix this up and use the Microsoft.IdentityModel.Tokens namespace. We're going to System.Text here for our encoding. And then let's go through this. So the first thing we do is we're saying that we're going to validate an issuer signing key, so yes, we're turning that on. The IssuerSigningKey is now this new symmetric key that we're going to generate by getting those bytes from the key that we stored over here. That's this big long key that we created. So we're now creating this new symmetric key. We want to validate the issuer, and so we then have to give it a valid issuer, so that's that name. In this case, it was the URL, right, to this particular Web API project. We also want to validate the audience, so we set that to true. And again, the ValidAudience name is settings.Audience. All of these things together are going to make up this bearerToken. What's neat about this is that all of this kind of helps us validate that that token is valid when it goes out, and that it's the same token and that we can validate it when it comes back. So we're going to have to pass it back and forth for each web call. We also want to validate the lifetime of this token, so we set that property to true, and the ClockSkew is simply the time span from minutes, and that's the number of minutes to expiration, which as you remember in the settings JSON file, I set it to 10. So there we've now configured our authentication. The last thing we have to do down in the Configure method then is simply type in app.UseAuthentication so that the Web API project here knows that we're using the authentication that we configured.

  48. Create Singleton of Settings What we just created was a configuration object that tells us what data is going to be basically hashed and sent down to the bearerToken. Now what we need to do though is take those same settings and give them to our security controller. So what we need to do is we need to create a singleton of that JwtSettings class, and we do that by saying services.AddSingleton, and we pass in an instance of that settings object. This is going to allow us to then use dependency injection that's built into ASP.NET Core and inject those settings into the security controller, so that we can pass them to the Security Manager, which is where we're going to build the bearerToken. You should still have the Startup.cs file open. Scroll up to the ConfigureServices method, and let's add services.AddSingleton. It's of the type JwtSettings and we're going to pass in the settings. So what this does is this creates a singleton of JwtSettings so that we can then use dependency injection and inject that into the security controller.

  49. Inject Settings into Controller and Security Manager Now that you've injected that, we can use dependency injection and in the SecurityController's constructor, we can have ASP.NET Core automatically inject that Settings class into there. All we need to do is place that into a field variable that we can then access whenever we make a method call from our SecurityController. Since we're going to be building the bearerToken in the SecurityManager, we need to do the same thing here in this class. We're going to create a constructor that accepts the Settings object. Again, place that into a field variable. Within the login method in the SecurityController, we're going to pass the settings that we got injected, we're going to pass those to the constructor now of the SecurityManager. So we just modified the SecurityManager, we can now pass those settings to that particular class. Let's go to Visual Studio Code, inject the JwtSettings class, and pass those settings to the security manager. Open the SecurityController.cs, and add a field that is of the type JwtSettings, we're going to call it _settings, and create a constructor for this SecurityController that ASP.NET Core can inject an instance of those JwtSettings. We then take those settings passed in and assign them to the field variable here. Next, open up the Model folder, go to Security Manager, and at the top of this class, let's do the same thing. Create our field variable, create a constructor that passes in the JwtSettings, and assign the settings to our local field variable. Once you create this, you'll notice that code highlights that we have an error in the SecurityController file, so we go here and we find out that the SecurityManager needs an instance of that JwtSettings, which we've already created here in this settings field variable, so simply pass that along to the SecurityManager.

  50. How to Create a JWT Token We're going to modify the SecurityManager class, and we're adding on a method here called BuildJwtToken. What goes into the token is a list of claims. We're going to pass in the authorized user object into this BuildJwtToken, we'll create a list of claim objects, these come from the JwtSystem, and we're going to add to this JwtClaims list new Claims. We'll add a subject and a Jwt ID. So the subject is the username, the Jti is the Guid.NewGuid. So this gives us a real NewGuid, not just an empty one, like we had last time. We then add on all of the claims that we have properties for in our UserAuth object. So for each one of our properties, we add an individual claim with the name of the claim and the value for that claim. The value is either true or false. After creating our list of claims, we're now going to create a new JwtSecurityToken object. We'll take that list of claims and add it to the claims property, and we'll add in all the other properties from our Settings object, the Issuer, the Audience, the Expires, and our credentials from our key that we create from our key. And then finally, we write this token and that creates a string representation of the JwtToken that's returned from this method.

  51. Create the BuildJwtToken Method Let's go add this method to the SecurityManager class to create the token. Open the SecurityManager class and locate an area down here, maybe just above the BuildUserAuthObject method, or anywhere really, doesn't matter, and we're going to add this new BuildJwtToken method. The first thing we need is a SymmetricSecurityKey that comes from MicrosoftIdentityModel.Tokens. So we're going to create a new one of those by encoding the bytes that we find in our JwtSettings class key property. So we need System.Text as a using as well. We can now create our standard jwtClaims. This is the minimum required to build a JWT bearerToken. We're going to create a list of claims, we're going to add a new claim, which is called JwtRegisteredClaimNames.Sub. This gives us our subject, and that comes from the System.IdentityModel.Tokens.jwt, and to the subject, we're going to pass in the UserName. For the JWT ID, we're going to go ahead and use a NewGuid here. So remember before we just created a NewGuid and it was empty, it was a blank. We're now going to use a real GUID. Next we add in the custom claims, and these are the claims that we get from our UserAuthorization object, so the IsAuthenticated property, the CanAccessProducts property, the CanAddProduct property, et cetera. And we just create a new claim for each one of them, giving them the name, same name as what we find as our property name. So for each one of those, and then we pass in the ToLower representation of the string value. So true would be lowercase true, or false, depending on what the value is set to. Finally, we create our JwtSecurityToken class, and we pass to it these properties. The issuer comes from our _settings.Issuer property, the audience comes from the Audience property. Here's that list of claims that we just created are now passed in the claims property. We don't want this token used before the date as of right now. And it expires in 10 minutes from now. And our SigningCredentials are created by the key and we're going to use Sha256 as the security algorithm to create the hash of that particular key. We then return all of this as a string by creating a new SecurityTokenHandler and calling the WriteToken method and passing to it our new JwtSecurityToken object.

  52. Return Bearer Token to Angular The last thing we do is we call this BuildJwtToken method from the BuildUserAuthObject. This is the one that actually creates the new instance of our AppUserAuth, and that we want to fill in now with the bearerToken. So we want to set ret.BearerToken = BuildJwtToken, passing in what we've already filled in from this AppUserAuth object. Now that we've got all of this in place, it's time to try this out. Well, at this point we have made quite a bit of changes. Let's save all of those changes and let's run our .NET Core Web API project. So it's going to go through the build again. Once we come up, hopefully your Angular application is still running. Let's try our login. You can log in with either of these two user names, psheriff or bjones. Click on Login, it now hits the Web API, and now look at the bearerToken. So our bearerToken now is this big long string here, and we can go out and we can look at this whole big long thing, and you can grab everything. Don't grab the quotes, but grab everything else. Copy it to the clipboard. So what we're going to do is we're going to take that to the clipboard, and we're going to go to jwt.io. And down here there is a little encoded area that you can now paste that into, and as soon as you do, it gives us some information, it tells us the header, which is the algorithm and the token type that's being used. It now shows us our payload, and there is the payload that we've put in. The subject, the username, the jti, that's our GUID that we generated, isAuthenticated is true, canAccessProduct is true, canAddProduct, canSaveProduct, canAccessCategories, and canAddCategory, all of these are true. Then we've got our not before, our expiration, the issuer, and the audience. So if you can come here and drop your bearerToken into this particular website, you know you have a valid JWT Token now. Does this mean that our application is working and that we can click on the products and see the list? No, it doesn't. Again, bring up your F12 tools. We're not getting a 500 error anymore, but we are now getting a 401 Unauthorized. And the reason why is because we've told it that we wanted to use an authentication system of the JwtBearerTokens, but when we called the product's API here, we did not pass the bearerToken back in. Well, that's what we're going to have to learn how to do next.

  53. Module Summary In this module, we saw that placing those JSON Web Token settings in the JSON file and using the JWT settings class helps us avoid repetition of that data from one class to the other. And for more information on JSON Web Tokens, check out the Pluralsight course Introduction to OAuth2, OpenID Connect, and JSON Web Tokens. We also saw that you can use that jwt.io website to view the information that's in your bearerToken. Coming up in the next module, we're going to take a look at how to pass this bearerToken now back and forth between the client and the server, and we're going to create an HTTP interceptor to make this process more automatic. I hope you'll join me for the next module.

  54. Working with Bearer Tokens in Angular Module Introduction Hello, this is Paul Sheriff with Pluralsight. This module is working with bearerTokens in Angular. In the last module, we saw how to send bearerTokens to the Angular application; now we're going to learn how to pass those bearerTokens back to the server so that we can be authenticated. We're going to also see how to create an HTTP interceptor, so that we don't have to write code to do it on every single call, and we'll also talk about adding a security policy to our Web API calls, so that we can restrict each Web API call by a certain claim or a role. Let's get started.

  55. Pass Bearer Token to Web API Since we added the authorize attribute to the get method on the product controller, we can't call that method until we inject the security service into the product service, create an HttpHeader in which we add the Authorization header with our bearer token, and then pass that header to the Web API get method on the product controller. Let's go to our code and pass the bearer token to the server and also secure the complete product controller instead of just the get method. Open up the product.service, and let's inject the securityService into this ProductService. That's going to allow us to get at that bearerToken. Now here is our original call to getProducts. So all we're doing is just calling a get, but no headers are being passed, but if you remember in the product controller, we added an Authorize method. We now have a bearerToken and we have the Web API set up to say we need a bearerToken that's been authenticated in order to call with an Authorize attribute. Let's create a new HttpHeaders object, and we'll assign that to this variable called httpOptions, and we'll set the Authorization header to Bearer space, and then we're going to grab the bearerToken that we sent down. Remember in the last one, we saw that big long string of Base64-encoded bearerToken that got sent back from our Web API. So we need to create this new header with that information, and then pass that to the get here. So what we do is we create an object and we say headers is the name of the property, and we pass our new header that we just created. So that's our new Web API call. Let's give it a shot. Let's go ahead and save this. Let's go back over to Chrome. Let's log in. Once we've logged in, we'll click on Products, and look at that, we're back to seeing our list of products. Remember that's where we were always getting a 500 at first, and then a 401, but now we've been authorized. Now that's just for this one screen. What about the other screens? Well, we haven't actually secured those, so if we went in here, we still can get at the product data. It's not because we're authorized now, it's because the authorize attribute is only on the one method. So what we need to do is we need to go change the authorize attribute and move it to the product controller level.

  56. Secure the Entire Product Controller Let's go to our PtcApi project, locate the ProductController.cs, so you can see the Authorize is only on the get method, but all the other ones, the Get by id, the Post, all of these are still wide open. So we would either have to copy this Authorize from one to the other, or we can simply move it to the product controller level. This now says all methods within this class are now under security control, so that means that until we pass a valid bearerToken back and the Web API has actually validated that that bearerToken is correct, nothing in this whole controller can be called. So this is what you would want to do for every single one of your controllers. Now, let's go ahead and save this. Let's restart our .NET Web API. Once this is restarted, we'll go back to our application, we'll log in. And let's go to Products. We'll get the product list, because we wrote code in the product service to pass the header, but as soon as we try to get a single one now, we're back to what we had before. We're back to the 401 Unauthorized. So, what do we have to do? It means we need to now add that same code in every single method. Well, that sounds like a lot of work. Let's see if there's a better way to accomplish this.

  57. What Is an HTTP Interceptor? As this is a pretty common thing to do, the Angular team has thought of this, and they allow us to create what's called an HTTP interceptor because we don't want to pass the bearerToken each time on each method call, that would be a lot of code that we would have to write. So we're going to create this HTTP interceptor class, and it intercepts each HTTP call, and does it one time. We only have to create this once, register this with the app.module, and inside of there, then it will automatically call this and add the authorization header to each individual call. And that's a lot better than us having to make each one of these calls individually, and writing that same code that I wrote in the last little clip there each time.

  58. Create the HTTP Interceptor So let's go ahead and create an HTTP interceptor. Right mouse click on the security folder and add a new file, http-interceptor.ts. Into this we're going to add quite a bit code here. Let's go and give us full screen here. We're going to import the Injectable and the NgModule from angular/core, we're going to import Observable from rxjs, and then we're going to import HttpEvent, HttpInterceptor, HttpHandler, HttpRequest from angular/common/http, and one more constant we're going to bring in is the HTTP_INTERCEPTORS from angular/common/http as well. So we could have combined these, I wanted to just point them out a little bit more explicitly here. So we've got the Injectable. We export the class, HttpRequestInterceptor, which implements HttpInterceptor. So this is part of Angular. So we then have to have an intercept method here that accepts the HttpRequest and an HttpHandler, and it's going to return an observable of an HttpEvent. We're going to grab the bearerToken from localStorage. So finally we're getting to see why we were putting that bearerToken into localStorage before. It's because we're in an HttpRequest. We can't inject the security service, which is also a service, we can't inject that, which then uses, right, Http, because we're already in an HttpHandler. So we have to get that bearerToken another way other than injecting with security service. So, we stored it into localStorage so that we can just grab it here very quickly and easily. As long as we got a token, we're going to take the existing request coming in, and we're going to clone it, and we're then going to create the header now. So we're going to on that request we're going to do a headers.set and we're going to use the same code that we built last time in the product service, we're now going to create the Authorization header, and we're going to create the bearer token. So we're going to add on the word Bearer space and then the token itself. We then return next.handle newReq. This is the new one that we created with the new header. So it takes the existing request that's about to be set out through the Angular HTTP client, and it creates a new one with a new header, and then returns that so Angular can use this handler; otherwise, if that token does not exist in localStorage, it simply returns the original one, which means it just goes on and handles it just like it normally would. The last thing we do down here is we create a module out of this. So we do an @NgModule, and the providers, we're going to provide our constant there, HTTP_INTERCEPTORS, we're using the class HttpRequestInterceptor, right, that's this guy right here. And then multiple instances of this are allowed, and here's our export class HttpInterceptorModule.

  59. Register and Test the HTTP Interceptor Now that we have this module created, the last thing we need to do is register this in our app.module. Add it with all the rest of the modules here as an import statement, HttpInterceptorModule, there it is, hit Tab so it will import that new module. Once we have this, let's save all of these changes. Let's go back to our product.service now, and we can now eliminate the code that we wrote before. We no longer need the SecurityService as part of the constructor. We can eliminate all of this code that we wrote. And we can put our call back to what we had originally. Very nice. You can also go up and remove the import statement here as well for the security service. Go ahead and save this, and then we're ready to try this out. Let's switch back over to Chrome. Let's log in and click on Products, and look at that, it works. Let's click on a single product, and it works. So we are back to having everything working, and now we don't have to keep adding a bunch of code to every single call. Our HTTP interceptor now takes care of all of that.

  60. Security Policies Currently we're just securing the product controller based on someone who's authenticated. But sometimes we need to get a little more granular than that. We might wish to secure certain methods based on a claim. So, that means that we need to configure our Web API service to use claim policies. What we can do in the Authorize attribute is we can add Policy = and then some sort of ClaimType. To do that, we add code in the ConfigureServices method down in the Startup.cs. And we use an AddPolicy method, and we add one of policies, our claims that we have in our UserClaim table. In this case, maybe we're adding CanAccessProducts, and we're requiring that the claim CanAccessProducts is a true value. Now be very careful, I've got a little note there that says the claim type and value are case-sensitive, so those names have to match exactly the same name and value that you have in your UserClaim table. Once we've done that, in our ProductController on any method that we want, we can now authorize based on that policy. So, for instance, what we can do is on the get method there, we can say, hey, you know what, only those users with the claim type and value that match may run this particular method. So we might secure the get method, the one that returns all products, with the CanAccessProducts claim.

  61. Add Authorization to Web API Let's try this out now by adding a security policy to our product controller. Open up the Startup.cs, locate the ConfigureServices. This is where we added all of our AddAuthentication. Let's now go down and right after that let's now add code for the services here, we're going to AddAuthorization, as well as we did services.AddAuthentication, let's now AddAuthorization. And were going to pass as an object here cgf.AddPolicy, there's our CanAccessProducts, and we're saying that we want to require a claim CanAccessProducts to be true. Once we have this in place, we can open up our ProductController. Remember we've secured everything with Authorize, but now we can make it a little more granular by adding the Authorize down here on the get method. But simply adding in Policy = CanAccessProducts. Now this name here must match exactly the name that you specified here and then this name and this value must match exactly what you have in the UserClaim table.

  62. Test the Security Policy Let's go over to SQL Server. Here we are in my localdb SQL Server, and this is our PTC-Pluralsight database. And here we've got the users. So we can take a look at the users here. So we've got the username and the password and we can see the user ID here, the GUID. Then we can take a look at the UserClaims, and we can see again the User ID, so we know which one is for which particular user, and then we have the ClaimType and the ClaimValue. Now remember, these are the guys that have to be exactly the same casing. So CanAccessProducts right now is true for the psheriff login. Let's set that to false. I want to turn that off. When we do that, that means that when we run our application, things aren't going to work, because I won't be able to get out the products anyway because of the route guard, so we need to turn that off. So let's take away that route guard by going to the app-routing.module. Locate the path for products, and let's remove the AuthGuard here. We have to remove this, right, because otherwise it's going to have CanAccessProducts come back as false, and the products menu is going to go away, but we could still type it in directly on the address bar, and this would then stop us from getting there. Well, we want to temporarily remove that, because we want to make sure that our security policy is working. So I'm going to go ahead and save that. In fact, let's save all of our changes now. And let's give this thing a try. Let's go back over to Chrome, and let's start this guy up here and click on Login. Let's log in as psheriff. And we can see now canAccessProducts is false, the Products menu has indeed gone away, but now let's try to go directly to the path, which now since we don't have a route guard it's going to let us get there. It's going to make the call to the get method on the ProductsController, but our security policy should now stop us from getting there. So what we're doing is simulating someone that's just trying to call our Web API call directly from some other program that they have. So if we bring up our F12 tools here, we should see that the server responded with a 403 Forbidden, which is exactly what we wanted. By the way, I wanted to mention, if you do come in and you do see the product list, which will happen sometimes, it's a caching problem. Simply close down the browser and close down Visual Studio Code, bring everything back up, and you should then see this status of 403 Forbidden.

  63. Module Summary In this module, we learned how to pass our bearer token back to the server so that it can authenticate us back to the Web API, so we can make our Web API method calls. We also created an HTTP interceptor, so that we don't have to write the same code over and over again in every method that we want to make a call to the Web API. And we added a security policy to give us more granular control over which methods are allowed to be called by which set of users based on their user claims. Coming up in the next module, we're going to now move to more of an enterprise security system. We're going to create that array of user claims from the table, and we'll pass that entire array down instead of setting properties one by one in our authorization object. Then we're going to create a structural directive, a custom structural directive, for securing the UI and eliminate any sort of binding to specific properties. I hope you'll join me for the next module.

  64. Using Claims-based Authorization Module Introduction Hello, this is Paul Sheriff with Pluralsight. This module is Using Claims-based Authorization. The goals for this module are to use an array of claims instead of individual properties like we have been using. This will make our security system a little more flexible and support a large amount of claims for enterprise-type applications. We're going to modify these Angular classes to take advantage of this new way of doing this. We're going to modify our C# classes on the Web API to also take advantage of these new changes. We're also going to build our own structural directive that we are going to call hasClaim that we can now add to take away complete menu items or buttons or any UI element that we want on the DOM. Let's get started.

  65. Changes to Make to the Angular Security Classes So far what we've put into place with our security architecture is a login page, a user class, a security service, a Web API service, and a SQL Server with a couple of tables. What we're going to do now is we're going to modify the authorization object. We're going to take away all of those individual properties and instead we're going to use an array of claims that we get back from the UserClaim table. Now we've already written that code. All we have to do is just modify the part that builds the authorization token. There are a few changes we're going to have to make in order to use an array of claims instead of individual properties. First off, we're going to have to add an AppUserClaim class down in Angular, we're going to add a claims array to our AppUserAuth object, we're going to modify the resetSecurityObject method to clear the claims array, we're going to add an isClaimValid method to our security service, and a hasClaim method to our security service. And we're going to have to modify the route guard in order to check the new array instead of using the individual properties.

  66. Remove Individual Properties and Add Claims Array Let's go ahead and start modifying our Angular classes. In the last module, we took away the route guard from our products route. Make sure you add that back in. That was just a temporary thing to show how our Web API method was stopping access to that. Let's go to our security folder and let's add a new file called app-user-claim.ts. This particular user claim class that we create is going to have a claimId, a UserId, a claimType, and a claimValue. Now that should look a little familiar to you, as this matches the UserClaim table that we saw in SQL Server. Now that we have this new class, let's go into our AppUserAuth object here and we're going to delete all of these individual properties now and instead we're going to add a claims property that's of the type AppUserClaim, and it's going to be an array of those. And let's go ahead and initialize it to an empty array. Be sure to hit Tab so that it adds the appropriate import statement. Next open the security service class, locate the resetSecurityObject and you'll notice that this now has a bunch of errors because before we were setting each one of these individual properties to a false value. All of those properties are now gone. Instead, let's now use the securityObject.claims and let's reset that to just simply an empty array.

  67. Check Claims in Security Service and Route Guard Next inside of our security service class, let's add a new method called isClaimValid. Now, we're going to pass in a claimType, and optionally a claimValue to detect, and it's going to return a Boolean. We're also then going to set up a couple of variables here, so our return value, and an AppUserAuth. We'll retrieve the securityObject down here, and I'm just doing that so we have a little simple shorthand here. Check to make sure it's valid and if it is, we're now going to check the claimType indexdOf and see if it has a colon in it, because we may want to add our hasClaim claimType:value. This allows us to see if the claimType has a specific value. Another way to call this would be simply to access claimType, which will assume that there is a true value for the claim that we're trying to check and see. But I wanted to give us an option here. So, we're going to check and see if that claimType has a colon in it, and if it does, we're going to split those two words, we'll grab the claimType out of the 0 element, and we'll grab the claimValue out of first element in the words. Otherwise, if it doesn't have that colon in the claimType, we're going to assume the claimType is just that, and the claimValue is now going to be true. We're going to check to see if it's a true value. Next we attempt to find the claim in our claims array that we just created, so we'll attempt a find here, checking where the claimType in the claims array is equal to the claimType passed in, and the claimValue in the claim array is also the same as the claimValue passed in or a true if there was no claimValue. If all of this comes back, not equal to null, we know we've got one, and we'll return a true back from this expression. So the isClaimValid will actually return a true value. If it doesn't find one, then obviously it will return a false, which means that the claim is not valid. One thing you'll notice is that this is a private method. Well, that means we need a public method to exposed from this, so let's create one called hasClaim, claimType is defined as any, and we're going to have a claimValue here that is optional that is also defined as any. All we're going to do is return this .isClaimValid, passing in the claimType and the claimValue. Since we no longer have individual properties, but we have an array of claims, we do need to modify our auth guard. Remember our auth guard was accessing the security object and checking the individual property based on the data that was passed in from the route. Since we no longer have the individual properties, we're going to use our new hasClaim method and check our claimType. So this is how we'll now protect a route by looking up the claimType within our array of claims that we're going to get out of the UserClaims table.

  68. Changes to Make to the Web API Classes Now that we've modified the Angular classes, let's go modify the server-side classes. What we want to do is add a list of claims to our AppUserAuth up on the server now and take away the individual properties, assign the list of claims in the BuildUserAuthObject method and eliminate the one-by-one assignments, and we're going to add claims to the jwtClaims array in the BuildJwtToken method.

  69. Make Changes to Server-side C# Classes Let's modify our server-side classes and we'll view the new user auth object that's returned from our Web API call. Open the AppuserAuth class and let's delete all of the public properties that we used for individually turning off UI elements. And instead, let's add a generic list of AppUserClaim classes. So this is where we get all of those claims from the UserClaim table, and we're going to add them to a list here, and let's just call it Claims and of course add our appropriate get and set. Now, the list is not there, because we have not added a using for System.Collections.Generic, so go ahead and add that now. Now you'll notice that we have some errors in Security Manager, and that's fine. We knew we had to fix some things up in here. So the first thing we'll do is we're going to look for where we're looping through each of those claims, right, and setting each of the individual properties. Well, we don't want to do that anymore. What we want to do instead is just get all the claims for that user, which we're doing right here, and actually assign it to the return value coming back. So we can simply say ret.Claims is equal to GetUserClaims, and then you can delete all of this where we are setting the individual properties of the AppUserAuth because we don't need to do that anymore. Next we need to go to the BuildJwtToken method, because right in here is where we were adding all these individual custom claims, right? The CanAccessProdcuts, CanAddProduct, et cetera. We're going to eliminate all of those, and we're going to add custom claims from the Claims array. So let's build a foreach here, and in the foreach, we're going to grab a claim in the authUser.Claims array. Remember, AuthUser is what is passed to this method. Once we're in the loop, we're just going to use our jwtClaims object and add to this a new Claim based on the claim.ClaimType, so these are the ones right out of the table, claim.ClaimValue. So now instead of each individual property being set, we're just simply adding however many claims we have in our table. This is going to make it just a little bit more flexible and will support a large amount of claims that you may have in a large enterprise system. Let's take a look at our new bearer token that's coming back now from these changes that we made. Go ahead and run the Web API system. We'll get that started. Once that's up and running, come back over here. We're going to have to change just a couple of things in the Angular application. I'm going to go down into src app and I'm going to open up the app.component.html, because all I want to do is remove these ngIf directives. Remember these are gone. These properties are absolutely gone. So we want to get rid of these at this point. Let's save that, and if you're not running, go ahead and start the application. And then let's see what we get back now. Because our bearer token is going to be a little bit different than what we had before. So we're going to go ahead and log in here as psheriff. Once we log in, we should now get a much larger bearerToken back, and we're going to see that we get all this whole array of claims now coming back to us. And we can see, we get the claimid now and the userid, we could have eliminated those from coming down just to keep our payload a little bit smaller, but I just left them in for now. Let's go ahead and one more time let's grab the whole bearerToken. Now this one goes all the way and comes all the way down to here. So let's go ahead and copy that to the clipboard. Let's then go to that jwt.io. Come down here to our text box and paste it in, and now we can see, we've got the same amount, or same properties basically, but remember these are now coming from the table. So if we add additional properties, or additional rows to the table, they're going to come down as additional properties in our bearerToken, because we looped through and built those.

  70. How to Create a Structural Directive Now that we have an array of claims on both the server-side and the client-side, it's now time to build your own custom structural directive to make UI elements appear and disappear. Since we don't have individual properties to assign to or bind to using the ngIf, we have to create our own custom structural directive, and I'm going to name it hasClaim. And that's going to look like what you see here, *hasClaim-= and then in double quotes put in single quotes, because we need to pass a string value as the claimType that we want to check, right. It's no longer a property name, so we have to enclose it in the single quotes. So CanAddProduct, CanAddCategory, et cetera. What this structural directive will do then is it will remove an element if the claim is not valid. We create a new directive by using the @Directive function, and we pass into that a selector, and the selector I'm just going to call hasClaim. That's what everyone used in our DOM. We had an input property, so use the @Input, and the set is called hasClaim; the claimType comes in as an any. We then check our securityService by calling the hasClaim method that we wrote, passing in this claimType. And if it returns a true, we're going to call the this.viewContainer.createEmbeddedView, passing in this .templateRef. That's the structure of in the DOM that this structural directive has been applied to. If it returns a false, we'll remove the template from the DOM.

  71. Build and Test the Structural Directive Let's go to Visual Studio Code and create our new structural directive and use it on our button elements. Let's add our new structural directive by opening a new Command Prompt in the PTC application and using the Angular CLI. We'll do an ng, g for generate, do for directive, under the security folder, let's add our hasClaim directive, keeping the structure flat and registering it with our app.module. And there is our new has-claim.directive. Now it's very basic. We need to add a couple of things, so let's go ahead and add Input, TemplateRef, and also our ViewContainerRef as well. So we're adding each of these imports from Angular Core. Next, modify the selector, because it always adds the prefix that we've set up when we created this project, which I had done as ptc. Let's just name it as hasClaim. Then let's add to our constructor and have Angular inject a few things. We're going to have it inject our templateRef, TemplateRef as any. Let's also add our viewContainer of the type ViewContainerRef, and one more, and that's our securityService that we've created. So we've got a few things that we're going to have Angular inject into our directive for us. And the last thing we'll do in this directive is let's add on the input property that I talked about in the slides called hasClaim. It's going to accept this claimType. It then checks to see if the securityService when we call the hasClaim passin in the claimType, that means great, everything's true, then let's go ahead and embed the structural element that this directive has been applied to. If the hasClaim returns a false, we're going to remove the whole structural element, the template, from the DOM. Offscreen I went ahead and started up our Web API service, but now let's now go and secure the Add New Product button in the product-list.component.html. Remember we had a button that's Add New Product, and we use the ngIf here and it said securityObject.canAddProduct. Well, that no longer exists. So instead let's use our new structural directive hasClaim, and what we're going to do now is specify CanAddProduct. Now remember, you must enclose this in single quotes. It has to be passed in as a string, not as a property, because it's no longer a property, it's not a property in the product-list.component.ts, it's a string that's being passed to the structural directive, hasClaim. Well, let's give this a try. Let's save our change, let's go over to Chrome, let's log in here as psheriff. Once we log in, let's go to our products and we should see the Add New Product button. Let's now log out as psheriff, log in as bjones, and when we come into products, the button will disappear, because bjones does not have that claim type. If you remember, one of things that I said we could do is we could add a value after the claimType. So if you remember down in our security.service, one of the things that we put in here was a little bit of code to check to see if the claimType passed in has a colon in it. If it does, it's going to split up the two words, the ClaimType and the ClaimValue. So that's what I've done here now. Let's save this change. Let's go back, log back in now as psheriff, and now you can see the button has gone away, because now we're looking for a claimValue of CanAddProduct with a value of false. However, my particular record in the claim UserClaim table has CanAddProduct to be true, thus the two don't match.

  72. Secure Menu Items So we just got done securing buttons, but what about our menus? Well, the problem is we're not allowed to have two structural directives on one element. So, that means that we can wrap our menus in an ng-container and do the isAuthenticated property on the container and use our structural directive hasClaim on the routerLinks. Let's take a look at securing our menu items. We've secured a button, but what about securing our menu items? So on the app.component.html, remember I had taken away the ngIf structural directive. So the problem is we want to only have the products and the category menus, these two menus, show up if we're authenticated and we have the appropriate claim. The problem is you cannot have two structural directives on one element. Well, not to worry, we have what's called ng-container. And an ng-container we can wrap around our menu items here. So let's add an ng-container around each one of these, and then what we can do is we can apply an ngIf structural directive on the container. Say securityObject.isAuthenticated, like so, for the products, and for the categories. Then on the routerLink itself, we can add our new custom structural directive and we can specify that we want canAccessProducts, and also we can specify canAccessCategories, like so. Now these, if you remember, can be any casing. The reason why is if we were to go look at our security.service here, when I actually try to find, I'm actually checking the lowercase versions of each of these. So, our claimType, that name can be whatever we want. You can use uppercase, lowercase, it really doesn't matter here. So let's pop over to Chrome here. Notice that they're gone, because of the IsAuthenticated. Let's now log in as psheriff, and we should now see our appropriate menus.

  73. Handling Multiple Claims per Element In many applications, we want to allow more than one claim per UI element. So we want to be able to pass an array of claims to our structural directive that says if any one of these claims are true, then we're going to let this particular UI element be displayed. To accomplish this, we simply modify the hasClaim method that we already wrote, where we check the claimType parameter to see what's being passed in. If it's a string, we simply call the isClaimValid method, like we did before, but if it's an array, we're going to take it and convert it into an array, and we'll loop through each array element. Each array element is simply a string, which is a claimType. And as long as one is successful, we're going to return true from this method, signifying that, hey, this person is allowed to get in, because he matches one of those claimTypes.

  74. Modify Code to Handle Multiple Claims Let's now go handle multiple claims by rewriting the hasClaim method. Let's also secure other buttons just like we had them done before, but now we'll use our structural directive, and we're even going to be able to remove some code from components that we no longer need. Open up the security.service and locate the hasClaim method. I'm going to completely replace this, because I'm adding a lot of comments, and I wanted to add some comments to remind myself of what I can do with this particular method. This method will allow me to pass in a single claimType, it'll allow me to pass in a claimType:value, or it'll allow me to pass in an array of those claimTypes, and even each element of the array could be a claimType and a value. So we didn't change the signature at all, this stays the same. All we do now is check to see if the type of claim is a string, so if it's a regular string, we're going to call the isClaimValid just like we did before. That handles these first two scenarios. Otherwise, we're going to assume that it's an array. So we're going to take this and we're going to convert it to a claims variable here that's of the type string array. Make sure that we did actually get some conversion taken place. Then we loop through the array. Each time through, we're going to call isClaimValid, passing in the index into that array, and if just one of them is successful, we're going to break out of the loop and we'll return that true value, or false value, as the case may be. So let's try this out. Let's go back to our product-list.component.html and on the hasClaim structural directive here, let's make this into an array, and we'll allow either the CanAddProduct or the canAccessCategories. So we can just try that out and make sure everything works as appropriate. But this is what the syntax would look like. Next let's go to the product-detail.component, because if you remember, one of the things we had here was on the Save button, we actually had a structural directive that we now need to change and use our custom one, and we'll change that so that it passes in canSaveProduct. We can do the same thing now over on the category-list.component where we also had a structural directive, but instead of the ngIf, we're going to use the hasClaim. Save all of your changes here, and then you could just go try things out. Log in as psheriff, and let's just make sure that all our buttons are working like they should. We can see the Save, we saw the Add New Product, we see the Categories. Now let's log out and log in as bjones. Now one of the things that we changed here was we made the Add New Product show up if it's either CanAddProduct or CanAccessCategories, since we know that bjones can access categories, we also see the button here. Yet we go in here, the Save button is gone and the Categories has the Add New Category, because he has that particular claim.

  75. Remove Code from Components Now we get to do kind of a fun thing. We get to remove the security service that we had added to a couple of these components. For example, in the category-list.component, when we were using the ngIf, we had to have the security object around. We no longer need that anymore, because we now have this new structural directive. So we can remove the securityService, the securityObject, and that means we can eliminate the securityService from our constructor and the code that used to assign to that as well. That's kind of nice that we get to remove code. This makes it simpler now to implement security, we don't have to add a whole bunch of things. We can do that on the category list component, we can do it on the product detail component as well, so just simply remove everything you don't need. Now it doesn't mean that you might not necessarily need the security service again at some point, right, maybe you're checking some security within code to make sure they can do something, that's fine. But at least for checking objects and things like that, it is no longer necessary for us to inject all of this code and have all of this available when we're using the structural directives. Again, save all of this and just make sure that everything is still working as you'd expect. We see there are no menus. That's a good thing. And look at that, everything is still working just like we would expect.

  76. Module Summary and Role-based Security In this module, we added an array of claims to our authorization object. We returned that array of claims from the Web API. We then built a custom structural directive to check those claims. We even added support for multiple claims as well. And we even simplified our code by removing certain amounts of code that we don't need just to check security anymore. One thing I did want to mention is it would be very easy for you now to add a role array and implement role-based security, just like you did here with claims-based. It would be just a matter of reading those roles from a table, adding a roles array, and then creating a custom structural directive called has role.

  77. Course Summary Well, congratulations! You've made it through the Security for Angular course where we learned about authenticating users, securing UI elements and routes, we used JSON Web Tokens to secure our Web API, and we learned how to pass bearer tokens back and forth. We also learned how to build claims-based authorization and created our structural directive to simplify our code. I hope you enjoyed this course for Pluralsight. This is Paul Sheriff.