๐ IdentityServer Overview
IdentityServer, now Duende IdentityServer, is an authentication server that implements the OpenID Connect (OIDC) and OAuth 2.0 standards for ASP.NET Core. It acts as a central security token service (STS) for all your applicationsโincluding web, mobile, and APIsโto provide Single Sign-On (SSO) and API access control in a standardized, secure way.
๐ฆ This approach is highly recommended for complex, modern application architectures (e.g., microservices) where you have multiple client applications (like SPAs and mobile apps) that need to access multiple APIs. For simpler, single-application scenarios, ASP.NET Core Identity may be sufficient.
โ๏ธ How it works
An IdentityServer instance is a custom ASP.NET Core application that runs the Duende IdentityServer middleware. It exposes several standard endpoints to handle authentication and token issuance.
๐ The high-level flow is:
- ๐ค A user accesses a client application (e.g., a web app).
- ๐ The client redirects the user to the IdentityServer's login page for authentication.
- ๐ The user enters their credentials on the IdentityServer's login page, which authenticates the user.
- ๐ซ IdentityServer redirects the user back to the client application with an identity token and, potentially, an authorization code.
- ๐จ The client application uses the code to request an access token from IdentityServer, which it uses to access protected APIs.
- โ The API validates the token and grants or denies access to the requested resource.
๐งช Example in .NET Core
This example provides the foundational steps to set up an IdentityServer, a client application, and a protected API.
1๏ธโฃ Create the IdentityServer project
First, create a new ASP.NET Core project to host IdentityServer.
Install the NuGet package:
dotnet add package Duende.IdentityServer
Add IdentityServer to the service container (Program.cs):
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddIdentityServer()
.AddInMemoryClients(Config.Clients)
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddTestUsers(Config.TestUsers) // For development only
.AddDeveloperSigningCredential(); // For development only
var app = builder.Build();
app.UseIdentityServer(); // Add the middleware
app.Run();
Define client and resource configurations (Config.cs):
This example uses in-memory configuration, but in production, you would use a database with Entity Framework Core.
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Test;
public static class Config
{
public static IEnumerable IdentityResources =>
new List
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
public static IEnumerable<ApiScope> ApiScopes =>
new List<ApiScope>
{
new ApiScope("api1", "My API")
};
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedScopes = { "api1" }
}
};
public static List<TestUser> TestUsers =>
new List<TestUser>
{
new TestUser
{
SubjectId = "1",
Username = "alice",
Password = "password",
Claims = { new System.Security.Claims.Claim("given_name", "Alice") }
}
};
}
2๏ธโฃ Create the protected API
Next, create a separate API project that trusts and uses IdentityServer.
Install the NuGet package:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Add authentication services to the API (Program.cs):
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://localhost:5001"; // The URL of your IdentityServer
options.Audience = "api1";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers().RequireAuthorization();
app.Run();
Secure an endpoint:
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
// ...
}
๐ Advantages and disadvantages
| Aspect | Advantages | Disadvantages |
|---|---|---|
| Advantages | Centralized security: Provides a single, centralized authentication point, enforcing consistent security policies across all applications. Single Sign-On (SSO): Users log in once to access multiple applications seamlessly. Standardized protocols: Based on OpenID Connect and OAuth 2.0, ensuring interoperability with various clients and identity providers. Extensibility: Highly customizable to fit specific business logic and integrates with ASP.NET Core Identity for user management. |
Complexity and learning curve: Implementing and managing IdentityServer is more complex than simple cookie-based authentication and requires a strong understanding of security protocols. Licensing costs: While older versions were open-source, Duende IdentityServer requires a paid license for most production commercial use cases. Maintenance overhead: As a self-hosted solution, you are responsible for its security, patching, and scalability. |
๐ก Best practices and tips
- ๐ Secure your signing credentials: Use a cryptographically secure certificate for token signing. Never use AddDeveloperSigningCredential() in production. Use a secure secrets store like Azure Key Vault to manage certificates.
- ๐ Use the correct grant type: Always use the Authorization Code with Proof Key for Code Exchange (PKCE) for client-side applications (SPAs, mobile apps). Use Client Credentials for server-to-server communication.
- ๐งช Validate tokens correctly: Ensure your APIs are configured to validate tokens by setting the correct Authority and Audience in AddJwtBearer.
- ๐ฆ Manage clients and scopes correctly: Configure client and resource access appropriately, following the principle of least privilege. Clients should only request the scopes they need.
- ๐๏ธ Integrate with a real database: In production, store your configuration (clients, resources) and operational data (tokens, grants) in a persistent store like a database using the Entity Framework Core packages.
๐ Alternatives to Duende IdentityServer
- ๐ OpenIddict: A free, open-source alternative to Duende IdentityServer. It's a library that lets you build your own STS and is a good option if you want to avoid licensing costs but still want full control over your implementation.
- ๐งฐ Keycloak: An open-source, Java-based identity and access management (IAM) solution that offers a ready-to-run server and an admin console. It provides more out-of-the-box features than Duende, but may offer less flexibility.
- โ๏ธ Managed services (e.g., Auth0, Microsoft Entra ID): These are cloud-based, identity-as-a-service providers. They reduce your maintenance burden but come with costs and potentially less customization.