# 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 ───► │ 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 ```