OAuth2 ile FastAPI’de Güvenli Yetkilendirme İşlemleri: Adım Adım Kılavuz
Günümüzde web uygulamalarının güvenliği her zamankinden daha önemli. Kullanıcı verilerini korumak ve yetkisiz erişimi engellemek için sağlam bir yetkilendirme mekanizması şarttır. FastAPI, modern ve hızlı bir web çerçevesi olarak, OAuth2 gibi endüstri standardı yetkilendirme protokollerini kolayca entegre etmenizi sağlar. Bu makalede, OAuth2’nin temellerini, FastAPI ile nasıl kullanıldığını ve adım adım bir yetkilendirme uygulamasının nasıl geliştirileceğini ayrıntılı olarak inceleyeceğiz.
İçindekiler
- OAuth2 Nedir?
- OAuth2 Akışları
- FastAPI ile OAuth2 Entegrasyonu
- Bağımlılıkların Kurulumu
- Güvenlik Bağımlılıklarının Tanımlanması
- Token Endpoint’inin Oluşturulması
- Kaynakların Korunması
- Kullanıcı Kayıt ve Giriş İşlemleri
- Örnek Kod ve Uygulama
- Ek Güvenlik Önlemleri
- Sonuç
OAuth2 Nedir?
OAuth2, uygulamaların kullanıcı adları ve parolalarını paylaşmadan, bir sunucudaki kaynaklara (örneğin, profil bilgileri, fotoğraflar) erişmesini sağlayan bir yetkilendirme standardıdır. Kullanıcının kimlik bilgilerini doğrudan uygulamaya vermeden, kullanıcı adına işlem yapma yetkisi verir. OAuth2, farklı akışlar aracılığıyla çeşitli senaryoları destekler ve modern web ve mobil uygulamalar için vazgeçilmezdir.
OAuth2 Akışları
OAuth2, farklı kullanım durumlarına uygun çeşitli akışlar sunar. En yaygın akışlar şunlardır:
- Authorization Code Grant: En güvenli akışlardan biridir. Kullanıcı önce yetkilendirme sunucusuna yönlendirilir, izin verir ve ardından uygulama, yetkilendirme kodu ile bir erişim belirteci (access token) talep eder.
- Implicit Grant: Tarayıcı tabanlı uygulamalar için kullanılır. Erişim belirteci doğrudan yetkilendirme sunucusundan alınır. Güvenlik açıkları nedeniyle pek önerilmez.
- Password Grant: Kullanıcı adı ve şifre doğrudan uygulamaya verilir ve uygulama erişim belirteci talep eder. Güvenliği riskli olduğu için sadece güvenilir uygulamalar için uygundur.
- Client Credentials Grant: Uygulamaların kendi adına işlem yapması gerektiğinde kullanılır. Kullanıcı kimliği gerektirmez.
FastAPI ile OAuth2 Entegrasyonu
FastAPI, OAuth2 entegrasyonunu kolaylaştıran güçlü araçlar sunar. FastAPI’nin bağımlılık enjeksiyonu (dependency injection) sistemi, güvenlik gereksinimlerini kolayca yönetmenizi sağlar. FastAPI’nin sunduğu fastapi.security
modülü, OAuth2 akışlarını uygulamanıza yardımcı olacak araçlar içerir.
Bağımlılıkların Kurulumu
FastAPI ile OAuth2 kullanabilmek için gerekli bağımlılıkları yüklemelisiniz. Terminalde aşağıdaki komutu çalıştırın:
pip install fastapi[all] passlib[bcrypt] python-jose[cryptography]
Bu komut, FastAPI, şifreleme için Passlib ve JSON Web Token (JWT) işlemleri için Python-jose kütüphanelerini yükleyecektir.
Güvenlik Bağımlılıklarının Tanımlanması
Öncelikle, kullanıcı kimlik bilgilerini doğrulayacak ve erişim belirteci oluşturacak fonksiyonları tanımlamamız gerekiyor. Bu fonksiyonlar, FastAPI bağımlılıkları olarak kullanılacak ve API uç noktalarına güvenlik katmanı ekleyecektir.
Örnek bir güvenlik bağımlılığı:
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta
from typing import Optional
# Güvenlik ayarları
SECRET_KEY = "YOUR_SECRET_KEY"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# Şifreleme ayarları
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# OAuth2 şeması
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
# Kullanıcı doğrulama fonksiyonu (örnek)
def authenticate_user(db, username, password):
user = get_user(db, username)
if not user:
return False
if not verify_password(password, user.hashed_password):
return False
return user
# Token oluşturma fonksiyonu
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# Şifre hashleme fonksiyonu
def get_password_hash(password):
return pwd_context.hash(password)
# Şifre doğrulama fonksiyonu
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
# Mevcut kullanıcıyı alma (örnek)
def get_user(db, username: str):
# Veritabanından kullanıcıyı çekme işlemini burada yapın
# Örnek: db.query(User).filter(User.username == username).first()
# Bu kısım veritabanı yapınıza göre değişir.
return None # Örnek olarak None döndürüyoruz.
# Token doğrulama fonksiyonu
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
token_data = {"username": username}
except JWTError:
raise credentials_exception
user = get_user(None, username) # Veritabanı bağlantısı geçirilmedi (None)
if user is None:
raise credentials_exception
return user
Token Endpoint’inin Oluşturulması
Token endpoint’i, kullanıcıların kimlik bilgilerini göndererek erişim belirteci alabilecekleri uç noktadır. FastAPI’de bu endpoint’i aşağıdaki gibi tanımlayabilirsiniz:
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
# ... (Yukarıdaki güvenlik bağımlılıkları burada olmalı) ...
app = FastAPI()
@app.post("/token")
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
user = authenticate_user(db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.username},
expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
Kaynakların Korunması
API’nizdeki kaynakları korumak için, Depends
bağımlılık enjeksiyonunu kullanarak get_current_user
fonksiyonunu API uç noktalarına ekleyebilirsiniz. Bu, sadece geçerli bir erişim belirteci olan kullanıcıların bu uç noktalara erişebilmesini sağlar.
from fastapi import Depends
# ... (Yukarıdaki güvenlik bağımlılıkları ve token endpoint'i burada olmalı) ...
@app.get("/items/")
async def read_items(current_user = Depends(get_current_user)):
return [{"item_id": "Foo", "owner": current_user.username}]
Kullanıcı Kayıt ve Giriş İşlemleri
OAuth2’nin temel amacı, mevcut kimlik doğrulama sistemlerini kullanarak yetkilendirme sağlamaktır. Bu nedenle, kullanıcı kayıt ve giriş işlemleri genellikle OAuth2’nin dışında ele alınır. Ancak, basit bir örnek olarak, kullanıcı kayıt ve giriş işlemlerini FastAPI içinde nasıl gerçekleştirebileceğinizi gösterelim:
from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel
from sqlalchemy.orm import Session
# ... (Yukarıdaki güvenlik bağımlılıkları burada olmalı) ...
class UserCreate(BaseModel):
username: str
password: str
@app.post("/users/", status_code=status.HTTP_201_CREATED)
async def create_user(user: UserCreate, db: Session = Depends(get_db)):
db_user = get_user(db, user.username)
if db_user:
raise HTTPException(status_code=400, detail="Username already registered")
hashed_password = get_password_hash(user.password)
db_user = User(username=user.username, hashed_password=hashed_password)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
Örnek Kod ve Uygulama
Yukarıdaki kod parçacıklarını bir araya getirerek basit bir OAuth2 ile korunan FastAPI uygulaması oluşturabilirsiniz. Tam bir örnek uygulama genellikle bir veritabanı entegrasyonu ve daha kapsamlı hata yönetimi içerir. Ancak, bu kılavuz size OAuth2’nin FastAPI ile nasıl entegre edileceğine dair temel bir anlayış sağlamıştır.
Ek Güvenlik Önlemleri
- SECRET_KEY’i Güvenli Saklayın: SECRET_KEY’i asla doğrudan kodda saklamayın. Ortam değişkenleri veya güvenli bir konfigürasyon yönetimi aracı kullanın.
- HTTPS Kullanın: Tüm iletişimlerin şifrelenmesi için HTTPS kullanın.
- Token Sürelerini Kısa Tutun: Erişim belirteçlerinin (access token) geçerlilik sürelerini mümkün olduğunca kısa tutun ve yenileme belirteçleri (refresh token) kullanın.
- Giriş Denemelerini Sınırlayın: Kaba kuvvet saldırılarını önlemek için başarısız giriş denemelerini sınırlayın.
- Bağımlılıkları Güncel Tutun: Güvenlik açıklarını gidermek için FastAPI ve diğer bağımlılıklarınızı düzenli olarak güncelleyin.
Sonuç
Bu makalede, OAuth2’nin ne olduğunu, farklı akışlarını, FastAPI ile nasıl entegre edilebileceğini ve temel güvenlik önlemlerini ele aldık. FastAPI’nin sunduğu esneklik ve kolaylık sayesinde, OAuth2 gibi modern yetkilendirme protokollerini uygulamalarınıza kolayca entegre edebilirsiniz. Unutmayın, güvenlik her zaman öncelikli olmalı ve uygulamalarınızın güvenliğini sağlamak için sürekli olarak en iyi uygulamaları takip etmelisiniz.