Building APIs with C# and ASP.NET Core

Security Considerations

Spencer Schneidenbach

Spencer Schneidenbach

Aviron Software, Microsoft MVP
Building APIs with C# and ASP.NET Core

Check out a free preview of the full Building APIs with C# and ASP.NET Core course

The "Security Considerations" Lesson is part of the full, Building APIs with C# and ASP.NET Core course featured in this preview video. Here's what you'd learn in this lesson:

Spencer walks through some security best practices. Security concerns are typically addressed in two areas. Authentication through the process of determining a user's identity and authorization, determining if an authenticated user has access to a resource.

Preview
Close

Transcript from the "Security Considerations" Lesson

[00:00:00]
>> Spencer Schneidenbach: It would be a mistake not to at least touch on security and talk about it a little bit. So I refactored my 4z final project to add in some security concerns, and we'll go through and we'll tweak and we'll test with them. But I want to first talk about security at a base.

[00:00:15]
So you have two major types that ASP.NET Core is concerned with. Which is, authentication, making sure that you have a valid username and password, and you are who you say you are, and then authorization. Just because I can walk into a Walmart doesn't mean that I can go to the employees-only section, right?

[00:00:33]
I'm not authorized. I'm not an employee at Walmart. So we're going to talk through just a few things. We're going to talk through what are JSON web tokens or JWTs. We're gonna talk about the stuff built into ASP.NET Core that allow you to add security. And really you can do it in a very fine-grained way, in a very powerful way, and very simply as well.

[00:00:54]
We'll talk about common authorization patterns for ASP.NET Core APIs and a not good Implementation. Not good because it is not production. It's not code that you would run in production, but for the purposes of demonstration, it will get the point across. JSON web token is a URL safe means of representing claims to be transferred between two parties.

[00:01:15]
That's a lot of fancy words for saying, I have a token that has information in it. And I want to present that to the server in a way that the server can verify and not only make sure that I'm not scamming them, it includes what's called a signature verification.

[00:01:30]
To make sure that I just didn't make this up. The server will verify that independently to make sure that that token is valid. It also has a payload, which contains the claim. So you'll see it in this format. These are what they look like. You'll see that the header is one base 64 string.

[00:01:49]
You see that there's a dot between it. It's got the body, and then it's got the signature as well. And the fun thing about these things is that they can be decoded. So you can use a tool like JWT.IO, which we are going to go to. You're gonna see when I paste this code in, I've got nothing, I paste it in, and now you can see that we can decode that data and see what's going on in here.

[00:02:11]
In this case, our claims that we're including our sub, our name, and our IAT
>> Spencer Schneidenbach: Which is the sub is who the token refers to. It's typically like a user ID and the name would be the real name of that person or whatever name that they have stored inside of that target system.

[00:02:35]
And typically, this is sent in the authorization header with a bearer prefix Fix. So if you've ever sent a bearer token to an API bearer and then the token, that's how you would authorize yourself. The system on the back end would verify it, and then you'd be off to the races.

[00:02:49]
You'd be able to access whatever resources they gave you. This is different than what's called an opaque token, which is literally just like a password. And in that it is just a random string. And doesn't necessarily give you access to anything. It doesn't have any claims associated with it.

[00:03:04]
The powerful thing about JWTs and claims specifically is that you can issue a token that says, here's all the things that you have access to. And now you don't have to do database calls down the line to actually make sure that you have access to the resources that you have access to.

[00:03:20]
Here's an example of a claim. A claim is pretty much any key value pair that starts with the string. So you can say that I am part of the engineering department. I am an administrator. Typically, a claim will include your name as as I mentioned, or the subject, which is, again, usually just ID.

[00:03:37]
So this is important, because the sample project uses JWT, which I will show you here in a second, but I do want to point out a few of the features inside of ASP.NET Core. So there is an attribute called authorize that you can use to protect access to resources.

[00:03:53]
A naked authorized attribute will simply say that you must be authenticated before you can access these resources. It doesn't have anything to do with authorization at this point. However, you can change your authorized attribute to include things to say, in order for this person to be authorized to use this resource, we want to make sure that they're part of the administrator role.

[00:04:14]
A policy allows you to define a really nuanced way of saying you must have all of these different permissions in order to access this resource. So you can say that this policy is defined. We call it senior engineers from engineering department only. And this policy requires that this person have the senior engineer role, and they must be part of the engineering department, okay?

