Your API is wide open

If you read part 1, you know now what a JWT is and how to issue one.

We’ve provided a convenient way for clients to gain access to restricted areas of our API

… but, we haven’t actually restricted anything.

If you leave your API open like this, your SPA can make requests to it, but so can anyone else.

As a minimum we want to ensure the client making a request to our API has a valid token (which they got by calling our JWT-issuing action, with a valid username and password).

The plan

Our plan of attack:

  1. Require authentication for our API controllers
  2. Test that anonymous requests are rejected
  3. Configure JWT auth in startup.cs
  4. Test that requests with a valid JWT are accepted

Require Authentication

With the [Authorize] attribute you can easily lock down your API to authorized users only.

[Authorize]
[Route("api")]
public class ApiController : Controller
{
    [HttpGet("Test")]
    public IActionResult Test()
    {
        return Ok("Super secret content, I hope you've got clearance for this...");
    }

    // rest of controller goes here
}

Now, unless otherwise specified, every action in this controller will require the request to be authenticated.

Test anonymous requests

Try navigating to your http://yourapihere/api/test and you’ll get a 401 Unauthorized response.

Check your work

Whilst it’s become a little bloated in recent times, Postman is still a handy tool for testing your site.

In this case, if you want to try hitting your API, you can easily create a GET request, run it, then check what status code comes back (401 hopefully).

So our API is definitely secure, but now we have the opposite problem to before, no one can get past this barrier.

Authenticate JWTs

In ASP.NET Core 2.0, configuring JWT auth is pretty straightforward.

In most cases, you just need to configure it in startup.cs.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = "yourdomain.com",
                ValidAudience = "yourdomain.com",
                IssuerSigningKey = new SymmetricSecurityKey(
                    Encoding.UTF8.GetBytes(_configuration["SecurityKey"]))
            };
        });

    services.AddMvc();
}

These are the basic options for configuring JWT auth for your site.

This code configures ASP.NET Core so that requests to API actions (which require authentication) will check for a token meeting these requirements:

  • issued with the correct issuer and audience details
  • signed with the same secret key that we’re using (from configuration)
  • hasn’t expired

If you’re wondering where _configuration came from (it may be missing in your startup.cs file), you can easily bring it in via the constructor and let ASP.NET Core wire it up for you.

public Startup(IConfiguration configuration)
{
    _configuration = configuration;
}

Test valid requests

Now to the final hurdle, can we get to our test API method if we pass a valid token?

First up, we can hit the API action we created in part 1, to get a JWT.

Then modify the headers for our API GET request, to pass that token in the Authorization header.

Authorization: Bearer <token goes here>

So now what?

You can issue a JWT and validate it. Your app is now protected from meddling by anonymous users.

This approach is known as Bearer Token Authentication where your app issues a token and then gives access to the bearer of that token.

If you have a valid token, you’re in.

So what shall we cover next in the mysterious and complex world of authentication?

Let me know by entering your details in the “Want to learn .net Core” box below and hit reply when you get my welcome email.

Get the SOURCE CODE: JWT authentication for your ASP.NET Core 2.0 app

Enter your details and I'll ping you a link to the code:

I hate SPAM and will keep your email address safe. You will be signed up to my regular emails and can easily unsubscribe if you'd rather not receive them.

Photo Credits:

Jez B Fairly pointless… via photopin (license)

Theo Crazzolara Stop, it’s winter via photopin (license)