> ## Documentation Index
> Fetch the complete documentation index at: https://docs.diyanet.pro/llms.txt
> Use this file to discover all available pages before exploring further.

# Client Yapılandırması

> Public PKCE client ayarları ve dev için adım adım manuel kurulum rehberi

Bu sayfa hem client ayarlarının ne anlama geldiğini hem de Keycloak'ı **elle** kurmak için
adım adım rehberi içerir. Dev'de bu işi normalde [otomatik provisioning](/keycloak/provisioning)
yapar; manuel kurulum, provisioning kapalıyken veya harici bir Keycloak'ta lazım olur.

## Client ayarları (her iki SPA)

Her iki SPA da public (PKCE) client'tır:

| Alan                   | `diyanet-website`                    | `diyanet-admin`                      |
| ---------------------- | ------------------------------------ | ------------------------------------ |
| Client type            | OpenID Connect                       | OpenID Connect                       |
| Client authentication  | **OFF** (public)                     | **OFF** (public)                     |
| Standard flow          | ✅                                    | ✅                                    |
| Direct access grants   | ☐                                    | ☐                                    |
| PKCE method            | `S256`                               | `S256`                               |
| Access token lifespan  | 2 saat                               | 5 dakika                             |
| Refresh token rotation | açık                                 | açık                                 |
| Redirect URI           | `http://localhost:3000/*` (+swagger) | `http://localhost:3001/*` (+swagger) |
| Web origins            | `http://localhost:3000`, `:5005`     | `http://localhost:3001`, `:5005`     |

<Note>
  Client authentication **kapalıdır** (public client). Secret yoktur — tarayıcıda çalışan bir SPA
  secret saklayamaz. Güvenlik PKCE (`code_challenge_method=S256`) ile sağlanır.
</Note>

## Manuel kurulum (dev)

Aşağıdaki adımlar bir realm + client için verilmiştir; **iki realm** için tekrarlanır
(`diyanet-vatandas-dev-realm` → `diyanet-website`, `diyanet-yonetim-dev-realm` → `diyanet-admin`).

<Steps>
  <Step title="Realm oluştur">
    `http://localhost:8080` → Administration Console → giriş (`admin` / `.env` → `KEYCLOAK_ADMIN_PASSWORD`).
    Sol üst `master` menüsü → **Create Realm** → Realm name: `diyanet-yonetim-dev-realm` → **Create**.
  </Step>

  <Step title="Client oluştur">
    **Clients → Create client**

    | Alan        | Değer            |
    | ----------- | ---------------- |
    | Client type | `OpenID Connect` |
    | Client ID   | `diyanet-admin`  |

    **Next → Capability config:**

    | Alan                   | Değer            |
    | ---------------------- | ---------------- |
    | Client authentication  | **OFF** (public) |
    | Standard flow          | ✅                |
    | Direct access grants   | ☐                |
    | Service accounts roles | ☐                |

    **Next → Login settings:**

    | Alan                | Değer                                                |
    | ------------------- | ---------------------------------------------------- |
    | Valid redirect URIs | `http://localhost:3001/*`                            |
    | *(2.)*              | `http://localhost:5005/swagger/oauth2-redirect.html` |
    | Web origins         | `http://localhost:3001`, `http://localhost:5005`     |

    **Save**
  </Step>

  <Step title="PKCE'yi zorunlu kıl">
    **Clients → diyanet-admin → Advanced sekmesi → Advanced Settings →
    Proof Key for Code Exchange Code Challenge Method = `S256`** → **Save**.
  </Step>

  <Step title="Token ömrünü ayarla">
    **Realm settings → Tokens → Access Token Lifespan** → personel realm'ı için `5 minutes`,
    vatandaş realm'ı için `2 hours`. (İstenirse client override edilebilir.)
  </Step>

  <Step title="Protocol mapper'ları ekle">
    **Clients → diyanet-admin → Client scopes → `diyanet-admin-dedicated` → Add mapper → By configuration → User Attribute.**

    İlk mapper — `permissions` (multivalued):

    | Alan                                     | Değer         |
    | ---------------------------------------- | ------------- |
    | Name / User Attribute / Token Claim Name | `permissions` |
    | Claim JSON Type                          | `String`      |
    | **Multivalued**                          | **ON**        |
    | Add to access token                      | ON            |

    İkinci mapper — `organization_id`:

    | Alan                                     | Değer             |
    | ---------------------------------------- | ----------------- |
    | Name / User Attribute / Token Claim Name | `organization_id` |
    | Claim JSON Type                          | `String`          |
    | Multivalued                              | OFF               |
    | Add to access token                      | ON                |
  </Step>

  <Step title="Realm rollerini oluştur">
    **Realm roles → Create role.** Personel realm'ı için sırayla: `SuperAdmin`, `Admin`, `Staff`,
    `ReadOnly`. Vatandaş realm'ı için: `Citizen`.
  </Step>

  <Step title="Test kullanıcısı oluştur ve rol ata">
    **Users → Create new user** (Username, Email, Email verified ON) → **Credentials → Set password**
    (Temporary: OFF) → **Role mapping → Assign role.** Listede "Filter by realm roles" seçip ilgili
    rolü (örn. `Admin`) ata.
  </Step>

  <Step title="Kullanıcı attribute'larını gir">
    **Users → (kullanıcıyı seç) → Attributes.** `permissions` çok-değerli olduğundan birden çok satır
    eklenebilir:

    | Key               | Value                                  |
    | ----------------- | -------------------------------------- |
    | `permissions`     | `users:read`                           |
    | `permissions`     | `users:write`                          |
    | `organization_id` | `00000000-0000-0000-0000-000000000001` |

    **Save.**
  </Step>

  <Step title="Swagger'dan login test et">
    API'yi başlat → `http://localhost:5005/swagger` → **Authorize.** `KeycloakPersonel` bölümünde
    scope'lar (`openid profile email`) seçili → **Authorize** → Keycloak login → test kullanıcısı
    ile gir. Artık istekler bu token ile gider. (Swagger PKCE kullanır, secret alanı boş bırakılır.)
  </Step>
