first commit
This commit is contained in:
201
belgeler/auth.md
Normal file
201
belgeler/auth.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# Kimlik Doğrulama Sistemi
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Proje email + şifre tabanlı kimlik doğrulama kullanır. Başarılı girişte iki token döner:
|
||||
|
||||
| Token | Ömür | Kullanım |
|
||||
|---|---|---|
|
||||
| `access_token` | 15 dakika | Her korumalı isteğe `Authorization: Bearer` başlığı |
|
||||
| `refresh_token` | 7 gün | Süresi dolan access token'ı yenilemek için |
|
||||
|
||||
Ek kural: Email doğrulaması tamamlanmadan login ve refresh işlemleri engellenir.
|
||||
|
||||
Algoritma: **HS256** (HMAC-SHA256)
|
||||
|
||||
---
|
||||
|
||||
## Akış Diyagramı
|
||||
|
||||
```
|
||||
┌─────────┐ POST /api/v1/auth/register ┌─────────┐
|
||||
│ Client │ ────────────────────────────────────► │ Server │
|
||||
│ │ ◄──── 201 { user_id } + verify mail │ │
|
||||
└─────────┘ └─────────┘
|
||||
|
||||
┌─────────┐ GET /api/v1/auth/verify-email ┌─────────┐
|
||||
│ Client │ ── token linki ile ──────────────────► │ Server │
|
||||
│ │ ◄──── 200 email verified ──────────── │ │
|
||||
└─────────┘ └─────────┘
|
||||
|
||||
┌─────────┐ POST /api/v1/auth/login ┌─────────┐
|
||||
│ Client │ ── { email, password } ──────────────► │ Server │
|
||||
│ │ ◄── 200 { access_token, │ │
|
||||
│ │ refresh_token } ───────────── └─────────┘
|
||||
└─────────┘
|
||||
|
||||
┌─────────┐ GET /api/v1/me ┌─────────┐
|
||||
│ Client │ ── Authorization: Bearer <access> ───► │ Server │
|
||||
│ │ ◄── 200 { user_id, email, username } │ (auth │
|
||||
└─────────┘ │ middleware)
|
||||
└─────────┘
|
||||
|
||||
┌─────────┐ POST /api/v1/auth/refresh ┌─────────┐
|
||||
│ Client │ ── { refresh_token } ────────────────► │ Server │
|
||||
│ │ ◄── 200 { access_token } ───────────── └─────────┘
|
||||
└─────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Kayıt (`Register`)
|
||||
|
||||
**Dosya:** `app/accounts/controllers/user.go` → `Register()`
|
||||
|
||||
1. JSON body doğrulanır (`username` min 3, `email` geçerli format, `password` min 8 karakter, `confirm_password` min 8 karakter).
|
||||
2. `password` ve `confirm_password` eşleşmesi kontrol edilir.
|
||||
3. Şifre `bcrypt.DefaultCost` ile hash'lenir.
|
||||
4. `User` kaydı veritabanına yazılır.
|
||||
5. Rastgele bir email doğrulama token'ı üretilir ve kullanıcıya yazılır.
|
||||
6. Kullanıcıya doğrulama maili gönderilir.
|
||||
7. `email` alanı unique index'li; duplicate durumunda `409 Conflict` döner.
|
||||
|
||||
Not: Mail gönderimi başarısız olursa oluşturulan kullanıcı kaydı geri silinir.
|
||||
|
||||
```json
|
||||
// İstek
|
||||
{
|
||||
"username": "ali",
|
||||
"email": "ali@ornek.com",
|
||||
"password": "gizli1234",
|
||||
"confirm_password": "gizli1234"
|
||||
}
|
||||
|
||||
// Başarılı yanıt 201
|
||||
{ "message": "user created. please verify your email", "user_id": 1 }
|
||||
```
|
||||
|
||||
## Email Doğrulama (`VerifyEmail`)
|
||||
|
||||
**Dosya:** `app/accounts/controllers/user.go` → `VerifyEmail()`
|
||||
|
||||
1. Query string içinden `token` alınır.
|
||||
2. Token ile kullanıcı bulunur.
|
||||
3. `email_verified=true`, `email_verified_at=now`, `email_verify_token=""` olarak güncellenir.
|
||||
|
||||
```json
|
||||
// Başarılı yanıt 200
|
||||
{ "message": "email verified successfully" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Giriş (`Login`)
|
||||
|
||||
**Dosya:** `app/accounts/controllers/user.go` → `Login()`
|
||||
|
||||
1. Email ile kullanıcı aranır.
|
||||
2. `email_verified` kontrol edilir; doğrulanmamış hesaplara `403` dönülür.
|
||||
3. `bcrypt.CompareHashAndPassword` ile şifre doğrulanır.
|
||||
4. Her iki adımda da hata mesajı aynı tutulur — kullanıcı numaralandırma saldırısına karşı.
|
||||
5. Başarıda access + refresh token döner.
|
||||
|
||||
```json
|
||||
// İstek
|
||||
{ "email": "ali@ornek.com", "password": "gizli1234" }
|
||||
|
||||
// Başarılı yanıt 200
|
||||
{
|
||||
"access_token": "eyJ...",
|
||||
"refresh_token": "eyJ...",
|
||||
"token_type": "Bearer"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Token Yenileme (`RefreshToken`)
|
||||
|
||||
**Dosya:** `app/accounts/controllers/user.go` → `RefreshToken()`
|
||||
|
||||
1. Body'den `refresh_token` alınır.
|
||||
2. `JWT_REFRESH_SECRET` ile doğrulanır.
|
||||
3. Kullanıcının `email_verified` durumu kontrol edilir; doğrulanmamışsa `403` döner.
|
||||
4. Claims'ten `user_id`, `email`, `username` alanları kullanılarak yeni access token üretilir.
|
||||
5. Refresh token yenilenmez (sliding window değil, sabit pencere).
|
||||
|
||||
```json
|
||||
// İstek
|
||||
{ "refresh_token": "eyJ..." }
|
||||
|
||||
// Başarılı yanıt 200
|
||||
{ "access_token": "eyJ...", "token_type": "Bearer" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Google Login (OAuth 2.0)
|
||||
|
||||
**Dosya:** `app/accounts/controllers/user.go` → `GoogleLogin()` ve `GoogleCallback()`
|
||||
|
||||
Akış:
|
||||
|
||||
1. `GET /api/v1/auth/google/login`
|
||||
2. Sunucu CSRF için `state` üretir, cookie'ye yazar ve `auth_url` döner.
|
||||
3. Client kullanıcıyı `auth_url` adresine yönlendirir.
|
||||
4. Google kullanıcıyı callback'e döndürür: `GET /api/v1/auth/google/callback?state=...&code=...`
|
||||
5. Sunucu `state` doğrular, `code` ile Google'dan token alır.
|
||||
6. Google `userinfo` verisi çekilir.
|
||||
7. Kullanıcı email'e göre bulunur/oluşturulur, `SocialAccount(provider=google)` kaydı bağlanır.
|
||||
8. Google ile gelen kullanıcı email'i doğrulanmış kabul edilir (`email_verified=true`).
|
||||
9. Yerel `access_token` + `refresh_token` üretilip döndürülür.
|
||||
|
||||
Yeni endpointler:
|
||||
|
||||
- `GET /api/v1/auth/google/login`
|
||||
- `GET /api/v1/auth/google/callback`
|
||||
|
||||
---
|
||||
|
||||
## GitHub Login (OAuth 2.0)
|
||||
|
||||
**Dosya:** `app/accounts/controllers/user.go` → `GitHubLogin()` ve `GitHubCallback()`
|
||||
|
||||
Akış:
|
||||
|
||||
1. `GET /api/v1/auth/github/login`
|
||||
2. Sunucu CSRF için `state` üretir, cookie'ye yazar ve `auth_url` döner.
|
||||
3. Client kullanıcıyı `auth_url` adresine yönlendirir.
|
||||
4. GitHub callback'e döndürür: `GET /api/v1/auth/github/callback?state=...&code=...`
|
||||
5. Sunucu `state` doğrular, `code` ile GitHub'dan token alır.
|
||||
6. GitHub profil/email bilgisi çekilir.
|
||||
7. Kullanıcı email'e göre bulunur/oluşturulur, `SocialAccount(provider=github)` kaydı bağlanır.
|
||||
8. GitHub ile gelen kullanıcı email'i doğrulanmış kabul edilir (`email_verified=true`).
|
||||
9. Yerel `access_token` + `refresh_token` üretilip döndürülür.
|
||||
|
||||
Yeni endpointler:
|
||||
|
||||
- `GET /api/v1/auth/github/login`
|
||||
- `GET /api/v1/auth/github/callback`
|
||||
|
||||
---
|
||||
|
||||
## Güvenlik Notları
|
||||
|
||||
- Şifreler veritabanında **asla düz metin** tutulmaz; bcrypt hash'i saklanır.
|
||||
- `Password` alanı modelde `json:"-"` ile işaretlidir — API yanıtlarında görünmez.
|
||||
- Access ve refresh token farklı secret'larla imzalanır (`JWT_SECRET` / `JWT_REFRESH_SECRET`).
|
||||
- Production'da her iki secret'ın en az 32 karakter uzunluğunda, rastgele olması gerekir.
|
||||
- HTTPS zorunludur; token'lar aktarım sırasında şifrelenmez.
|
||||
- Register adımında şifre uyumsuzluğu için `400 Bad Request` dönülür: `password and confirm_password do not match`.
|
||||
|
||||
---
|
||||
|
||||
## Swagger
|
||||
|
||||
- Swagger UI: `/swagger/index.html`
|
||||
- Doküman üretme komutu:
|
||||
|
||||
```bash
|
||||
$(go env GOPATH)/bin/swag init -g main.go
|
||||
```
|
||||
Reference in New Issue
Block a user