---
title: SAIF.Web.API.Clients.35 security and authorization
summary: Authorization requirements, AD resource groups, security enforcement points, and data-level access control.
status: draft
owner: bendy
last_reviewed: 2026-09-15
library: SAIF.Web.API.Clients.35
reference_type: package
---

# SAIF.Web.API.Clients.35 security and authorization

This page documents authorization and identity mechanisms implemented or consumed by `SAIF.Web.API.Clients.35`. This is a **client-side, outbound** HTTP library: it does not enforce authorization itself, and it does not make authorization decisions — it authenticates outbound requests, propagates caller identity, and translates the remote API's authorization outcomes (401/403) into typed exceptions.

## Authorization architecture

Authorization is fully delegated to the remote SAIF Web API this client calls. `JsonHttpClient` supplies an authentication mechanism (NTLM by default, or a caller-supplied `IAuthenticator`) and caller-identity headers on every request, but the decision of whether the caller is authorized for a given resource is made entirely by the server the request is sent to. This library only consumes that decision after the fact, via HTTP status code translation.

The following diagram shows how the client attaches authentication and identity material to an outbound request before it reaches the remote API:

```mermaid
%%{init: {'flowchart': {'nodeSpacing': 1, 'rankSpacing': 20}}}%%
flowchart TD
    Caller[Consuming code] --> Client["JsonHttpClient.GetJsonResponse"]
    Client --> Auth["IAuthenticator (NtlmAuthenticator default, or injected)"]
    Client --> Headers["Identity headers: Client-Name / Application-ID / Client-User<br>(ClientInfo)"]
    Client --> OBO["OnBehalfOfUser header<br>(net4.x only, when SetOnBehalfOfUserHeaders = true)"]
    Auth --> Remote[Remote SAIF Web API]
    Headers --> Remote
    OBO --> Remote
    Remote --> Decision{HTTP status}
```

The following diagram shows how the client translates the remote API's HTTP status code into the appropriate typed result or exception:

```mermaid
%%{init: {'flowchart': {'nodeSpacing': 1, 'rankSpacing': 20}}}%%
flowchart TD
    Decision{HTTP status} -->|200-399| Success[Return typed result]
    Decision -->|401/403| Deny["ExceptionHandler.ToKnownError -><br>UnauthorizedAccessException (BR-20)"]
    Decision -->|404/400/other| OtherErr["Other typed SAIFException subtype (BR-20)"]
```

## AD resource catalog

**None detected.** No AD resource/group names, roles, claims, ACLs, or policy resources are implemented, referenced, or hard-coded anywhere in this library's compiled scope. This library issues outbound HTTP requests and does not define or consume any AD-backed authorization resource.

| Resource name | Purpose | Enforcement point | Source |
| --- | --- | --- | --- |
| *(none)* | Not applicable — no AD resource catalog exists in this library | N/A | `src/SAIF.Web.API.Clients/JsonHttpClient.cs`, `src/SAIF.Web.API.Clients.35/SAIF.Web.API.Clients.35.csproj` |

## Authorization enforcement points

There is **no local authorization-decision enforcement point** in this library — the remote SAIF Web API is the sole decision point. The rows below are the boundary points where this client attaches identity/authentication material to outbound requests, and where it consumes the remote decision after the fact.

