MSDN Documentation

Learn and build with Microsoft technologies

Securing ASP.NET Core APIs with IdentityServer

This tutorial demonstrates how to secure your ASP.NET Core Web APIs using IdentityServer, a popular open-source framework for authentication and authorization in .NET.

1. Prerequisites

2. Setting up IdentityServer

Ensure you have followed the setup steps in the IdentityServer Setup tutorial.

3. Protecting API Endpoints

To protect an API endpoint, you need to configure your ASP.NET Core API project to require authentication. This is typically done using the [Authorize] attribute.

3.1. Applying the [Authorize] Attribute

Add the [Authorize] attribute to your controller or specific action methods.


using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace MyApi.Controllers
{
    [ApiController]
    [Route("[controller]")]
    [Authorize] // This attribute protects the entire controller
    public class DataController : ControllerBase
    {
        [HttpGet]
        public IActionResult GetSecureData()
        {
            // Accessing claims of the authenticated user
            var userId = User.FindFirst("sub")?.Value;
            var userName = User.Identity?.Name;

            return Ok(new { Message = $"Hello, {userName}! Your ID is {userId}. This is secure data." });
        }

        [HttpGet("public")]
        [AllowAnonymous] // This endpoint is publicly accessible
        public IActionResult GetPublicData()
        {
            return Ok(new { Message = "This is public data, no authentication required." });
        }
    }
}
            

4. Configuring API Scopes in IdentityServer

IdentityServer uses scopes to define permissions for your APIs. You need to configure these scopes in your IdentityServer project's Config.cs or equivalent.


using IdentityServer4.Models;
using System.Collections.Generic;

public static class Config
{
    public static IEnumerable<IdentityServer4.Models.ApiScope> ApiScopes =>
        new List<ApiScope>
        {
            new ApiScope("myapi.read", "Read access to My API"),
            new ApiScope("myapi.write", "Write access to My API")
        };

    public static IEnumerable<IdentityServer4.Models.ApiResource> ApiResources =>
        new List<ApiResource>
        {
            new ApiResource("myapi", "My Application API")
            {
                Scopes = { "myapi.read", "myapi.write" }
            }
        };

    // ... other configurations (Clients, Identity Resources)
}
            

5. Configuring API Client in IdentityServer

Clients are applications that request tokens from IdentityServer. Your ASP.NET Core API itself can act as a client, especially if it needs to call other secured services.


using IdentityServer4.Models;
using System.Collections.Generic;

public static class Config
{
    // ... ApiScopes and ApiResources

    public static IEnumerable<Client> Clients =>
        new List<Client>
        {
            new Client
            {
                ClientId = "api_client",
                ClientName = "API Client",
                AllowedGrantTypes = GrantTypes.ClientCredentials, // For machine-to-machine communication
                ClientSecrets = { new Secret("secret".Sha256()) },
                AllowedScopes = { "myapi.read" }
            }
            // ... other clients
        };

    // ... Identity Resources
}
            

6. Configuring the ASP.NET Core API to Validate Tokens

Your API needs to be configured to trust IdentityServer and validate incoming JWT tokens.

6.1. Add NuGet Packages

Install the following NuGet packages in your API project:

6.2. Configure Authentication in Program.cs (or Startup.cs)


// Program.cs (for .NET 6+)

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

// IdentityServer Configuration
var identityServerUri = builder.Configuration["IdentityServer:Authority"]; // e.g., "https://localhost:5001"

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.Authority = identityServerUri; // URL of your IdentityServer
        options.Audience = "myapi";          // Audience defined in ApiResource
        options.RequireHttpsMetadata = false; // Set to true for production
    });

// Authorization
builder.Services.AddAuthorization(); // Enables [Authorize] attribute

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseHttpsRedirection();

// Authentication Middleware
app.UseAuthentication();

// Authorization Middleware
app.UseAuthorization();

app.MapControllers();

app.Run();
            

Ensure your appsettings.json includes the IdentityServer authority:


{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "IdentityServer": {
    "Authority": "https://localhost:5001" // Replace with your IdentityServer URL
  }
}
            

7. Testing the Secured API

To test, you'll need a client application that can authenticate with IdentityServer and obtain a JWT token. This token should be sent in the Authorization header of your API requests:


Authorization: Bearer [Your_JWT_Token_Here]
            
Important: For production environments, always use HTTPS for both your API and IdentityServer. Set options.RequireHttpsMetadata = true; and configure your SSL certificates properly.

8. Advanced Security Concepts

By following these steps, you can effectively secure your ASP.NET Core Web APIs with IdentityServer, providing robust authentication and authorization for your applications.