# Authentication API Documentation Bu doküman, Django REST API'nin authentication endpoint'lerini ve kullanım örneklerini içerir. ## 📋 İçindekiler 1. [Genel Bilgiler](#genel-bilgiler) 2. [Registration (Kayıt)](#registration-kayıt) 3. [Email Activation (Aktivasyon)](#email-activation-aktivasyon) 4. [Login (Giriş)](#login-giriş) 5. [Token Refresh](#token-refresh) 6. [Social Authentication](#social-authentication) 7. [User Profile](#user-profile) 8. [Password Reset](#password-reset) 9. [Frontend Entegrasyonu](#frontend-entegrasyonu) 10. [Error Handling](#error-handling) --- ## Genel Bilgiler **Base URL:** `http://localhost:8000/api/v1/` **Authentication:** JWT Bearer Token ``` Authorization: Bearer ``` **Content-Type:** `application/json` ### Rate Limiting - **Anonymous users:** 100 requests/hour - **Authenticated users:** 1000 requests/hour --- ## Registration (Kayıt) ### Endpoint ``` POST /api/v1/auth/users/ ``` ### Request Body ```json { "email": "user@example.com", "password": "StrongP@ssw0rd123", "re_password": "StrongP@ssw0rd123", "first_name": "Ali", "last_name": "Veli" } ``` ### Response (201 Created) ```json { "id": 1, "email": "user@example.com", "first_name": "Ali", "last_name": "Veli" } ``` ### Önemli Notlar - Kullanıcı oluşturulur ancak **`is_active=False`** olarak ayarlanır - Aktivasyon emaili otomatik gönderilir - Kullanıcı email aktivasyonu yapmadan login olamaz - Password minimum 8 karakter olmalı ve güçlü olmalı ### Curl Example ```bash curl -X POST http://localhost:8000/api/v1/auth/users/ \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "password": "StrongP@ssw0rd123", "re_password": "StrongP@ssw0rd123", "first_name": "Ali", "last_name": "Veli" }' ``` --- ## Email Activation (Aktivasyon) ### Endpoint ``` POST /api/v1/auth/users/activation/ ``` ### Request Body ```json { "uid": "MQ", "token": "c4h7vu-a8f3d2e1c4b5a6d7e8f9g0h1" } ``` ### Response (204 No Content) Başarılı aktivasyon sonrası response body boş döner. ### Önemli Notlar - `uid` ve `token` aktivasyon emailindeki linkten alınır - Token 24 saat geçerlidir - Başarılı aktivasyon sonrası `is_active=True` olur - Kullanıcı artık login olabilir ### Email Link Format ``` http://localhost:3000/auth/activate/{uid}/{token}/ ``` Frontend bu linki yakalayıp backend'e POST request yapmalı. ### Curl Example ```bash curl -X POST http://localhost:8000/api/v1/auth/users/activation/ \ -H "Content-Type: application/json" \ -d '{ "uid": "MQ", "token": "c4h7vu-a8f3d2e1c4b5a6d7e8f9g0h1" }' ``` ### Resend Activation Email ``` POST /api/v1/auth/users/resend_activation/ ``` Request Body: ```json { "email": "user@example.com" } ``` --- ## Login (Giriş) ### Endpoint ``` POST /api/v1/auth/jwt/create/ ``` ### Request Body ```json { "email": "user@example.com", "password": "StrongP@ssw0rd123" } ``` ### Response (200 OK) ```json { "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` ### Token Bilgileri - **Access Token:** 60 dakika geçerli - **Refresh Token:** 7 gün geçerli - Token rotation aktif (refresh kullanıldığında yeni refresh token döner) ### Önemli Notlar - Kullanıcı `is_active=False` ise login başarısız olur - Hatalı email/password için 401 Unauthorized döner ### Curl Example ```bash curl -X POST http://localhost:8000/api/v1/auth/jwt/create/ \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "password": "StrongP@ssw0rd123" }' ``` ### Error Response (401 Unauthorized) ```json { "detail": "No active account found with the given credentials" } ``` --- ## Token Refresh ### Endpoint ``` POST /api/v1/auth/jwt/refresh/ ``` ### Request Body ```json { "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` ### Response (200 OK) ```json { "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` ### Önemli Notlar - Yeni access token ve yeni refresh token döner (rotation) - Eski refresh token blacklist'e eklenir - Refresh token expire olduysa 401 döner ### Curl Example ```bash curl -X POST http://localhost:8000/api/v1/auth/jwt/refresh/ \ -H "Content-Type: application/json" \ -d '{ "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }' ``` --- ## Social Authentication ### Supported Providers - **Google:** `google-oauth2` - **GitHub:** `github` - **Facebook:** `facebook` ### Endpoint ``` POST /api/v1/auth/social// ``` ### Request Body ```json { "access_token": "ya29.a0AfH6SMBx..." } ``` ### Response (200 OK) ```json { "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "id": 1, "email": "user@example.com", "first_name": "Ali", "last_name": "Veli", "is_active": true, "date_joined": "2025-12-12T21:30:00Z" } } ``` ### Önemli Notlar - Social login ile gelen kullanıcılar **otomatik aktif** (`is_active=True`) - Email aktivasyon gerekmez - Kullanıcı yoksa otomatik oluşturulur - Provider'dan email alınamazsa hata döner ### Google OAuth2 Example #### 1. Frontend'de Google OAuth ```javascript // Google OAuth2 ile token al const googleUser = await gapi.auth2.getAuthInstance().signIn(); const accessToken = googleUser.getAuthResponse().access_token; // Backend'e gönder const response = await fetch('http://localhost:8000/api/v1/auth/social/google-oauth2/', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ access_token: accessToken }) }); const data = await response.json(); // data.access, data.refresh, data.user ``` #### 2. Curl Example ```bash curl -X POST http://localhost:8000/api/v1/auth/social/google-oauth2/ \ -H "Content-Type: application/json" \ -d '{ "access_token": "ya29.a0AfH6SMBx..." }' ``` ### GitHub OAuth2 Example ```bash curl -X POST http://localhost:8000/api/v1/auth/social/github/ \ -H "Content-Type: application/json" \ -d '{ "access_token": "gho_16C7e42F292c6912E7710c838347Ae178B4a" }' ``` ### Error Responses **Invalid Provider (400)** ```json { "error": "Invalid provider. Must be one of: google-oauth2, github, facebook" } ``` **Missing Token (400)** ```json { "error": "access_token is required" } ``` **Authentication Failed (401)** ```json { "error": "Authentication failed. Invalid token." } ``` **Email Not Provided (403)** ```json { "error": "Authentication forbidden. Email not provided by provider or permission denied." } ``` --- ## User Profile ### Get Current User ``` GET /api/v1/auth/users/me/ ``` **Headers:** ``` Authorization: Bearer ``` **Response (200 OK):** ```json { "id": 1, "email": "user@example.com", "first_name": "Ali", "last_name": "Veli", "is_active": true, "date_joined": "2025-12-12T21:30:00Z" } ``` ### Update Current User ``` PATCH /api/v1/auth/users/me/ ``` **Request Body:** ```json { "first_name": "Ahmet", "last_name": "Yılmaz" } ``` ### Curl Example ```bash curl -X GET http://localhost:8000/api/v1/auth/users/me/ \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ``` --- ## Password Reset ### 1. Request Password Reset ``` POST /api/v1/auth/users/reset_password/ ``` **Request Body:** ```json { "email": "user@example.com" } ``` **Response (204 No Content)** Email gönderilir, link formatı: ``` http://localhost:3000/auth/password/reset/confirm/{uid}/{token}/ ``` ### 2. Confirm Password Reset ``` POST /api/v1/auth/users/reset_password_confirm/ ``` **Request Body:** ```json { "uid": "MQ", "token": "c4h7vu-a8f3d2e1c4b5a6d7e8f9g0h1", "new_password": "NewStrongP@ssw0rd123", "re_new_password": "NewStrongP@ssw0rd123" } ``` **Response (204 No Content)** --- ## Frontend Entegrasyonu ### Nuxt.js 3 Example #### 1. Composable: `useAuth.ts` ```typescript // composables/useAuth.ts export const useAuth = () => { const config = useRuntimeConfig(); const accessToken = useCookie('access_token'); const refreshToken = useCookie('refresh_token'); const register = async (userData: { email: string; password: string; re_password: string; first_name: string; last_name: string; }) => { const { data, error } = await useFetch(`${config.public.apiBase}/auth/users/`, { method: 'POST', body: userData, }); return { data, error }; }; const login = async (email: string, password: string) => { const { data, error } = await useFetch(`${config.public.apiBase}/auth/jwt/create/`, { method: 'POST', body: { email, password }, }); if (data.value) { accessToken.value = data.value.access; refreshToken.value = data.value.refresh; } return { data, error }; }; const socialLogin = async (provider: string, accessTokenValue: string) => { const { data, error } = await useFetch( `${config.public.apiBase}/auth/social/${provider}/`, { method: 'POST', body: { access_token: accessTokenValue }, } ); if (data.value) { accessToken.value = data.value.access; refreshToken.value = data.value.refresh; } return { data, error }; }; const getUser = async () => { if (!accessToken.value) return null; const { data } = await useFetch(`${config.public.apiBase}/auth/users/me/`, { headers: { Authorization: `Bearer ${accessToken.value}`, }, }); return data.value; }; const logout = () => { accessToken.value = null; refreshToken.value = null; }; return { register, login, socialLogin, getUser, logout, accessToken, refreshToken, }; }; ``` #### 2. Register Page: `pages/auth/register.vue` ```vue ``` #### 3. Activation Page: `pages/auth/activate/[uid]/[token].vue` ```vue ``` #### 4. Login Page: `pages/auth/login.vue` ```vue ``` ### Next.js 14 Example #### 1. Auth Context: `context/AuthContext.tsx` ```typescript 'use client'; import { createContext, useContext, useState, useEffect } from 'react'; interface User { id: number; email: string; first_name: string; last_name: string; } interface AuthContextType { user: User | null; login: (email: string, password: string) => Promise; logout: () => void; register: (userData: any) => Promise; } const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = useState(null); const [accessToken, setAccessToken] = useState(null); useEffect(() => { // Load token from localStorage const token = localStorage.getItem('access_token'); if (token) { setAccessToken(token); fetchUser(token); } }, []); const fetchUser = async (token: string) => { try { const response = await fetch('http://localhost:8000/api/v1/auth/users/me/', { headers: { 'Authorization': `Bearer ${token}`, }, }); const data = await response.json(); setUser(data); } catch (error) { console.error('Failed to fetch user', error); } }; const login = async (email: string, password: string) => { const response = await fetch('http://localhost:8000/api/v1/auth/jwt/create/', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email, password }), }); if (!response.ok) { throw new Error('Login failed'); } const data = await response.json(); localStorage.setItem('access_token', data.access); localStorage.setItem('refresh_token', data.refresh); setAccessToken(data.access); await fetchUser(data.access); }; const logout = () => { localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); setAccessToken(null); setUser(null); }; const register = async (userData: any) => { const response = await fetch('http://localhost:8000/api/v1/auth/users/', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(userData), }); if (!response.ok) { throw new Error('Registration failed'); } }; return ( {children} ); } export const useAuth = () => { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; }; ``` --- ## Error Handling ### Common Error Codes | Status Code | Meaning | Common Causes | |-------------|---------|---------------| | 400 | Bad Request | Invalid data, validation errors | | 401 | Unauthorized | Invalid credentials, expired token | | 403 | Forbidden | Account not activated, permission denied | | 404 | Not Found | Endpoint doesn't exist | | 429 | Too Many Requests | Rate limit exceeded | | 500 | Internal Server Error | Server-side error | ### Error Response Format ```json { "detail": "Error message here", "field_name": ["Field-specific error"] } ``` ### Example: Registration Validation Error ```json { "email": ["A user with that email already exists."], "password": ["This password is too common."] } ``` --- ## Testing with Postman/Insomnia ### 1. Register ``` POST http://localhost:8000/api/v1/auth/users/ Content-Type: application/json { "email": "test@example.com", "password": "TestP@ssw0rd123", "re_password": "TestP@ssw0rd123", "first_name": "Test", "last_name": "User" } ``` ### 2. Check Email (MailPit) Open: `http://localhost:8025` ### 3. Activate Account ``` POST http://localhost:8000/api/v1/auth/users/activation/ Content-Type: application/json { "uid": "MQ", "token": "c4h7vu-a8f3d2e1c4b5a6d7e8f9g0h1" } ``` ### 4. Login ``` POST http://localhost:8000/api/v1/auth/jwt/create/ Content-Type: application/json { "email": "test@example.com", "password": "TestP@ssw0rd123" } ``` ### 5. Get User Profile ``` GET http://localhost:8000/api/v1/auth/users/me/ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` --- ## Environment Variables ### Development (.env.dev) ```bash DEBUG=True SECRET_KEY=your-secret-key-here ALLOWED_HOSTS=localhost,127.0.0.1 # Database DATABASE_URL=sqlite:///db.sqlite3 # Email (MailPit) EMAIL_HOST=localhost EMAIL_PORT=1025 EMAIL_USE_TLS=False # CORS CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173 ``` ### Production (.env.prod) ```bash DEBUG=False SECRET_KEY=your-production-secret-key ALLOWED_HOSTS=yourdomain.com,api.yourdomain.com # Database DATABASE_URL=postgresql://user:pass@host:5432/dbname # Email EMAIL_HOST=smtp.gmail.com EMAIL_PORT=587 EMAIL_USE_TLS=True EMAIL_HOST_USER=your-email@gmail.com EMAIL_HOST_PASSWORD=your-app-password # Social Auth SOCIAL_AUTH_GOOGLE_OAUTH2_KEY=your-google-client-id SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET=your-google-client-secret SOCIAL_AUTH_GITHUB_KEY=your-github-client-id SOCIAL_AUTH_GITHUB_SECRET=your-github-client-secret # CORS CORS_ALLOWED_ORIGINS=https://yourdomain.com ``` --- ## Support Sorularınız için: - GitHub Issues: [Your Repo] - Email: support@yourdomain.com - Documentation: [Your Docs URL] --- **Last Updated:** 2025-12-12 **Version:** 1.0.0