.NET 8 Authentication — JWT Access Token + Refresh Token Rotation + PBKDF2 Hashing + Rate Limiting + Clean Architecture
Bu proje, API sistemlerinde kullanılan JWT access token + refresh token rotation mekanizmasını baştan sona gösteren bir mini örnektir.
- .NET 8 Web API
- JWT access token (short-lived)
- Refresh token (long-lived) + Rotation
- Token revoke chain (reuse tespiti & engelleme)
- PBKDF2 password hashing
- InMemory refresh token store (Redis-ready mimari)
- IP-based rate limiting (5 req/min)
- Clean Architecture: Api / Application / Domain / Infrastructure
- xUnit + FluentAssertions testleri
- Mermaid sequence diagram’lı dokümantasyon
dotnet-oauth2-refresh-token-api/
│
├── src/
│ ├── Auth.Api/ → Web API (Controllers, Middleware, DI)
│ ├── Auth.Application/ → Login & Refresh use-case’leri
│ ├── Auth.Domain/ → Entities (User, RefreshToken)
│ └── Auth.Infrastructure/ → JWT, Hashing, TokenStore, UserStore
│
└── tests/
├── Auth.Application.Tests/
└── Auth.Api.Tests/
| Katman | Sorumluluk |
|---|---|
| Domain | User & RefreshToken modelleri, business rules |
| Application | AuthService (login, refresh, rotation) |
| Infrastructure | Hashing, JWT üretimi, token store, user store |
| Api | Controller, rate limiting, DI, authentication middleware |
sequenceDiagram
autonumber
User->>API: POST /auth/login {userName, password}
API->>UserService: GetByUserNameAsync
UserService-->>API: User
API->>PasswordHasher: VerifyPassword
PasswordHasher-->>API: ok
API->>JwtGenerator: GenerateAccessToken(user)
JwtGenerator-->>API: access_token
API->>RefreshTokenStore: StoreAsync(refresh_token)
RefreshTokenStore-->>API: stored
API-->>User: 200 {accessToken, refreshToken, expiresIn}
sequenceDiagram
autonumber
User->>API: POST /auth/refresh {refreshToken}
API->>RefreshTokenStore: GetAsync(refreshToken)
RefreshTokenStore-->>API: RefreshToken
API->>RefreshToken: IsActive?
RefreshToken-->>API: true
API->>UserService: GetByIdAsync(UserId)
UserService-->>API: User
API->>RefreshTokenStore: UpdateAsync(oldToken: revoked + replacedByToken)
API->>RefreshTokenStore: StoreAsync(newRefreshToken)
API->>JwtGenerator: GenerateAccessToken(user)
JwtGenerator-->>API: access_token
API-->>User: 200 {accessToken, refreshToken(new), expiresIn}
git clone https://github.com/<username>/dotnet-oauth2-refresh-token-api.git
cd dotnet-oauth2-refresh-token-api
dotnet restore
dotnet build
dotnet run --project src/Auth.Api/Auth.Api.csproj
POST /auth/login
Content-Type: application/json
{
"userName": "testuser",
"password": "Password123!"
}
POST /auth/refresh
Content-Type: application/json
{
"refreshToken": "<REFRESH_TOKEN>"
}
Yalnızca login ve refresh endpoint’lerinde aktif:
IP başına 1 dakikada 5 istek
Limit aşılırsa:
429 Too Many Requests
Bu brute-force saldırılarına karşı kritik savunmadır.
100.000 iterations
16-byte salt
32-byte key
Constant-time comparison
Her refresh çağrısında yeni refresh token üretilir.
Eski token revoke edilir. (artık geçersiz)
ReplacedByToken alanı zincir oluşturur.
HMAC-SHA256
sub, unique_name, jti claim’leri
Ömür: 5 dakika