
# Flask oturumları

`keenauth.bff.flask`, Flask 2.3 veya daha yeni bir uygulamaya Giriş yap özelliği ekler. Sunucunuz OAuth istemcisidir ve tüm belirteçleri sunucuda saklar. Tarayıcı yalnızca şifrelenmiş, HttpOnly bir oturum çerezi alır ve hiçbir zaman erişim, yenileme veya ID belirteci görmez. Bu, backend-for-frontend (BFF) desenidir. `keenauth-python` paketinin bir parçasıdır ve henüz PyPI'da yayımlanmamıştır.

Bunun yerine taşıyıcı (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[flask]"
```

## Başlamadan önce

1. Kontrol panelinde, ortamınızda bir web uygulaması oluşturun.
2. İstemci kimlik doğrulamasını seçin: `private_key_jwt` (önerilen, `PrivateKeyJwt`) veya bir istemci gizli anahtarı (`ClientSecretBasic`).
3. Yönlendirme URI'si olarak `https://app.acme.example/auth/callback` adresini, çıkış sonrası yönlendirme URI'si olarak `https://app.acme.example/` adresini ekleyin.
4. En az 32 karakterlik bir çerez gizli anahtarı oluşturun, örneğin `openssl rand -base64 32` ile. Bunu depoda 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; isteğin `Host` veya `X-Forwarded-*` başlıklarından asla oluşturmaz. Düz `http` yalnızca `localhost` için kabul edilir. Seçenekler `KeenAuthBff` oluşturulurken denetlenir, dolayısıyla 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` sınıfına ö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 olarak `PS256`; `RS256` için `algorithm="RS256"` geçirin).
- Her onayda `iss` ve `sub` istemci kimliğinize, `aud` ise veren (issuer) adresine ayarlanır; rastgele bir `jti` ve 60 saniyelik bir geçerlilik süresi bulunur. `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 (bir 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.

## Kancaları kaydetme

```python
from flask import Flask, g
from keenauth.bff.flask import init_app, require_auth

app = Flask(__name__)
init_app(app, bff)

@app.get("/orders")
@require_auth(bff)
def orders():
    return f"Signed in as {g.keenauth.session.user.email}"
```

`init_app`, aşağıdaki yolları sunar ve diğer her istekte oturumu okuyarak `g.keenauth` içine yerleştirir. Bu SDK, Flask'ın kendi `session` çerezini kullanmaz.

## Yollar

| Yol | 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ş yap). |
| `GET /auth/callback` | Giriş yap işlemini tamamlar ve oturum çerezini ayarlar. |
| `GET` veya `POST /auth/logout` | KeenAuth'ta Çıkış yap işlemini gerçekleştirir ve uygulamanıza geri döndürür. |

Giriş yap işlemi 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, denetler. Her başarılı girişte yeni bir oturum oluşturulur ve eski oturum atılır.

`returnTo`, `/orders?tab=open` gibi uygulamanıza ait bir yol olmalıdır. `//evil.example` ya da tam bir URL gibi diğer değerler yok sayılır ve kullanıcı `/` sayfasına yönlendirilir.

## Korumalı görünümler

Bir görünümü, yol dekoratörünün altına `@require_auth(bff)` ile süsleyin.


Oturum yoksa:

- bir sayfa isteği (`GET` veya `HEAD`), `returnTo` ile `/auth/login` adresine yönlendirilir;
- `/api/…` yoluna yapılan bir istek veya başka bir yöntem, bir problem belgesiyle `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ı, isteğin uygulamanızdan geldiğini belirtmelidir: `Sec-Fetch-Site: same-origin` veya uygulamanızın kökeniyle eşleşen 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 türlendirilmiş ID belirteci iddialarına sahiptir; tüm iddialar `session.user.claims` içindedir. Oturum nesnesi hiçbir zaman bir 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üresinin dolmasına 60 saniyeden az kaldığında SDK, görünümünüz çalışmadan önce onu yeniler. Her yenileme, yenileme belirtecini döndürür ve yanıtta yeni oturum çerezini ayarlar. Sunucu yenileme belirtecini reddederse oturum sona erer. Geçici bir sunucu hatası oturumu değiştirmez. 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ş yap işlemine sokan 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 siler (bir depo kullanıyorsanız saklanan oturumu da), yenileme belirtecini iptal eder ve tarayıcıyı ortamınızın çıkış uç noktasına yönlendirir; bu uç nokta tarayıcıyı uygulamanıza geri gönderir. Tarayıcının başka bir siteden geldiğini belirttiği istek reddedilir. `Sec-Fetch-Site` göndermeyen tarayıcılar, yalnızca kendi sayfalarınızdan gelen bir `POST` ile Çıkış yap işlemini gerçekleştirebilir.

## Oturum depolama

Varsayılan olarak tüm oturum çerezdedir; `secret` değerinden türetilen bir anahtarla AES-256-GCM kullanılarak şifrelenir ve doğrulanır. Değiştirilmiş ya da kopyalanmış bir çerez reddedilir. Çerez adı `__Host-keenauth_session.0` olup `Secure`, `HttpOnly`, `SameSite=Lax` ve `Path=/` ile ayarlanır. `http://localhost` üzerinde `__Host-` öneki ve `Secure` kaldırılır. 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)` metotlarına sahip bir nesneyle `store=` geçirin; örneğin Redis destekli bir depo. Bu durumda çerez yalnızca şifrelenmiş rastgele bir oturum kimliği tutar. Her Giriş yap işlemi 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'a bağlı belirteçler ve arka kanal çıkışı henüz desteklenmiyor.
- Yenilemeler yalnızca tek bir sunucu süreci içinde paylaşılır. Birden fazla süreçte, `refresh_reuse_interval_s` uygulama ayarı (varsayılan 5 saniye) paralel yenilemenin başarılı olmasına izin verir; değeri `0` yaparsanız ikinci yenileme oturumu sonlandırır.
