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

> İstemci IP çözümleme, cihaz tespiti ve risk skoru tabanlı güven değerlendirmesi.

`BuildingBlocks.DeviceDetector`, gelen HTTP isteğinden **IP**, **cihaz** ve **güven kararı** bilgisini üretir. Login gibi hassas akışlarda risk skoru hesaplamak, oturum kaydına cihaz parmak izi yazmak ve şüpheli istekleri ek doğrulamaya yönlendirmek için kullanılır. Tek giriş noktası `IClientSecurityContext` fasadıdır.

## Arayüzler

| Arayüz                   | İmza                                                                           | İmplementasyon                      |
| ------------------------ | ------------------------------------------------------------------------------ | ----------------------------------- |
| `IClientSecurityContext` | `IpDto GetIp()` · `DeviceDto GetDevice()` · `TrustDecisionDto EvaluateTrust()` | `HttpClientSecurityContext` (fasad) |
| `IClientIpResolver`      | gerçek IP'yi çözer (X-Forwarded-For, CF-Connecting-IP)                         | `ClientIpResolver`                  |
| `IDeviceDetector`        | User-Agent'tan cihaz/tarayıcı/OS çıkarır                                       | `DefaultDeviceDetector`             |
| `ITrustEvaluator`        | `TrustDecisionDto Evaluate(IpDto ip, DeviceDto device)`                        | `TrustEvaluator`                    |

### Value object'ler

`IClientSecurityContext` üç immutable DTO döndürür; bunlar domain tarafında `User.StartSession` gibi metotlara taşınarak `UserSession` kaydına yazılır.

| DTO                | Üyeler                                                                                                                                  |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `IpDto`            | `IpAddress`, `IsPrivateNetwork`, `IsProxy`, `IsVpnSuspected`, `IsTorExitNode`, `Source` (`Direct`/`X-Forwarded-For`/`CF-Connecting-IP`) |
| `DeviceDto`        | `ClientType` (`Mobile`/`Desktop`/`Bot`/`Unknown`), `Browser`, `BrowserVersion`, `Os`, `OsVersion`, `Name`, `Brand`, `Model`, `IsBot`    |
| `TrustDecisionDto` | `Level` (`Trusted`/`Challenge`/`Untrusted`), `RiskScore` (int), `Reason`                                                                |

## Güven değerlendirmesi — risk skoru

`TrustEvaluator`, IP ve cihaz sinyallerini toplayarak bir risk puanı çıkarır ve eşiklere göre karar verir:

| Sinyal                    | Puan |
| ------------------------- | ---- |
| `device.IsBot`            | +80  |
| `ClientType == "Bot"`     | +60  |
| `ClientType == "Unknown"` | +20  |
| `ip.IsTorExitNode`        | +70  |
| `ip.IsVpnSuspected`       | +40  |
| `ip.IsProxy`              | +30  |
| `ip.IsPrivateNetwork`     | +15  |
| `ip.Source != "Direct"`   | +10  |

| Toplam risk | Karar                           |
| ----------- | ------------------------------- |
| `< 30`      | `Trusted`                       |
| `30 – 69`   | `Challenge` (ek doğrulama iste) |
| `>= 70`     | `Untrusted` (reddet)            |

## DI kaydı — `AddDeviceDetector`

Tüm servisler **scoped**'tur (HttpContext'e bağlı).

```csharp theme={null}
public static IServiceCollection AddDeviceDetector(this IServiceCollection services, IConfiguration configuration)
{
    services.AddScoped<IDeviceDetector, DefaultDeviceDetector>();
    services.AddScoped<IClientIpResolver, ClientIpResolver>();
    services.AddScoped<ITrustEvaluator, TrustEvaluator>();
    services.AddScoped<IClientSecurityContext, HttpClientSecurityContext>();  // fasad
    return services;
}
```

```csharp theme={null}
// Program.cs — AddJwt'ten sonra
builder.Services.AddDeviceDetector(builder.Configuration);
```

<Note>
  `AddDeviceDetector` `HttpContext`'e erişir; `IHttpContextAccessor`'ın pipeline'da kayıtlı olması gerekir (`AddJwt`/`AddKeycloak` zaten ekler).
</Note>

## Kullanım — login risk skoru

```csharp theme={null}
[HttpPost("api/website/public/auth/login")]
public async Task<IActionResult> Login([FromBody] LoginRequest req, [FromServices] IClientSecurityContext security)
{
    TrustDecisionDto trust = security.EvaluateTrust();
    DeviceDto device = security.GetDevice();
    IpDto ip = security.GetIp();

    if (trust.Level == TrustLevel.Untrusted)
        return StatusCode(403, $"İstek reddedildi: {trust.Reason}");

    if (trust.Level == TrustLevel.Challenge)
    {
        // OTP / reCAPTCHA gibi ek adım iste
        return await RequireAdditionalVerificationAsync(req, trust.RiskScore);
    }

    // Oturum başlat — cihaz/IP bilgisi UserSession'a yazılır
    var command = new LoginCommand(req.Phone, device, ip);
    return Ok(await _mediator.Send(command));
}
```

Domain tarafında bu bilgi aggregate'e taşınır:

```csharp theme={null}
// User aggregate
public void StartSession(DeviceInfo device, ClientIpInfo ip, ...)
{
    var session = UserSession.Create(this.Id, device, ip, ...);
    _sessions.Add(session);
    AddDomainEvent(new UserSessionStartedDomainEvent(Id, session.Id));
}
```

## İlgili

<CardGroup cols={2}>
  <Card title="Kimlik doğrulama" icon="fingerprint" href="/security/authentication">
    Oturum başlatma ve token üretimi.
  </Card>

  <Card title="Bot koruması" icon="robot" href="/building-blocks/bot-protection">
    Challenge kararında reCAPTCHA v3 ile ek doğrulama.
  </Card>

  <Card title="OTP" icon="shield-halved" href="/building-blocks/otp">
    Yüksek riskte ikinci faktör.
  </Card>

  <Card title="Domain" icon="cube" href="/domain/aggregates">
    UserSession ve StartSession metodu.
  </Card>
</CardGroup>
