first commit
This commit is contained in:
170
app/lib/api-auth.ts
Normal file
170
app/lib/api-auth.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { db } from "@/db";
|
||||
import { apiKeys, user } from "@/db/schema";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { verifyJWT, isValidAPIKeyFormat } from "./jwt";
|
||||
import { UserRole } from "./permissions";
|
||||
|
||||
export interface AuthenticatedRequest extends NextRequest {
|
||||
userId?: string;
|
||||
email?: string;
|
||||
role?: UserRole;
|
||||
}
|
||||
|
||||
export interface AuthResult {
|
||||
authenticated: boolean;
|
||||
userId?: string;
|
||||
email?: string;
|
||||
role?: UserRole;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* API isteklerini doğrula (JWT token veya API key ile)
|
||||
*
|
||||
* Kullanım:
|
||||
* const authResult = await authenticateAPIRequest(request);
|
||||
* if (!authResult.authenticated) {
|
||||
* return NextResponse.json({ error: authResult.error }, { status: 401 });
|
||||
* }
|
||||
* const userId = authResult.userId;
|
||||
*/
|
||||
export async function authenticateAPIRequest(request: NextRequest): Promise<AuthResult> {
|
||||
const authHeader = request.headers.get("authorization");
|
||||
|
||||
if (!authHeader) {
|
||||
return {
|
||||
authenticated: false,
|
||||
error: "Authorization header eksik. Bearer token veya API key gerekli.",
|
||||
};
|
||||
}
|
||||
|
||||
// Bearer token kontrolü
|
||||
if (authHeader.startsWith("Bearer ")) {
|
||||
const token = authHeader.substring(7);
|
||||
|
||||
// JWT token mu yoksa API key mi?
|
||||
if (isValidAPIKeyFormat(token)) {
|
||||
// API Key doğrulama
|
||||
return await validateAPIKey(token);
|
||||
} else {
|
||||
// JWT token doğrulama
|
||||
return await validateJWTToken(token);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
authenticated: false,
|
||||
error: "Geçersiz authorization formatı. 'Bearer <token>' formatında olmalı.",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* JWT token doğrula ve kullanıcı bilgilerini getir
|
||||
*/
|
||||
async function validateJWTToken(token: string): Promise<AuthResult> {
|
||||
const payload = verifyJWT(token);
|
||||
|
||||
if (!payload) {
|
||||
return {
|
||||
authenticated: false,
|
||||
error: "Geçersiz veya süresi dolmuş token.",
|
||||
};
|
||||
}
|
||||
|
||||
// Kullanıcı bilgilerini DB'den al (role için)
|
||||
try {
|
||||
const users = await db
|
||||
.select()
|
||||
.from(user)
|
||||
.where(eq(user.id, payload.userId))
|
||||
.limit(1);
|
||||
|
||||
if (users.length === 0) {
|
||||
return {
|
||||
authenticated: false,
|
||||
error: "Kullanıcı bulunamadı.",
|
||||
};
|
||||
}
|
||||
|
||||
const userData = users[0];
|
||||
|
||||
return {
|
||||
authenticated: true,
|
||||
userId: payload.userId,
|
||||
email: payload.email,
|
||||
role: (userData.role as UserRole) || "user",
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("User lookup error:", error);
|
||||
return {
|
||||
authenticated: false,
|
||||
error: "Kimlik doğrulama sırasında bir hata oluştu.",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API key doğrula (veritabanından kontrol)
|
||||
*/
|
||||
async function validateAPIKey(key: string): Promise<AuthResult> {
|
||||
try {
|
||||
const apiKey = await db
|
||||
.select()
|
||||
.from(apiKeys)
|
||||
.where(and(eq(apiKeys.key, key), eq(apiKeys.isActive, true)))
|
||||
.limit(1);
|
||||
|
||||
if (apiKey.length === 0) {
|
||||
return {
|
||||
authenticated: false,
|
||||
error: "Geçersiz API key.",
|
||||
};
|
||||
}
|
||||
|
||||
const keyData = apiKey[0];
|
||||
|
||||
// Süre kontrolü
|
||||
if (keyData.expiresAt && keyData.expiresAt < new Date()) {
|
||||
return {
|
||||
authenticated: false,
|
||||
error: "API key süresi dolmuş.",
|
||||
};
|
||||
}
|
||||
|
||||
// Kullanıcı bilgilerini al
|
||||
const users = await db
|
||||
.select()
|
||||
.from(user)
|
||||
.where(eq(user.id, keyData.userId))
|
||||
.limit(1);
|
||||
|
||||
if (users.length === 0) {
|
||||
return {
|
||||
authenticated: false,
|
||||
error: "Kullanıcı bulunamadı.",
|
||||
};
|
||||
}
|
||||
|
||||
const userData = users[0];
|
||||
|
||||
// Son kullanım tarihini güncelle (opsiyonel)
|
||||
await db
|
||||
.update(apiKeys)
|
||||
.set({ lastUsedAt: new Date() })
|
||||
.where(eq(apiKeys.id, keyData.id));
|
||||
|
||||
return {
|
||||
authenticated: true,
|
||||
userId: keyData.userId,
|
||||
email: userData.email,
|
||||
role: (userData.role as UserRole) || "user",
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("API key doğrulama hatası:", error);
|
||||
return {
|
||||
authenticated: false,
|
||||
error: "Kimlik doğrulama sırasında bir hata oluştu.",
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user