Securing APIs with OAuth 2.0 and JWT in .NET Core
In today’s technology landscape, securing your APIs is paramount. With the rise of microservices and mobile applications, ensuring that only authorized users can access your resources is essential. One of the most robust methods to achieve this is by using OAuth 2.0 for authorization and JSON Web Tokens (JWT) for token management. In this article, we will explore how to implement OAuth 2.0 and JWT in a .NET Core application, providing you with actionable insights, code examples, and a step-by-step guide to secure your APIs.
Understanding OAuth 2.0 and JWT
What is OAuth 2.0?
OAuth 2.0 is an authorization framework that allows third-party applications to obtain limited access to an HTTP service. It enables secure delegated access, so users can grant access to their resources without sharing their credentials. OAuth 2.0 uses different flows to grant tokens based on the type of app and the use case.
What is JWT?
JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as plaintext in a JSON Web Encryption (JWE) structure. JWTs are commonly used for authentication and information exchange due to their lightweight nature and security features.
Use Cases for OAuth 2.0 and JWT
- Web Applications: Secure user login and session management.
- Mobile Applications: Provide secure access to backend services.
- Microservices: Enable service-to-service communication without exposing credentials.
Setting Up a .NET Core API with OAuth 2.0 and JWT
Step 1: Create a New .NET Core API Project
First, make sure you have the .NET SDK installed. You can create a new API project using the following command:
dotnet new webapi -n SecureApi
cd SecureApi
Step 2: Install Required NuGet Packages
You will need to install a few packages to work with authentication. Run the following commands to install them:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.IdentityModel.Tokens
Step 3: Configure JWT Authentication
Open the Startup.cs
file and configure the JWT authentication in the ConfigureServices
method:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
var key = Encoding.UTF8.GetBytes("YourSuperSecretKey"); // Replace with your secret key
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "YourIssuer",
ValidAudience = "YourAudience",
IssuerSigningKey = new SymmetricSecurityKey(key)
};
});
}
Step 4: Create a Token Generation Endpoint
Next, you need to create an endpoint to issue JWT tokens. Add a controller named AuthController.cs
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
[ApiController]
[Route("[controller]")]
public class AuthController : ControllerBase
{
[HttpPost("token")]
public IActionResult Token([FromBody] UserLogin login)
{
if (IsValidUser(login)) // Implement user validation logic here
{
var claims = new[]
{
new Claim(ClaimTypes.Name, login.Username)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YourSuperSecretKey")); // Same key as above
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "YourIssuer",
audience: "YourAudience",
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
}
return Unauthorized();
}
private bool IsValidUser(UserLogin login)
{
// Placeholder: Replace with actual user validation logic
return login.Username == "admin" && login.Password == "password";
}
}
public class UserLogin
{
public string Username { get; set; }
public string Password { get; set; }
}
Step 5: Protect Your API Endpoints
To secure your API endpoints, you can use the [Authorize]
attribute. For example, add it to a sample controller:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet]
[Authorize]
public IActionResult Get()
{
var forecast = new[]
{
new { Date = DateTime.Now, TemperatureC = 25, Summary = "Warm" },
new { Date = DateTime.Now.AddDays(1), TemperatureC = 20, Summary = "Cool" }
};
return Ok(forecast);
}
}
Step 6: Testing the Implementation
- Run your API using
dotnet run
. - Use a tool like Postman to send a POST request to
/auth/token
with the body:
{
"username": "admin",
"password": "password"
}
- Copy the token returned in the response.
- Send a GET request to
/weatherforecast
with the token in the Authorization header:
Authorization: Bearer {your_token_here}
If everything is set up correctly, you should receive the weather forecast data.
Conclusion
Securing your APIs with OAuth 2.0 and JWT in .NET Core not only enhances security but also simplifies the management of user access. By following the steps outlined in this article, you can implement a robust authentication mechanism that allows you to protect your resources effectively. Whether you're building web or mobile applications, understanding and leveraging these technologies will help you create a secure environment for your users and their data.
With these tools and techniques, you are on your way to building secure and scalable APIs!