| Enforcement point | Behavior / boundary | Source |
| --- | --- | --- |
| Outbound authenticator attachment + identity-header injection | `JsonHttpClient.GetJsonResponse` sets `client.Authenticator = _authenticator` (NTLM by default, or the caller-supplied `IAuthenticator`) and adds the `Client-Name`, `Application-ID`, `Client-User` headers from `ClientInfo` to every outbound request ([BR-01](business-rules.md#br-01-identity-headers-on-every-request), [BR-02](business-rules.md#br-02-default-ntlm-authentication)). | `src/SAIF.Web.API.Clients/JsonHttpClient.cs` |
| Conditional on-behalf-of forwarding | `JsonHttpClient.GetJsonResponse` adds an `OnBehalfOfUser` header when `SetOnBehalfOfUserHeaders` is true ([BR-04](business-rules.md#br-04-on-behalf-of-header-forwarding)); in this `.35` variant this path has no working implementation, since `HttpContextExtensions.cs` is excluded from compilation and `System.Web` is not referenced (see the net3.5-specific gap below). | `src/SAIF.Web.API.Clients/JsonHttpClient.cs`, `src/SAIF.Web.API.Clients.35/SAIF.Web.API.Clients.35.csproj` |
| 401/403 → typed exception translation | `ExceptionHandler.EnsureSuccessfulResponse` (invoked from `JsonHttpClient.GetJsonResponse` when `EnsureSuccessfulResponse` is true) calls `ExceptionHandler.ToKnownError`, which maps HTTP 401/403 to `SAIF.API.Exceptions.UnauthorizedAccessException` ([BR-20](business-rules.md#br-20-http-status-to-exception-type-mapping)). This is a *consumption* of the remote authorization decision, not a local enforcement decision. | `src/SAIF.Web.API.Clients/ExceptionHandler.cs` |

## Authentication

| Finding | Detail | Source |
| --- | --- | --- |
| Default authentication scheme | NTLM. `_authenticator = authenticator ?? new NtlmAuthenticator()` — a null authenticator silently falls back to NTLM, and two of four constructors hard-code it ([BR-02](business-rules.md#br-02-default-ntlm-authentication)). | `JsonHttpClient.cs` |
| Pluggable authentication | `IAuthenticator` (RestSharp) may be injected, permitting Basic/OAuth/JWT strategies chosen by the caller. | `JsonHttpClient.cs` |
| No credential storage | No username/password/token/connection-string literals, no `ConfigurationManager` credential reads, no certificate handling. | all files |

## Identity propagation

| Finding | Detail | Source |
| --- | --- | --- |
| Caller identity headers | `Client-Name`, `Application-ID`, `Client-User` are sent on **every** request, sourced from `ClientInfo` ([BR-01](business-rules.md#br-01-identity-headers-on-every-request)). These are unauthenticated, caller-supplied values — they identify but do not prove identity.* | `JsonHttpClient.cs`, `ClientInfo.cs` |
| On-behalf-of impersonation | When `SetOnBehalfOfUserHeaders` is true, an `OnBehalfOfUser` header carries the domainless current-user name via `HttpContext.Current.DomainlessUser()`. Whether the receiving API actually validates the request against that user rather than the service account is server-side behavior outside this client's source and is not demonstrated here.* | `JsonHttpClient.cs`, `Extensions/HttpContextExtensions.cs` |

### net3.5-specific gap: on-behalf-of path has no implementation in this variant

`Extensions/HttpContextExtensions.cs` — which supplies `DomainlessUser()`, the source of the `OnBehalfOfUser` header value — is **not compiled into `SAIF.Web.API.Clients.35`**, and this project does not reference `System.Web`. Consequently, setting `SetOnBehalfOfUserHeaders = true` on this net3.5 build variant has no working implementation behind it; the feature exists only in the actively-built `SAIF.Web.API.Clients` (net4.x) project that shares the rest of this linked source.* This mirrors the same dormant/retired status documented in [Overview](overview.md) and [BR-04](business-rules.md#br-04-on-behalf-of-header-forwarding).

| Finding | Detail | Source |
| --- | --- | --- |
| Compilation gap | `Extensions/HttpContextExtensions.cs` is excluded from this project's compiled sources; `System.Web` is not referenced. | `SAIF.Web.API.Clients.35.csproj` |

## Authorization

- No role checks, claims inspection, `PrincipalPermission`, `[Authorize]`, ACL, or policy evaluation exists in this library. Authorization is delegated entirely to the remote API.
- The library **consumes** authorization outcomes: HTTP 401 and 403 are translated into `SAIF.API.Exceptions.UnauthorizedAccessException` ([BR-20](business-rules.md#br-20-http-status-to-exception-type-mapping)).
- 401 (`Unauthorized`) is included in the default `RetryOnStatusCodes` set ([BR-05](business-rules.md#br-05-transient-failure-retry)), so an authentication failure is retried up to 3 times (with a 1-second default delay) before the exception is raised.

## Data-level authorization

**None detected.** This library performs no database access and no entity-ownership or data-scope validation of any kind; all data-level authorization, if any, is the responsibility of the remote API.

## Segregation of duties

**None detected.** No SOD types or mutually-exclusive-privilege rules exist anywhere in this library.

## Transport security

- No TLS/certificate configuration, no `ServicePointManager` settings, and no scheme validation. Whether traffic is encrypted depends entirely on the `serviceBaseUri` supplied by the caller.
- No `ServerCertificateValidationCallback` override was found — certificate validation is not weakened by this library.

## Sensitive-data handling

- Error responses are surfaced verbatim to callers: `GetContent`/`ToKnownError` fall back to the raw response body content. If the remote API returns sensitive detail in an error body, this library propagates it into the exception message without redaction.*
- No logging framework is used; nothing is written to disk or a log sink by this library.

## Security interfaces and contracts

| Interface / Class | Role | Consumers | Source |
| --- | --- | --- | --- |
| `IAuthenticator` (RestSharp) | Pluggable outbound authentication strategy; defaults to `NtlmAuthenticator` | `JsonHttpClient` | `JsonHttpClient.cs` |

## Notes
- Mark inferred statements with `*` and unknown statements with `**`. Do not use bold inline confidence labels.
- This is an infrastructure HTTP client library, not an AD-resource-gated application; the `## AD resource catalog` and `## Authorization enforcement points` sections above are populated with explicit "none detected" / boundary-only content rather than omitted, since no attribute-based or programmatic `IsAuthorized`/`IsInRole` checks exist in this library's own compiled scope.

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [API reference](api/index.md)
- [SAIF.Web.API.Core overview](../saif-web-api-core/overview.md)

## Sources
- src/SAIF.Web.API.Clients/JsonHttpClient.cs
- src/SAIF.Web.API.Clients/ClientInfo.cs
- src/SAIF.Web.API.Clients/Extensions/HttpContextExtensions.cs (excluded from this project)
- src/SAIF.Web.API.Clients.35/SAIF.Web.API.Clients.35.csproj
