
# Django oturumları

`keenauth.bff.django`, Django 4.2 ve sonrası bir uygulamaya Giriş yap özelliği ekler. Sunucunuz OAuth istemcisidir ve tüm belirteçleri sunucuda tutar. Tarayıcı yalnızca şifreli, HttpOnly bir oturum çerezi alır ve hiçbir zaman erişim, yenileme ya da ID belirteci görmez. Bu, arka uç cephe (BFF) desenidir. PyPI'da henüz yayımlanmamış olan `keenauth-python` paketinin bir parçasıdır.

Bunun yerine bearer belirteçleri alan bir API'yi korumak için [API'nizi koruma](/docs/sdk/protect-api) sayfasına bakın.

## Kurulum

```sh
pip install "keenauth-python[django]"
```

## Başlamadan önce

1. Panelde, ortamınızda bir web uygulaması oluşturun.
2. İstemci kimlik doğrulamasını seçin: `private_key_jwt` (önerilen, `PrivateKeyJwt`) ya da bir istemci gizli anahtarı (`ClientSecretBasic`).
3. `https://app.acme.example/auth/callback` yönlendirme URI'sini ve `https://app.acme.example/` çıkış sonrası yönlendirme URI'sini ekleyin.
4. En az 32 karakterlik bir çerez gizli anahtarı oluşturun, örneğin `openssl rand -base64 32` ile. Bunu depoya değil, gizli anahtar deponuzda saklayın.

## Örneği oluşturma

```python
import os
from keenauth.bff import BffOptions, ClientSecretBasic, KeenAuthBff

bff = KeenAuthBff(BffOptions(
    issuer="https://acme.eu.keenauth.app",  # your environment's issuer, exactly
    client_id="app_01j9zzzzzzzzzzzzzzzzzzzz",
    client_auth=ClientSecretBasic(os.environ["KEENAUTH_CLIENT_SECRET"]),
    app_base_url="https://app.acme.example",
    secret=os.environ["KEENAUTH_COOKIE_SECRET"],
))
```

`app_base_url`, uygulamanızın herkese açık adresidir. SDK yönlendirme URI'sini ve tüm yönlendirmeleri bundan oluşturur; asla isteğin `Host` ya da `X-Forwarded-*` başlıklarından oluşturmaz. Düz `http` yalnızca `localhost` için kabul edilir. Seçenekler `KeenAuthBff` oluşturulduğunda denetlenir, bu yüzden bir yapılandırma hatası uygulamayı başlangıçta durdurur.

## private_key_jwt kullanma

`private_key_jwt` ile uygulamanın paylaşılan bir gizli anahtarı yoktur. `PrivateKeyJwt`'ye özel anahtarınızı verin; SDK, belirteç uç noktasına yapılan her istek için yeni bir istemci onayı (RFC 7523) imzalar:

```python
from keenauth.bff import PrivateKeyJwt

client_auth = PrivateKeyJwt(key=os.environ["KEENAUTH_PRIVATE_KEY"])  # unencrypted PEM
```

- Desteklenen anahtarlar: EC P-256 (`ES256`), EC P-384 (`ES384`), Ed25519 (`EdDSA`) ve en az 2048 bitlik RSA (varsayılan `PS256`; `RS256` için `algorithm="RS256"` geçirin).
- Her onayda `iss` ve `sub` istemci kimliğinize, `aud` ise sağlayıcıya ayarlanır; rastgele bir `jti` ve 60 saniyelik bir ömür vardır. `kid` değeri, genel anahtarın RFC 7638 parmak izidir.
- Genel anahtarı uygulamaya kaydedin. `keenauth.m2m.load_private_key(pem).public_jwk()` bunu bir JWK olarak döndürür.

Kendi anahtar hizmetinizle (KMS veya HSM) imzalamak için bunun yerine bir fonksiyon geçirin: `PrivateKeyJwt(assertion=sign)`. `sign()` her çağrıda yeni bir imzalı onay döndürmelidir.

## Ara katmanı ekleme

```python
# settings.py
KEENAUTH_BFF = "myproject.auth.bff"  # dotted path to the KeenAuthBff instance
MIDDLEWARE = [
    # ...
    "keenauth.bff.django.KeenAuthMiddleware",
]
```

Ara katman aşağıdaki rotaları sunar ve diğer her istekte oturumu okuyarak `request.keenauth` içine yerleştirir.

```python
# views.py
from django.http import HttpResponse
from keenauth.bff.django import require_auth

@require_auth()
def orders(request):
    return HttpResponse(f"Signed in as {request.keenauth.session.user.email}")
```

## Rotalar

| Rota | Ne yapar |
|---|---|
| `GET /auth/login` | Giriş yap işlemini başlatır. İsteğe bağlı sorgu parametreleri: `returnTo` (kullanıcının varacağı yer) ve `organization` (bir kuruluşa giriş yapma). |
| `GET /auth/callback` | Giriş yap işlemini tamamlar ve oturum çerezini ayarlar. |
| `GET` veya `POST /auth/logout` | KeenAuth'ta Çıkış yapar ve uygulamanıza döner. |

