OAuth2 ile FastAPI’de Güvenli Yetkilendirme

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, 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.

Leave A Comment

Your email address will not be published. Required fields are marked *