fengling-console/docs/task-03-configure-openiddict.md

203 lines
5.7 KiB
Markdown

# Task 3: Configure OpenIddict
## Task Description
**Files:**
- Create: `src/Fengling.AuthService/Configuration/OpenIddictSetup.cs`
- Modify: `src/Fengling.AuthService/Program.cs`
## Implementation Steps
### Step 1: Create OpenIddict configuration
Create: `src/Fengling.AuthService/Configuration/OpenIddictSetup.cs`
```csharp
using Microsoft.Extensions.DependencyInjection;
using OpenIddict.Validation.AspNetCore;
namespace Fengling.AuthService.Configuration;
public static class OpenIddictSetup
{
public static IServiceCollection AddOpenIddictConfiguration(this IServiceCollection services, IConfiguration configuration)
{
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<Data.ApplicationDbContext>();
})
.AddServer(options =>
{
options.SetIssuer(configuration["OpenIddict:Issuer"] ?? "https://auth.fengling.local");
options.AddSigningKey(new SymmetricSecurityKey(
System.Text.Encoding.UTF8.GetBytes("fengling-super-secret-key-for-dev-only-change-in-prod-please!!!")));
options.AllowAuthorizationCodeFlow()
.AllowPasswordFlow()
.AllowRefreshTokenFlow()
.RequireProofKeyForCodeExchange();
options.RegisterScopes("api", "offline_access");
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
options.UseAspNetCore()
.EnableAuthorizationEndpointPassThrough()
.EnableTokenEndpointPassThrough()
.EnableLogoutEndpointPassThrough();
})
.AddValidation(options =>
{
options.UseLocalServer();
options.UseAspNetCore();
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
});
return services;
}
}
```
### Step 2: Update Program.cs with OpenIddict and EF Core
Edit: `src/Fengling.AuthService/Program.cs`
```csharp
using Fengling.AuthService.Configuration;
using Fengling.AuthService.Data;
using Fengling.AuthService.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Serilog;
var builder = WebApplication.CreateBuilder(args);
// Serilog
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.CreateLogger();
builder.Host.UseSerilog();
// Database
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
// Identity
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// OpenIddict
builder.Services.AddOpenIddictConfiguration(builder.Configuration);
// OpenTelemetry
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource =>
resource.AddService("Fengling.AuthService"))
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddSource("OpenIddict.Server.AspNetCore")
.AddOtlpExporter();
// Controllers
builder.Services.AddControllers();
// Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Fengling Auth Service",
Version = "v1",
Description = "Authentication and authorization service using OpenIddict"
});
options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
Password = new OpenApiOAuthFlow
{
TokenUrl = "/connect/token"
}
}
});
});
var app = builder.Build();
// Configure pipeline
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Fengling Auth Service v1");
options.OAuthClientId("swagger-ui");
options.OAuthUsePkce();
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
```
### Step 3: Run to verify startup
Run:
```bash
dotnet run
```
Expected: Service starts without errors, Swagger UI available at http://localhost:5000/swagger
### Step 4: Commit
```bash
git add src/Fengling.AuthService/Configuration/ src/Fengling.AuthService/Program.cs
git commit -m "feat(auth): configure OpenIddict with JWT and OAuth2 support"
```
## Context
This task configures OpenIddict for OAuth2/OIDC authentication, including:
- Server configuration with token endpoints
- Password flow for user authentication
- Development certificates for signing
- Integration with ASP.NET Core Identity
- Swagger UI with OAuth2 support
**Tech Stack**: OpenIddict 7.2.0, ASP.NET Core Identity, Swagger
## Verification
- [ ] OpenIddictSetup class created
- [ ] Program.cs updated with OpenIddict configuration
- [ ] Service starts without errors
- [ ] Swagger UI accessible
- [ ] Committed to git
## Notes
- Using symmetric key for token signing (dev only)
- Password flow enabled for direct authentication
- Development certificates used (replace in production)