Giriş yapma, PKCE (S256) ile yetkilendirme kodu akışını kullanır. Ortamınız destekliyorsa istek sunucuya gönderilir (PAR). Geri çağırmada SDK, `state`, `iss` ve ID belirtecini, `nonce` dahil olmak üzere denetler. Başarılı her giriş yeni bir oturum oluşturur; eski oturum atılır.

`returnTo`, uygulamanızın kendi yolu olmalıdır, örneğin `/orders?tab=open`. `//evil.example` ya da tam bir URL gibi başka her değer yok sayılır ve kullanıcı `/` adresine yönlendirilir.

## Korumalı görünümler

Bir görünümü `@require_auth()` ile süsleyin.


Oturum yoksa:

- bir sayfa isteği (`GET` veya `HEAD`), `returnTo` ile birlikte `/auth/login` adresine yönlendirilir;
- `/api/…` yoluna yapılan bir istek ya da başka bir yöntem, bir sorun belgesiyle birlikte `401` alır. Her yolda `401` yanıtı için `api=True` geçirin.

`POST`, `PUT`, `PATCH`, `DELETE` ve diğer güvenli olmayan yöntemlerde tarayıcının isteğin uygulamanızdan geldiğini bildirmesi gerekir: `Sec-Fetch-Site: same-origin` ya da uygulamanızın kaynağına eşit bir `Origin` başlığı. Diğer istekler `403` alır. Bu, `SameSite=Lax` ile birlikte siteler arası istek sahteciliğine karşı koruma sağlar.

## Oturumu kullanma ve API'nizi çağırma

Oturum bağlamında şunlar bulunur:

- `session`: `None` ya da oturum açmış kullanıcı. `session.user`, `subject`, `email`, `name`, `org_id` ve `org_roles` gibi tipli ID belirteci taleplerine sahiptir; tüm talepler `session.user.claims` içindedir. Oturum nesnesi hiçbir zaman belirteç içermez.
- `access_token`: sunucu tarafı çağrılar için geçerli bir erişim belirteci ya da `None`. Bunu tarayıcıya göndermeyin.

Erişim belirtecinin süresi 60 saniye içinde dolacaksa SDK, görünümünüz çalışmadan önce belirteci yeniler. Her yenileme, yenileme belirtecini döndürür ve yanıta yeni oturum çerezini ekler. Sunucu yenileme belirtecini reddederse oturum sona erer. Geçici bir sunucu hatası oturumu değiştirmeden bırakır. Bir süreçteki eşzamanlı istekler tek bir yenilemeyi paylaşır.

## Kuruluş değiştirme

`bff.switch_organization_path("org_01j9…", "/dashboard")`, kullanıcıyı o kuruluşta yeniden giriş yaptıran bir `/auth/login` bağlantısı döndürür. KeenAuth üyeliği denetler. Girişten sonra `session.user.org_id` kuruluşu tutar.

## Çıkış yapma

Bir formdan `/auth/logout` adresine `POST` gönderin. SDK, oturum çerezini (ve bir depo kullanıyorsanız saklanan oturumu) siler, yenileme belirtecini iptal eder ve tarayıcıyı ortamınızın çıkış uç noktasına gönderir; bu uç nokta da tarayıcıyı uygulamanıza geri döndürür. Tarayıcının başka bir siteden geldiğini işaretlediği istek reddedilir. `Sec-Fetch-Site` göndermeyen tarayıcılar yalnızca kendi sayfalarınızdan gelen bir `POST` ile Çıkış yapabilir.

## Oturum depolama

Varsayılan olarak tüm oturum çerezdedir; `secret` değerinden türetilen bir anahtarla AES-256-GCM kullanılarak şifrelenmiş ve doğrulanmıştır. Değiştirilmiş ya da kopyalanmış bir çerez reddedilir. Çerez `__Host-keenauth_session.0` adını taşır ve `Secure`, `HttpOnly`, `SameSite=Lax` ve `Path=/` ile ayarlanır. `http://localhost` üzerinde `__Host-` öneki ve `Secure` kullanılmaz. Büyük oturumlar en fazla üç çereze bölünür.

Belirteçleri sunucuda tutmak için `get(id)`, `set(id, session, ttl_seconds)` ve `delete(id)` yöntemlerine sahip bir nesneyi `store=` ile geçirin; örneğin Redis destekli bir depo. Bu durumda çerez yalnızca şifrelenmiş rastgele bir oturum kimliği taşır. Her giriş yeni bir kimlik oluşturur ve önceki kaydı siler. Depo belirteçleri tuttuğu için erişimini kısıtlayın. `MemorySessionStore` yalnızca geliştirme ve testler içindir.

Bir oturum en fazla 7 gün sürer (`session_max_age`); yenileme bu süreyi uzatmaz. Gizli anahtarı değiştirmek için bir liste geçirin: `secret=[new_secret, old_secret]`. Eski anahtarı `session_max_age` süresinden sonra kaldırın.

## Bugünkü sınırlar

- DPoP ile bağlanmış belirteçler ve arka kanal çıkışı henüz ele alınmıyor.
- Yenilemeler yalnızca tek bir sunucu sürecinde paylaşılır. Birden fazla süreçte, `refresh_reuse_interval_s` uygulama ayarı (varsayılan 5 saniye), paralel bir yenilemenin başarılı olmasına izin verir; bu değeri `0` yaparsanız ikinci yenileme oturumu sonlandırır.