</Steps>

## curl ile token testi

Public + PKCE client'ta `password` grant kapalıdır (`DirectAccessGrantsEnabled: false`),
bu yüzden token'ı tarayıcı akışıyla almak gerekir. Hızlı doğrulama için OIDC discovery'yi
kontrol edebilirsiniz:

```bash theme={null}
curl -s http://localhost:8080/realms/diyanet-yonetim-dev-realm/.well-known/openid-configuration \
  | jq '{issuer, token_endpoint, jwks_uri}'
```

Aldığınız access token'ı `https://jwt.io` ile açınca `realm_access.roles`, `permissions[]` ve
`organization_id` claim'leri görünmelidir (bkz. [Realm Yapısı](/keycloak/realm-structure)).

<Tip>
  Geçici olarak `Direct access grants` açıp `password` grant ile token almak teşhis için pratiktir,
  ama dev dışında kapalı tutun.
</Tip>

## appsettings karşılığı

Manuel kurulan değerler `appsettings.Development.json` → `Keycloak` ile eşleşmelidir:

```json theme={null}
"Keycloak": {
  "Vatandas": {
    "BaseUrl": "http://localhost:8080",
    "PublicBaseUrl": "http://localhost:8080",
    "Realm": "diyanet-vatandas-dev-realm",
    "ClientId": "diyanet-website",
    "RequireHttpsMetadata": false,
    "ValidateAudience": true,
    "CookieName": "kc_vatandas_token"
  },
  "Personel": {
    "BaseUrl": "http://localhost:8080",
    "PublicBaseUrl": "http://localhost:8080",
    "Realm": "diyanet-yonetim-dev-realm",
    "ClientId": "diyanet-admin",
    "RequireHttpsMetadata": false,
    "ValidateAudience": true,
    "CookieName": "kc_personel_token"
  }
}
```

## İlgili

<CardGroup cols={2}>
  <Card title="Otomatik Provisioning" href="/keycloak/provisioning">
    Bu adımları kod ile yapan yol.
  </Card>

  <Card title="Realm Yapısı" href="/keycloak/realm-structure">
    Roller, mapper'lar, token içeriği.
  </Card>

  <Card title="Ortamlar" href="/keycloak/environments">
    Dev / stage / prod URL stratejisi.
  </Card>

  <Card title="Sorun Giderme" href="/keycloak/troubleshooting">
    Redirect URI / PKCE hataları.
  </Card>
</CardGroup>
