← Dashboard'a Dön

🔐 Supabase Auth Clone - Dokümantasyon

📋 İçindekiler

Genel Bakış

Bu sistem, Supabase Auth API'sini taklit eden bir PHP/MySQL tabanlı authentication sistemidir. Mevcut Wo_Users tablonuzu kullanır ve Supabase Flutter paketleri ile %95 uyumludur.

Özellikler

⚠️ Supabase Auth ile Farklar

ÖNEMLİ: Supabase Flutter Paketi Kullanılamaz!

Supabase Flutter paketi (supabase_flutter), bu API ile DOĞRUDAN ÇALIŞMAZ!

Supabase paketi, Supabase'in kendi sunucularına özel olarak tasarlanmıştır ve bizim API'miz ile uyumsuz internal routing'e sahiptir.

1. URL Yapısı

❌ YANLIŞ (Çalışmaz):
Supabase.initialize(
  url: 'https://dev.motoclup.com',
  anonKey: 'your-key',
);
✅ DOĞRU (Çalışır):

Supabase paketini KULLANMAYIN, direkt HTTP istekleri yapın.

2. Neden Supabase Paketi Çalışmaz?

3. Çözüm: HTTP Client Kullanın

// ❌ YANLIŞ - Supabase paketi kullanmayın
import 'package:supabase_flutter/supabase_flutter.dart';

// ✅ DOĞRU - HTTP client kullanın
import 'package:http/http.dart' as http;
import 'dart:convert';

Kurulum ve Yapılandırma

Backend Yapılandırması

1. JWT Secret Ayarı

config.php dosyasında:

define('JWT_SECRET', 'your-super-secret-jwt-key-change-this-in-production');
define('JWT_EXPIRATION', 3600); // 1 saat

2. API Key

define('API_KEY', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9');

3. Database Tablosu

Mevcut Wo_Users tablonuz kullanılır. Gerekli kolonlar:

API Endpoints

Base URL

https://dev.motoclup.com/auth/v1

1. Sign Up (Kayıt)

Endpoint: POST /auth/v1/signup

Request:

{
  "email": "[email protected]",
  "password": "password123",
  "data": {
    "first_name": "John",
    "last_name": "Doe"
  }
}

Response (200):

{
  "access_token": "eyJhbGci...",
  "token_type": "bearer",
  "expires_in": 3600,
  "refresh_token": "eyJhbGci...",
  "user": {
    "id": 1,
    "email": "[email protected]",
    "role": "authenticated",
    "user_metadata": {
      "username": "john123",
      "first_name": "John",
      "last_name": "Doe"
    }
  }
}

2. Sign In (Giriş)

Endpoint: POST /auth/v1/token?grant_type=password

Request:

{
  "email": "[email protected]",
  "password": "password123"
}

Response: Sign Up ile aynı format

3. Get User (Kullanıcı Bilgisi)

Endpoint: GET /auth/v1/user

Headers:

Authorization: Bearer <access_token>

4. Update User (Güncelleme)

Endpoint: PATCH /auth/v1/user

Headers:

Authorization: Bearer <access_token>
Content-Type: application/json

Request:

{
  "first_name": "Jane",
  "about": "New bio"
}

5. Refresh Token

Endpoint: POST /auth/v1/token?grant_type=refresh_token

Request:

{
  "refresh_token": "eyJhbGci..."
}

6. Logout

Endpoint: POST /auth/v1/logout

Headers:

Authorization: Bearer <access_token>

Response: 204 No Content

Flutter Entegrasyonu

Dependencies (pubspec.yaml)

dependencies:
  http: ^1.1.0
  shared_preferences: ^2.2.0

AuthService Sınıfı

import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';

class AuthService {
  static const String baseUrl = 'https://dev.motoclup.com';
  static const String apiKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9';
  
  String? _accessToken;
  String? _refreshToken;
  Map<String, dynamic>? _currentUser;
  
  // Sign In
  Future<Map<String, dynamic>> signIn({
    required String email,
    required String password,
  }) async {
    final response = await http.post(
      Uri.parse('$baseUrl/auth/v1/token?grant_type=password'),
      headers: {
        'Content-Type': 'application/json',
        'apikey': apiKey,
      },
      body: jsonEncode({
        'email': email,
        'password': password,
      }),
    );
    
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      _accessToken = data['access_token'];
      _refreshToken = data['refresh_token'];
      _currentUser = data['user'];
      
      await _saveTokens();
      
      return data;
    } else {
      throw Exception(jsonDecode(response.body)['message']);
    }
  }
  
  // Get Current User
  Future<Map<String, dynamic>?> getCurrentUser() async {
    if (_accessToken == null) {
      await _loadTokens();
    }
    
    if (_accessToken == null) return null;
    
    final response = await http.get(
      Uri.parse('$baseUrl/auth/v1/user'),
      headers: {
        'Authorization': 'Bearer $_accessToken',
        'apikey': apiKey,
      },
    );
    
    if (response.statusCode == 200) {
      _currentUser = jsonDecode(response.body);
      return _currentUser;
    } else if (response.statusCode == 401) {
      await refreshSession();
      return getCurrentUser();
    }
    
    return null;
  }
  
  // Private methods
  Future<void> _saveTokens() async {
    final prefs = await SharedPreferences.getInstance();
    if (_accessToken != null) {
      await prefs.setString('access_token', _accessToken!);
    }
    if (_refreshToken != null) {
      await prefs.setString('refresh_token', _refreshToken!);
    }
  }
  
  Future<void> _loadTokens() async {
    final prefs = await SharedPreferences.getInstance();
    _accessToken = prefs.getString('access_token');
    _refreshToken = prefs.getString('refresh_token');
  }
}

Kullanım Örneği

final authService = AuthService();

// Sign In
try {
  await authService.signIn(
    email: '[email protected]',
    password: 'password123',
  );
  print('Signed in!');
} catch (e) {
  print('Error: $e');
}

// Get Current User
final user = await authService.getCurrentUser();
print('User: ${user?['email']}');

Hata Çözümleri

1. "Failed to fetch" Hatası

Sorun: Flutter uygulaması API'ye erişemiyor.

Çözüm (Android):

android/app/src/main/AndroidManifest.xml dosyasında:

<application
    android:usesCleartextTraffic="true">

2. SSL Certificate Hatası

Geliştirme ortamı için:

import 'dart:io';

class MyHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..badCertificateCallback = (cert, host, port) => true;
  }
}

// main.dart'ta
void main() {
  HttpOverrides.global = MyHttpOverrides();
  runApp(MyApp());
}
⚠️ Uyarı: Production'da SSL sertifikası kullanın!

3. Token Expired Hatası

Çözüm: Otomatik refresh mekanizması kullanın (yukarıdaki AuthService'te mevcut).

Güvenlik Notları

Production Checklist

Token Güvenliği

Test Sayfaları

Özet

✅ Yapılması Gerekenler:

  1. HTTP client kullanın (Supabase paketi DEĞİL)
  2. AuthService sınıfı oluşturun
  3. Token'ları secure storage'da saklayın
  4. Error handling ekleyin
  5. Auto-refresh mekanizması ekleyin

❌ Yapılmaması Gerekenler:

  1. Supabase Flutter paketini kullanmayın
  2. Token'ları plain text olarak saklamayın
  3. SSL sertifikasız production'a çıkmayın
  4. Weak JWT secret kullanmayın

Son Güncelleme: 18 Aralık 2025 | Versiyon: 1.0.0

← Dashboard'a Dön