# 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 <access_token>
```

**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/<provider>/
```

### 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 <access_token>
```

**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
<template>
  <div>
    <h1>Register</h1>
    <form @submit.prevent="handleRegister">
      <input v-model="form.email" type="email" placeholder="Email" required />
      <input v-model="form.first_name" placeholder="First Name" />
      <input v-model="form.last_name" placeholder="Last Name" />
      <input v-model="form.password" type="password" placeholder="Password" required />
      <input v-model="form.re_password" type="password" placeholder="Confirm Password" required />
      <button type="submit">Register</button>
    </form>
    <p v-if="message">{{ message }}</p>
  </div>
</template>

<script setup lang="ts">
const { register } = useAuth();
const form = ref({
  email: '',
  password: '',
  re_password: '',
  first_name: '',
  last_name: '',
});
const message = ref('');

const handleRegister = async () => {
  const { data, error } = await register(form.value);
  
  if (error.value) {
    message.value = 'Registration failed';
  } else {
    message.value = 'Registration successful! Please check your email to activate your account.';
  }
};
</script>
```

#### 3. Activation Page: `pages/auth/activate/[uid]/[token].vue`
```vue
<template>
  <div>
    <h1>Account Activation</h1>
    <p v-if="loading">Activating your account...</p>
    <p v-else-if="success">✅ Account activated successfully! You can now login.</p>
    <p v-else-if="error">❌ Activation failed. Link may be expired.</p>
  </div>
</template>

<script setup lang="ts">
const route = useRoute();
const config = useRuntimeConfig();

const loading = ref(true);
const success = ref(false);
const error = ref(false);

onMounted(async () => {
  const { uid, token } = route.params;
  
  try {
    await $fetch(`${config.public.apiBase}/auth/users/activation/`, {
      method: 'POST',
      body: { uid, token },
    });
    success.value = true;
  } catch (e) {
    error.value = true;
  } finally {
    loading.value = false;
  }
});
</script>
```

#### 4. Login Page: `pages/auth/login.vue`
```vue
<template>
  <div>
    <h1>Login</h1>
    <form @submit.prevent="handleLogin">
      <input v-model="email" type="email" placeholder="Email" required />
      <input v-model="password" type="password" placeholder="Password" required />
      <button type="submit">Login</button>
    </form>
    
    <div class="social-login">
      <button @click="handleGoogleLogin">Login with Google</button>
      <button @click="handleGithubLogin">Login with GitHub</button>
    </div>
    
    <p v-if="error">{{ error }}</p>
  </div>
</template>

<script setup lang="ts">
const { login, socialLogin } = useAuth();
const router = useRouter();

const email = ref('');
const password = ref('');
const error = ref('');

const handleLogin = async () => {
  const { data, error: loginError } = await login(email.value, password.value);
  
  if (loginError.value) {
    error.value = 'Login failed. Please check your credentials.';
  } else {
    router.push('/dashboard');
  }
};

const handleGoogleLogin = async () => {
  // Google OAuth2 implementation
  // Use @nuxtjs/google-oauth2 or similar
  const googleToken = await getGoogleAccessToken(); // Your implementation
  
  const { data, error: socialError } = await socialLogin('google-oauth2', googleToken);
  
  if (!socialError.value) {
    router.push('/dashboard');
  }
};

const handleGithubLogin = async () => {
  // GitHub OAuth2 implementation
  const githubToken = await getGithubAccessToken(); // Your implementation
  
  const { data, error: socialError } = await socialLogin('github', githubToken);
  
  if (!socialError.value) {
    router.push('/dashboard');
  }
};
</script>
```

### 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<void>;
  logout: () => void;
  register: (userData: any) => Promise<void>;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [accessToken, setAccessToken] = useState<string | null>(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 (
    <AuthContext.Provider value={{ user, login, logout, register }}>
      {children}
    </AuthContext.Provider>
  );
}

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

