6-creating-a-secure-api-using-oauth2-and-jwt-in-net-core.html

Creating a Secure API Using OAuth2 and JWT in .NET Core

In today’s interconnected digital landscape, securing APIs is more crucial than ever. As developers, we must ensure that our applications are not only functional but also secure from unauthorized access. One effective way to achieve this is by implementing OAuth2 for authorization and JSON Web Tokens (JWT) for secure token transmission. In this article, we will walk through the process of creating a secure API using OAuth2 and JWT in .NET Core, providing clear code examples and actionable insights along the way.

Understanding OAuth2 and JWT

What is OAuth2?

OAuth2 is an authorization framework that allows third-party applications to obtain limited access to user accounts on an HTTP service, such as Facebook, Google, or GitHub. It does this by delegating user authentication to the service that hosts the user account.

What is JWT?

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. The information is digitally signed, ensuring that it hasn’t been altered.

Why Use OAuth2 and JWT Together?

Using OAuth2 and JWT together offers several advantages:

  • Statelessness: JWTs are self-contained, allowing for stateless authentication.
  • Scalability: By not storing sessions on the server, you can easily scale your application.
  • Security: The use of tokens reduces the risk of CSRF attacks and allows for secure API access.

Setting Up Your .NET Core Project

Prerequisites

Before we dive into the code, ensure you have the following:

  • .NET Core SDK installed
  • A code editor (Visual Studio, Visual Studio Code, etc.)
  • Basic knowledge of C# and ASP.NET Core

Creating the Project

  1. Create a new ASP.NET Core Web API project: bash dotnet new webapi -n SecureApi cd SecureApi

  2. Add the necessary packages: bash dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer dotnet add package Microsoft.IdentityModel.Tokens

Configuring OAuth2 and JWT in Startup.cs

Step 1: Configure Services

Open the Startup.cs file and configure JWT authentication in the ConfigureServices method.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    // Add authentication services
    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(Encoding.UTF8.GetBytes("YourSecretKey"))
        };
    });

    services.AddScoped<IUserService, UserService>(); // Your user service for authentication
}

Step 2: Configure Middleware

Next, configure the middleware to use authentication:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthentication(); // Enable authentication
    app.UseAuthorization();  // Enable authorization

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Implementing User Authentication

Step 3: Create the User Model

Create a simple user model that will help us manage user data.

public class User
{
    public string Username { get; set; }
    public string Password { get; set; }
}

Step 4: Implement User Service

Create a user service that handles user authentication and JWT generation.

public interface IUserService
{
    string Authenticate(string username, string password);
}

public class UserService : IUserService
{
    private readonly List<User> _users = new() // Example users (in a real app, use a database)
    {
        new User { Username = "test", Password = "password" }
    };

    public string Authenticate(string username, string password)
    {
        var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);
        if (user == null) return null;

        // Generate JWT token
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.UTF8.GetBytes("YourSecretKey");
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, user.Username) }),
            Expires = DateTime.UtcNow.AddDays(1),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }
}

Step 5: Create the Auth Controller

Create a controller to handle authentication requests.

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private readonly IUserService _userService;

    public AuthController(IUserService userService)
    {
        _userService = userService;
    }

    [HttpPost("login")]
    public IActionResult Login([FromBody] User user)
    {
        var token = _userService.Authenticate(user.Username, user.Password);
        if (token == null) return Unauthorized();

        return Ok(new { Token = token });
    }
}

Securing API Endpoints

Step 6: Protecting Routes

To secure specific routes, use the [Authorize] attribute above your controller or action methods.

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
    [HttpGet]
    public IActionResult GetValues()
    {
        return Ok(new string[] { "value1", "value2" });
    }
}

Conclusion

Creating a secure API using OAuth2 and JWT in .NET Core is a robust way to protect your application from unauthorized access. By following the steps outlined in this article, you can implement a secure authentication mechanism that is scalable and efficient.

Key Takeaways:

  • Understand OAuth2 and JWT: Knowing how they work together is crucial for implementing secure APIs.
  • Use .NET Core’s built-in authentication features: Simplifies the process of token generation and validation.
  • Always protect your API endpoints: Ensure that sensitive data is only accessible to authorized users.

With these insights and examples, you're now equipped to enhance the security of your .NET Core APIs effectively. Happy coding!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.