A .NET 10 API with layered architecture, JWT authentication via Keycloak, and external HTTP integration via Refit.
Refit-Keycloak.Domain: domain entities and business rulesRefit-Keycloak.Application: use cases and application servicesRefit-Keycloak.Infrastructure: external integrations (Refit and Keycloak)Refit-Keycloak.Api: HTTP entry layer (Minimal API + Swagger)Refit-Keycloak.Tests: unit tests
- .NET 10
- ASP.NET Core Minimal API
- Refit
- Keycloak (JWT Bearer)
- Swagger/OpenAPI (Swashbuckle)
- xUnit + Moq
- .NET 10 SDK installed
- Docker and Docker Compose installed
docker-compose up -dOpen http://localhost:8080 and sign in with:
- user:
admin - password:
admin
- Create realm
dev - Create client
api-client - To test tokens easily, configure the client as:
- Access Type:
Confidential - Service Accounts Enabled:
ON
- Access Type:
- Copy the
Client secret
Note: the API expects the following values in Refit-Keycloak.Api/appsettings.json:
- Authority:
http://localhost:8080/realms/dev - Audience:
api-client
dotnet restore RefitKeycloak.slnxdotnet build RefitKeycloak.slnxdotnet run --project Refit-Keycloak.ApiBy default (launch profile), the API runs on http://localhost:5201.
GET /-> Swagger UIGET /swagger/v1/swagger.json-> OpenAPI documentGET /health-> simple health checkGET /posts-> public endpoint (external data via Refit)GET /secure-> JWT-protected endpoint (Keycloak)
Example with curl:
curl -X POST "http://localhost:8080/realms/dev/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=api-client" \
-d "client_secret=YOUR_CLIENT_SECRET"Copy the returned access_token.
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" http://localhost:5201/securedotnet test RefitKeycloak.slnx- Port already in use: stop the previous process running on port
5201 401on/secure: validateAuthority,Audience,client_id, and token- Swagger not opening: ensure the API is running and access
http://localhost:5201/