Files
dj52/AUTH.md
Beyhan Oğur ec28a2024d first commit
2026-04-26 22:22:29 +03:00

19 KiB
Raw Blame History

Authentication API Documentation

Bu doküman, Django REST API'nin authentication endpoint'lerini ve kullanım örneklerini içerir.

📋 İçindekiler

  1. Genel Bilgiler
  2. Registration (Kayıt)
  3. Email Activation (Aktivasyon)
  4. Login (Giriş)
  5. Token Refresh
  6. Social Authentication
  7. User Profile
  8. Password Reset
  9. Frontend Entegrasyonu
  10. 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

{
  "email": "user@example.com",
  "password": "StrongP@ssw0rd123",
  "re_password": "StrongP@ssw0rd123",
  "first_name": "Ali",
  "last_name": "Veli"
}

Response (201 Created)

{
  "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

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

{
  "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
http://localhost:3000/auth/activate/{uid}/{token}/

Frontend bu linki yakalayıp backend'e POST request yapmalı.

Curl Example

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:

{
  "email": "user@example.com"
}

Login (Giriş)

Endpoint

POST /api/v1/auth/jwt/create/

Request Body

{
  "email": "user@example.com",
  "password": "StrongP@ssw0rd123"
}

Response (200 OK)

{
  "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

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)

{
  "detail": "No active account found with the given credentials"
}

Token Refresh

Endpoint

POST /api/v1/auth/jwt/refresh/

Request Body

{
  "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response (200 OK)

{
  "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

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

{
  "access_token": "ya29.a0AfH6SMBx..."
}

Response (200 OK)

{
  "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

// 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

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

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)

{
  "error": "Invalid provider. Must be one of: google-oauth2, github, facebook"
}

Missing Token (400)

{
  "error": "access_token is required"
}

Authentication Failed (401)

{
  "error": "Authentication failed. Invalid token."
}

Email Not Provided (403)

{
  "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):

{
  "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:

{
  "first_name": "Ahmet",
  "last_name": "Yılmaz"
}

Curl Example

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:

{
  "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:

{
  "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

// 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

<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

<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

<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

'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

{
  "detail": "Error message here",
  "field_name": ["Field-specific error"]
}

Example: Registration Validation Error

{
  "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)

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)

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:


Last Updated: 2025-12-12 Version: 1.0.0