# OAuth uygulaması

> Kullanıcıların kendi hesaplarıyla izin verdiği bir uygulama yazın — istemci kaydı, PKCE'li yetkilendirme, belirteç ve yenileme.

Solk her kurulumda bir **OAuth 2.1 yetkilendirme sunucusu** çalıştırır. Aynı sunucu MCP istemcilerine (Claude) ve REST API'yi kullanıcı adına çağıran uygulamalara belirteç verir. Desteklenen akış **yetki kodu + PKCE (S256)** ve **yenileme belirtecidir**; parola akışı ve istemci kimlik bilgisi akışı yoktur.

| | Adres |
|---|---|
| Keşif | `https://ornek.solk.app/.well-known/oauth-authorization-server` |
| İstemci kaydı | `POST https://ornek.solk.app/oauth/register` |
| Yetkilendirme | `GET https://ornek.solk.app/oauth/authorize` |
| Belirteç | `POST https://ornek.solk.app/oauth/token` |
| İptal | `POST https://ornek.solk.app/oauth/revoke` |

Her kurulumun kendi yetkilendirme sunucusu vardır: kullanıcının kurulum adresini (ör. `ornek.solk.app`) ondan alın ve keşif belgesini o adresten okuyun.

:::steps
### İstemciyi kaydedin

Uygulamanızı bir kez kaydedin ([Dinamik istemci kaydı](/rest-api/oauth/register), RFC 7591). Sunucu tarafında gizli anahtar saklayabilen uygulamalar `client_secret_post` seçer; masaüstü ve mobil uygulamalar `none` (genel istemci) kullanır.

```bash
curl https://ornek.solk.app/oauth/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "Örnek Entegrasyon",
    "redirect_uris": ["https://uygulamaniz.com/oauth/callback"],
    "token_endpoint_auth_method": "none"
  }'
```

```json
{
  "client_id": "crm_Jq8w…",
  "client_id_issued_at": 1790939471,
  "client_name": "Örnek Entegrasyon",
  "redirect_uris": ["https://uygulamaniz.com/oauth/callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"]
}
```

Dönüş adresleri `https://` ya da yerel geri döngü (`http://localhost`, `http://127.0.0.1`, `http://[::1]`) olmalıdır. Yerel geri döngü adreslerinde kapı (port) numarası eşleşmede yok sayılır. İstemci kaydı yerine **CIMD** de kullanılabilir: `client_id` olarak istemci bilgi belgenizin `https://` adresini verin.

### PKCE değerlerini üretin

Her yetkilendirme için rastgele bir `code_verifier` (43–128 karakter) ve onun SHA-256 özetinin base64url hâli olan `code_challenge` üretin:

```python
import secrets, hashlib, base64
verifier = secrets.token_urlsafe(48)
challenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).decode().rstrip("=")
```

### Kullanıcıyı yönlendirin

```text
https://ornek.solk.app/oauth/authorize
  ?response_type=code
  &client_id=crm_Jq8w…
  &redirect_uri=https%3A%2F%2Fuygulamaniz.com%2Foauth%2Fcallback
  &scope=crm.read%20crm.write
  &state=xyz123
  &code_challenge=E9Melhoa2Owv…
  &code_challenge_method=S256
```

Kullanıcı oturum açmamışsa önce giriş ekranı gelir. Onay ekranı uygulamanızın adını, dönüş adresinin alan adını ve istenen kapsamları gösterir. Kullanıcı **İzin ver** derse tarayıcı şuraya döner:

```text
https://uygulamaniz.com/oauth/callback?code=Zx8…&state=xyz123
```

Reddederse `?error=access_denied&state=xyz123`. `state` değerinin sizin gönderdiğinizle aynı olduğunu doğrulayın.

### Kodu belirteçle değiştirin

Kod 5 dakika geçerlidir ve **bir kez** kullanılır. Belirteç ucu form gövdesi bekler:

```bash
curl https://ornek.solk.app/oauth/token \
  -d grant_type=authorization_code \
  -d code=Zx8… \
  -d redirect_uri=https://uygulamaniz.com/oauth/callback \
  -d client_id=crm_Jq8w… \
  -d code_verifier=$VERIFIER
```

```json
{
  "access_token": "mcp_uWrPBo…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "mcpr_Nu5ue…",
  "scope": "crm.read crm.write"
}
```

### API'yi çağırın

```bash
curl https://ornek.solk.app/api/v1/me -H "Authorization: Bearer mcp_uWrPBo…"
```

Erişim belirteci REST API'de ve [MCP](/mcp/overview) ucunda geçerlidir. `crm.write` kapsamı yoksa yazma istekleri `403 insufficient_scope` döner.

### Belirteci yenileyin

Erişim belirteci 1 saat sonra düşer. Yenileme belirteciyle yeni bir çift alın — her yenilemede **yeni** yenileme belirteci gelir ve eskisi geçersiz olur:

```bash
curl https://ornek.solk.app/oauth/token \
  -d grant_type=refresh_token \
  -d refresh_token=mcpr_Nu5ue… \
  -d client_id=crm_Jq8w…
```

Eski yenileme belirteciyle tekrar denemek `400 invalid_grant` döner. Yenileme belirteci 60 gün kullanılmazsa düşer; kullanıcı yeniden izin vermelidir.
:::

## İzinler ve geri alma

- Bir kullanıcı aynı uygulamaya ikinci kez izin verdiğinde mevcut izin güncellenir (kapsam yeni onaydakiyle değişir); uygulama başına tek izin vardır.
- Kullanıcı **Ayarlar → Uygulama bağlantıları**'nda uygulamanızı, son kullanım zamanını ve çağrı sayısını görür; **Erişimi kaldır** o izinden verilmiş tüm belirteçleri anında düşürür.
- Kullanıcı kapatılırsa belirteçleri çalışmaz.
- Uygulamanız belirteci kendisi iptal etmek için [`POST /oauth/revoke`](/rest-api/oauth/revoke) çağırabilir.

## Hatalar

| Durum | Yanıt |
|---|---|
| Kod süresi doldu, kullanıldı, yanlış istemci ya da `redirect_uri` eşleşmiyor | `400 {"error": "invalid_grant"}` |
| PKCE doğrulanamadı | `400 {"error": "invalid_grant", "error_description": "PKCE doğrulanamadı."}` |
| Aynı kod ikinci kez kullanıldı | `400 invalid_grant` **ve** o izinden verilmiş tüm belirteçler iptal edilir |
| Desteklenmeyen akış | `400 {"error": "unsupported_grant_type"}` |
| Çok fazla istek | `429 {"error": "slow_down"}` |