[00:04:40]
You can also require them to be part of another role, or have another claim, or have any other set of claims. You could even authorize it down to a specific person or person with a specific name. I have to say that while I'm showing these to you and that they're really important and interesting, and authorization is a really cool subject, it is a really nuanced subject.

[00:05:02]
There is a lot to authentication. The rabbit hole goes very deep, and authorization is almost certainly going to be dictated by the terms of tthe person that you're working for, or whoever you're building the system for. Permissions is such a complex, nuanced issue, especially when you get into big enterprises like healthcare.

[00:05:24]
And it really does become specific to that business and specific to that industry to see how they're implemented. But these are some of the tools that you can use kind of out of the box in order to kind of get what you need from your authorization system. So I just wanna kinda point out.

[00:05:39]
A few of the things that I would consider if I were making an authorization system. Or if I was adding an authorization system to an ASP.NET Core API, these are decisions that I do have to make. First things first, if I'm using a React app, or if I'm creating a React app and I want to have my own login scheme, I'm probably gonna reach for something called ASP.NET Core Identity.

[00:06:01]
Again, security could be a course in and of itself. You could do an entire course simply on security. But there is a product called ASP.NET Core Identity. It buttons really well with EF Core, and it buttons obviously very well with ASP.NET Core. And it basically gives you a lot of the base structures that you would need.

[00:06:19]
Like a user table or a role table that you would need to actually build an identity system. And you can use that as your login scheme for your React app. If you do that, it used to be back in the day that you would get a bearer token from the API, and then you would set it in local storage.

[00:06:38]
But nowadays it's best practice to say, just use cookies, just create a cookie, give an authorization cookie back to the browser, and then just use that to authenticate to your API. You could also just use if you have an integration level API, and you just wanna give somebody an API key that's very common as well.

[00:06:55]
If you use open API at all or using Twilio or a number of other services, typically you're just given one key that gives you access to the system. And then you just use that key in order to perform tasks or make API calls. That's very common as well.

[00:07:11]
By making an integration level API, I'm usually going to reach for some kind of API key solution. And it could be something if I'm building on top of an existing system. It's something that I might just build on to it and treat my API key as like a username and password pair or something along those lines.

[00:07:28]
So let me walk through just a little bit in the final app what I have added. I actually did go through and add security to this API. So if we go to the employee controller, you'll see that I have added an authorized attribute up here. And that's because I did some very rudimentary JWT token creation.

[00:07:57]
What I mean by rudimentary is that I went here and I have a security controller. And you cannot say that I didn't warn you that you should not use this code. This code is for demo purposes only. I needed a quick way to generate a JWT and that's what I got right here.

[00:08:13]
Which is to say that I just pass in a role inside of my GetTokenRequestBody, and I generate a Java Web token or JSON web token from there. And if you dig into the method, you can see that I just give it a random ID, I give it the role that I've been assigned.

[00:08:33]
And now I can use this along with my authorized attribute to actually restrict access to certain resources. You might go back and think about the use case where we only want certain people to be able to access the social security number on an employee. This is a perfect use case for that.

[00:08:49]
Is to say that only a person with this claim or this level of authorization can actually get that. And we'll probably protect that under a separate endpoint. I also want to note that inside of my unit tests, every time I do factory.Create Client, I now do a separate call to get that JSON token back from the server.

[00:09:10]
I make a call to do that here, and then I add it as part of the default request headers. And what will happen is, you saw the unit tests pass earlier. If I don't have that, if I I comment this out, you'll see that when I run this endpoint, when I run this thing, that I will no longer get back anything.

[00:09:30]
I will get 401 unauthorized, and that's because I haven't identified myself to the server with a valid JSON web token. So that's security. Just a very high-level teaser of some of the features that are inside of ASP.NET Core. I will tell you that I use policies a ton.

[00:09:45]
I do use claims. I do use roles, although roles are one of those particular things that will differ between really depending on the company or the system that I'm building. And I certainly use JSON Web Token. And I also use a lot of the identity stuff. I use ASP.NET Core identity quite a bit for projects.

[00:10:08]
So I recommend you check those out and that's security. It's a little demo. So I would highly recommend you download this project. If you haven't downloaded the code samples yet, download them and then open up 4z final. And just start playing with the JSON Web Token, start playing with the endpoints and see if you can add custom policies.

[00:10:30]
And change your bearer token to actually allow you to get into those endpoints.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now