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

# BuildingBlocks.Jwt

> Çok-şemalı custom JWT — Backoffice (Bearer) + OTPChallenge token'ları.

`BuildingBlocks.Jwt`, Keycloak token'larının dışında uygulamanın kendi ürettiği iki ayrı JWT şemasını yönetir: uzun ömürlü **Backoffice** oturum token'ı ve kısa ömürlü **OTPChallenge** token'ı. Tek `AddJwt(...)` çağrısı iki `JwtBearer` şeması kurar; `JwtTokenValidator` token doğrulama/claim okuma sağlar.

## Token sarmalayıcılar

| Tip               | Üyeler                                                                         | Amaç                        |
| ----------------- | ------------------------------------------------------------------------------ | --------------------------- |
| `JwtAccessToken`  | `string AccessToken`, `DateTime ExpiresAt`, `long ExpiresInSeconds` (computed) | Access token + son kullanma |
| `JwtRefreshToken` | benzer yapı                                                                    | Refresh token taşıyıcısı    |

## `JwtTokenValidator`

Simetrik (`SymmetricSecurityKey`, HMAC) veya OIDC (`OpenIdConnectConfiguration`) anahtarla token doğrular.

| Metot             | İmza                                                                                                                                                                 | Amaç                            |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
| ctor              | `JwtTokenValidator(string secretKey, bool validateLifetime = true, string? issuer = null, string? audience = null, OpenIdConnectConfiguration? openIdConfig = null)` | Doğrulayıcıyı yapılandırır      |
| `ValidateToken`   | `bool ValidateToken(string jwt)`                                                                                                                                     | İmza + ömür doğrular            |
| `GetClaim`        | `string? GetClaim(string jwt, string claimType)`                                                                                                                     | Tek claim okur                  |
| `GetClaims`       | `IEnumerable<Claim> GetClaims(string jwt)`                                                                                                                           | Tüm claim'leri okur             |
| `GetPayload`      | `JwtPayload? GetPayload(string jwt)`                                                                                                                                 | Payload'ı parse eder            |
| `GetPayloadAs<T>` | `T? GetPayloadAs<T>(string jwt) where T : class`                                                                                                                     | Payload'ı tipe deserialize eder |

<Note>
  `issuer`/`audience` parametreleri `;` ile ayrılmış çoklu değer alabilir — bu durumda `ValidIssuers`/`ValidAudiences` listesi olarak değerlendirilir. `ClockSkew` 60 saniyedir.
</Note>

## Yapılandırma — `JwtOptions`

`Jwt` bölümüne bind edilir. İki alt bölüm, ikisi de `JwtBase`'den türeyen tiplerde:

```csharp theme={null}
public class JwtOptions
{
    public BackofficeOptions Backoffice { get; set; }      // : JwtBase
    public OTPChallengeOptions OTPChallenge { get; set; }  // : JwtBase
}
```

### `JwtBase`

| Üye             | Tip      | Açıklama               |
| --------------- | -------- | ---------------------- |
| `Secret`        | `string` | HMAC imzalama anahtarı |
| `ValidAudience` | `string` | Beklenen audience      |
| `ValidIssuer`   | `string` | Beklenen issuer        |
| `Expires`       | `double` | Token ömrü (dakika)    |
| `ClockSkew`     | `int`    | Ek tolerans (saniye)   |

### `AuthenticationSchemeTypes`

| Sabit                              | Değer            | Kullanım                                        |
| ---------------------------------- | ---------------- | ----------------------------------------------- |
| `BackofficeAuthenticationScheme`   | `"Bearer"`       | Uzun ömürlü backoffice oturumu                  |
| `OTPChallengeAuthenticationScheme` | `"OTPChallenge"` | OTP doğrulama state'i taşıyan kısa ömürlü token |

## DI kaydı — `AddJwt`

```csharp theme={null}
public static IServiceCollection AddJwt(this IServiceCollection services, IConfiguration configuration)
{
    services.Configure<JwtOptions>(o => configuration.GetSection("Jwt").Bind(o));
    services.Configure<RefreshTokenOptions>(o => configuration.GetSection("RefreshToken:Backoffice").Bind(o));

    // İki şema için named JwtBearerOptions yapılandırması
    services.ConfigureOptions<ConfigureBackofficeJwtOptions>();
    services.ConfigureOptions<ConfigureOTPChallengeJwtOptions>();
    services.AddHttpContextAccessor();

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultScheme             = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(AuthenticationSchemeTypes.BackofficeAuthenticationScheme, _ => { })
    .AddJwtBearer(AuthenticationSchemeTypes.OTPChallengeAuthenticationScheme, _ => { });

    return services;
}
```

```json theme={null}
{
  "Jwt": {
    "Backoffice": {
      "Secret": "<min-32-char>",
      "ValidAudience": "diyanet-api",
      "ValidIssuer": "diyanet",
      "Expires": 60,
      "ClockSkew": 60
    },
    "OTPChallenge": {
      "Secret": "<min-64-char>",
      "ValidAudience": "diyanet-api",
      "ValidIssuer": "diyanet",
      "Expires": 5,
      "ClockSkew": 30
    }
  }
}
```

<Note>
  Secret'lar `.env` üzerinden gelir: `JWT_BACKOFFICE_SECRET` (min 32 karakter), `JWT_OTP_SECRET` (min 64 karakter). OTPChallenge token'ları kasten kısa ömürlüdür (`Expires: 5`) — yalnızca OTP doğrulama akışı süresince geçerlidir.
</Note>

## Kullanım

```csharp theme={null}
// Token doğrulama
var validator = new JwtTokenValidator(secret, validateLifetime: true, issuer: "diyanet", audience: "diyanet-api");
if (!validator.ValidateToken(token)) return Unauthorized();
var sub = validator.GetClaim(token, "sub");

// Endpoint koruma — Backoffice
[Authorize(AuthenticationSchemes = AuthenticationSchemeTypes.BackofficeAuthenticationScheme)]
[HttpGet("api/admin/reports")]
public async Task<IActionResult> GetReports()
    => Ok(await _mediator.Send(new GetReportsQuery()));

// Endpoint koruma — OTPChallenge (sadece OTP doğrulama adımı)
[Authorize(AuthenticationSchemes = AuthenticationSchemeTypes.OTPChallengeAuthenticationScheme)]
[HttpPost("api/admin/auth/verify-otp")]
public async Task<IActionResult> VerifyOtp([FromBody] VerifyOtpRequest req)
    => Ok(await _mediator.Send(new VerifyOtpCommand(req.Code)));
```

## İlgili

<CardGroup cols={2}>
  <Card title="OTP" icon="shield-halved" href="/building-blocks/otp">
    OTPChallenge akışını besleyen kod üretimi/doğrulaması.
  </Card>

  <Card title="Keycloak" icon="key" href="/building-blocks/keycloak">
    SSO realm token'ları (custom JWT'den ayrı şemalar).
  </Card>

  <Card title="Authentication" icon="fingerprint" href="/security/authentication">
    Şema seçimi ve oturum yönetimi genel bakışı.
  </Card>

  <Card title="Staff login" icon="user-lock" href="/playbooks/staff-login">
    Backoffice + OTP login akışı baştan sona.
  </Card>
</CardGroup>
