---
title: SAIF.NetCore.ServiceExtensions security and authorization
summary: Authorization architecture, enforcement points, and security observations for this composition-root library.
status: draft
owner: Framework.NCore maintainers
last_reviewed: 2026-10-02
library: SAIF.NetCore.ServiceExtensions
reference_type: package
---

# SAIF.NetCore.ServiceExtensions security and authorization

This library is a **security composition root**, not an authorization engine. It defines no authorization mechanism of its own. Through its `IServiceCollection` extensions and abstract Startup base classes, it wires the authentication schemes, the REST SecurityApi authorization policy provider/handler, and the identity accessors — all implemented in `SAIF.NetCore.AuthService` and `SAIF.NetCore.OIDC` — into consuming applications. It also defines two cookie-presence "gate" middlewares of its own: one wired (`AspNetSessionIdMiddleware`) and one not (`LegacyBolAuthMiddleware`).

## Authorization architecture

Role decisions run through the REST SecurityApi client (`ISecurityClient`, from `SAIF.NetCore.AuthService`), not through the WCF SecurityService — no WCF service reference, `SecurityServiceClient`, `securityServiceUrl`/`WCFEndPointAddress` key, or `/WCF/Security` URL exists under this library's source. This library decides **which** authentication stack and **which** authorization components a consuming application gets, based on the chosen Startup base class and the `ASPNETCORE_HOST_LOCATION` environment variable, and it adds two cookie-presence gates of its own.

```mermaid
flowchart TD
    A[Consuming application Startup] --> B{Which base class?}
    B -->|AppStartup, External| C["RegisterOidcServices +<br>RegisterCoreAPIAuthServices-shaped SecurityApi wiring"]
    B -->|AppStartup, Internal/NotDefined| D[RegisterCoreAPIAuthServices]
    B -->|CoreAPIStartup| D
    B -->|EdgeAPIStartup| E["RegisterEdgeAPIAuthServices - JWT only,<br>no SecurityApi policy provider"]
    C --> F[SecurityApiPolicy / SecurityApiHandler]
    D --> F
    F --> G["ISecurityClient.IsAuthorized role check -<br>AuthService REST call"]
    E -.->|SecurityApiAuthorize on Edge throws at runtime, SEC-07| G
```

## AD resource catalog

**No AD group or resource-name literal exists in this library's code.** Every role name reaches the authorization handler from a consumer's `new SecurityApiAuthorize(roles)` attribute, where `roles` is a caller-supplied, comma-separated string argument, resolved through the `SecurityAPI.<roles>` dynamic policy (`SecurityAPIPolicy`, registered by this library). This library never supplies a role itself.

| Resource name | Context | Enforcement point (as wired by this library) | Confidence |
| --- | --- | --- | --- |
| *(none hard-coded)* | Role names are supplied by consumers through `new SecurityApiAuthorize(roles)`, where `roles` is a caller-supplied string. The comma-separated list is OR-evaluated by `SecurityApiHandler`. | `SecurityApiPolicy` + `SecurityApiHandler`, registered by [Register Core API auth services](operations/register-core-api-auth-services.md) and by [App startup configure services](operations/app-startup-configure-services.md)'s External branch | verified |

### Non-resource security identifiers hard-coded in the library

| Identifier | Kind | Used by | Confidence |
| --- | --- | --- | --- |
| `ASP.NET_SessionId` | Request cookie name (legacy ASP.NET session cookie) | `AspNetSessionIdMiddleware` presence check | verified |
| `SAIFAUTH` | Request cookie name (legacy credential cookie issued by `SAIF.NetCore.LegacyAuth`) | `LegacyBolAuthMiddleware` presence check | verified |
| `SAIF.BOL.Auth` | Request cookie name (legacy BOL auth cookie; issuer not in this repository) | `LegacyBolAuthMiddleware` presence check | verified (name); unknown (issuer)** |
| `endpoint` / `LegacySessionProvider` | EnvironmentClient setting (path of the legacy session provider) | Redirect target in both gate middlewares — see [Legacy cookie gate middleware](operations/legacy-cookie-gate-middleware.md) | verified |
| `connectionservicecreds` / `dbconnectionclient` | EnvironmentClient secure setting (DBConnectionAPI client credentials, `user\|password`) | [Register DB connection client](operations/register-db-connection-client.md) | verified (value never reproduced) |
| `ASPNETCORE_HOST_LOCATION` | Process/machine env var selecting the External (OIDC) or internal (dual IIS/JWT) auth stack | `AppStartup.HostLocation` | verified |
| `ASPNETCORE_REDIRECT_SSL` | Machine env var that can disable `UseHttpsRedirection` | `AppStartup.EnforceSslRedirect` | verified |

AD group names `Domain Users`, `Developer_Group`, and `Users` appear only in this library's **integration test** controllers (test-only, not library behavior).

## Authorization enforcement points

This library contains no `[SaifAuthorize]` / `[SecurityApiAuthorize]` / `[Authorize]` decoration on any of its own public types. Its enforcement points fall into three kinds: (A) security service registrations made on behalf of consumers, (B) pipeline placement, and (C) the two cookie-gate middlewares.

### A. Security service registrations

| # | Entry point | Authentication scheme(s) wired | Authorization components wired | Identity services wired | Source |
| --- | --- | --- | --- | --- | --- |
| A1 | [Register Core API auth services](operations/register-core-api-auth-services.md) | `ConfigureJwtBearerOptions` + dual policy scheme `"dual"`: `Authorization` header starting `"Bearer "` → JwtBearer, else IIS/Negotiate (`IISServerDefaults`) | `AddSecurityApiAuthorizeAttribute()` → `IAuthorizationPolicyProvider = SecurityApiPolicy` (Transient), `IAuthorizationHandler = SecurityApiHandler` (Singleton) | `AddIdentityAccessor()` → `ISecurityClient = SecurityClient` (Singleton), `WinIdentityService`, `TokenIdentityService`, `IIdentityServiceAccessor = MultiIdentityServiceAccessor` | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L250–259; `src/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/Extensions/AuthenticationServiceExtensions.cs` L46–53, L68–79, L83–88, L90–98 |
| A2 | [Register Edge API auth services](operations/register-edge-api-auth-services.md) | `ConfigureJwtBearerOptions` + JwtBearer only, no Windows fallback | **None** — no `SecurityApiPolicy`/`SecurityApiHandler` registered (see [SEC-07](#security-observations)) | `AddTokenIdentityService()` → `ISecurityClient` (Singleton), `IIdentityService = TokenIdentityService`, `IIdentityServiceAccessor = IdentityServiceAccessor` | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L99–108; `src/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/Extensions/AuthenticationServiceExtensions.cs` L31–34 |
| A3 | [Register OIDC services](operations/register-oidc-services.md) → [Add web authentication](operations/add-web-authentication.md) | `Cookies` (default authenticate/sign-in) + `OpenIdConnect` (Okta); challenge = `Cookies` by default or `OpenIdConnect` for a login app | Role-claim transformation services (`RoleClaimTransformer`, `IRoleClaimService`, `IClaimTransformCacheService`); `JwtClaimMiddleware`, `RefreshJwtMiddleware` (conditional), `LowerCaseUrlMiddleware`, `ILoginRedirectService`, `IJwtAuthorizationCookieClaimService`, `IDataProtectionCertService` | — | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–169, L177–212 |
| A4 | [Require authenticated user](operations/require-authenticated-user.md) | — | Global MVC `AuthorizeFilter` with `RequireAuthenticatedUser()` — denies anonymous access to every MVC endpoint unless `[AllowAnonymous]` | — | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L116–129 |
| A5 | [App startup configure services](operations/app-startup-configure-services.md), **External** host (`ASPNETCORE_HOST_LOCATION=EXTERNAL`) | A3 | `AddAuthorization()`. `SecurityApiPolicy`+`SecurityApiHandler` registered **twice** — inline and again via `AddSecurityApiAuthorizeAttribute()` (see [SEC-05](#security-observations)) | `ISecurityClient` registered Transient, then Singleton via `AddIdentityAccessor()` — last registration wins for single resolution | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` L98–137 |
| A6 | [App startup configure services](operations/app-startup-configure-services.md), **Internal or NotDefined** host | A1 (dual IIS/JWT, **not** OIDC) | A1 | A1 | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` L133–134 |
| A7 | [Core and Edge API startup](operations/core-and-edge-api-startup.md) — `CoreAPIStartup` | A1, unless `DisableAuthServices = true` (turns off **all** auth registration) | A1 | A1 | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/CoreAPIStartup.cs` L22, L61–64 |
| A8 | [Core and Edge API startup](operations/core-and-edge-api-startup.md) — `EdgeAPIStartup` | A2 | A2 (none) | A2 | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/EdgeAPIStartup.cs` L36 |
| A9 | [Register secure environment client](operations/register-secure-environment-client.md) | — | — (credential plumbing, not authorization). `ISystemHashService` is bound to the calling assembly, so secure-setting access is keyed on the caller's system hash. | — | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L82–92 |
| A10 | [Register environment client](operations/register-environment-client.md) (non-secure) | — | Registers `ISystemHashService` as a **null** singleton — any consumer resolving it in a non-secure host gets `null` | — | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L45–55 |

**Wired handler semantics** (summarized from AuthService; relevant here because this library activates the handler): `SecurityApiHandler.HandleRequirementAsync` returns without succeeding when `User.Identity.Name` is blank. It strips a `DOMAIN\` prefix, splits the required roles on `,`, and calls `ISecurityClient.IsAuthorized(user, role)` for each one, succeeding on the first `true` (OR semantics). The policy provider activates only for policy names starting with `SecurityAPI`.

### B. Pipeline placement

| Startup | Order of security-relevant middleware | Source | Notes |
| --- | --- | --- | --- |
| `AppStartup.Configure` | EnableBuffering → [`UseSession` → `AspNetSessionIdMiddleware`] (if `EnableSessionMiddleware`) → [Dynamic error handler invocation](operations/dynamic-error-handler-invoke.md) → [Debug request handler invocation](operations/debug-request-handler-invoke.md) → `UseAuthentication` → (External only: `LowerCaseUrlMiddleware` [OIDC challenge only] → `JwtClaimMiddleware` → `RefreshJwtMiddleware` [if enabled]) → `UseHsts` → `UseHttpsRedirection` (unless `ASPNETCORE_REDIRECT_SSL=false`) → `UseStaticFiles` → `UseRouting` → `ConfigureAuthorization` (virtual; default `UseAuthorization`) → `ConfigureUI` (endpoints) → `ConfigureSaifLogger` | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` L144–189, L195–198 | (1) The session gate runs **before** the error handler and before authentication. (2) `UseStaticFiles` runs before `UseAuthorization`, so static files are served without authorization (standard ASP.NET Core behavior*). (3) `ConfigureAuthorization` is `protected virtual` — a derived class can drop `UseAuthorization` entirely. |
| `CoreAPIStartup.Configure` | `ConfigureMiddleware` (buffering → error handler → debug handler) → `UseAuthentication` (skipped when `DisableAuthServices`) → `UseHsts` → `UseHttpsRedirection` → `UseRouting` → `UseAuthorization` (always) → `MapControllers` | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/CoreAPIStartup.cs` L74–97; `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/BaseApiStartup.cs` L33–42 | With `DisableAuthServices = true`, `UseAuthorization` still runs, but no authentication scheme is registered — any `[Authorize]` endpoint then fails at challenge time (`InvalidOperationException`: no default challenge scheme*). |
| `EdgeAPIStartup.Configure` | `ConfigureMiddleware` → `UseAuthentication` → `UseHsts` → `UseHttpsRedirection` → `UseRouting` → `UseAuthorization` → `MapControllers` | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/EdgeAPIStartup.cs` L45–65 | Standard ordering. |

No startup calls `RequireAuthenticatedUser()` (A4); none of the base Startup classes applies a global authenticated-user requirement by default. Each endpoint is protected only if the consumer decorates it with `[Authorize]`/`[SecurityApiAuthorize]` or calls `RequireAuthenticatedUser()` itself — **unprotected-by-default is the composed posture.**

### C. Cookie-gate middlewares

Both gate middlewares are documented together in [Legacy cookie gate middleware](operations/legacy-cookie-gate-middleware.md) and [BR-SE-16](business-rules.md#br-se-16-legacy-cookie-gates-check-presence-only-and-are-fail-open)

**`AspNetSessionIdMiddleware` — wired, fail-open gate (SEC-01, High).** Checks for presence only (`Request.Cookies["ASP.NET_SessionId"] == null`); never reads or validates the value (`src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Middleware/AspNetSessionIdMiddleware.cs` L37–39). On a missing cookie, redirects to the `LegacySessionProvider` endpoint (L41–44), but then **unconditionally** calls `await next(context)` (L47) — the redirect is advisory only; the rest of the pipeline (error handler, authentication, routing, authorization, endpoint) still executes, and any endpoint result that sets its own status/body overwrites the 302. Any client-supplied cookie value, including an arbitrary or expired one, satisfies the gate. Additional observations: the app's own `AddSession()` issues `.AspNetCore.Session`, not `ASP.NET_SessionId`, so only an external legacy session provider on a shared host/domain can set the cookie this gate checks for; the redirect host is derived from `Request.Host` without host filtering (L43), so a forged `Host` header produces a `Location` on an attacker-chosen host (low impact alone, but relevant to shared-cache poisoning); and the gate runs before the error handler (`src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` L152–158), so a failure in its settings lookup (L42) escapes the SAIF error handler. Mitigating control: ASP.NET Core authentication/authorization still applies independently to endpoints carrying `[Authorize]`/`[SecurityApiAuthorize]` — the defect bypasses only the legacy-session requirement, not decorated-endpoint authorization.

**`LegacyBolAuthMiddleware` — not wired, dead code, same flaw (SEC-02, latent).** Checks for presence of either `SAIFAUTH` or `SAIF.BOL.Auth` (`src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Middleware/LegacyBolAuthMiddleware.cs` L36–39), with the identical fail-open defect (unconditional `await next(context)` at L47 after `Redirect` at L44). It is registered in DI when `AppStartup.EnableLegacyBolAuthMiddleware = true` (`src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` L55, L113–116), but **no `UseMiddleware<LegacyBolAuthMiddleware>()` call exists anywhere in the repository** (repo-wide grep against `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` L144–189) — the flag registers a service that is never invoked, so setting it gives no protection (a misleading-configuration risk). The class is `public`, so an external consumer could wire it manually**.

## Security observations

### SEC-03 Exception detail disclosure to clients

| Field | Value |
| --- | --- |
| **Finding** | **Exception detail disclosure to clients.** Every `ControllerBaseExtensions.Throw*(Exception ex)` overload (see [Controller throw helpers](operations/controller-throw-helpers.md)) passes `ex.ToString()` (type, message, stack trace, inner exceptions) as the exception message; `DynamicErrorHandler`/`ErrorHandler.LogAndReturnException` writes it to the response body for handled exceptions. The response also carries a `Server-Name` header (machine name). |
| **Severity** | Medium |
| **Confidence** | verified |

### SEC-04 Credentials logged at Debug level

| Field | Value |
| --- | --- |
| **Finding** | **Credentials logged at Debug level.** [Debug request handler invocation](operations/debug-request-handler-invoke.md) runs on every request in every startup and logs `WebRequestDetails`, which captures all request headers (including `Authorization` and `Cookie`, which can carry `SAIFAUTH`) and the full request body with no redaction at the point this library emits the log event. **Mitigating control:** the LoggingApi sink (`SAIF.NetCore.Logging`'s `LoggingApiSink`) is reported to apply middleware that identifies and masks credentials and other secure data elements before the log entry is persisted to disk, Splunk, or Dynatrace; this masking is not implemented in, or traceable to source in, this repository.** Exposure at the point of emission (in-process, pre-sink) depends on the effective production log level. |
| **Severity** | Low (mitigated at the sink by LoggingApi masking, per the above); Medium at the point of emission if that mitigation is bypassed or the sink is misconfigured |
| **Confidence** | verified (code emits unredacted data at the point of logging); unknown (sink-side masking could not be confirmed in source)** |

### SEC-05 Duplicate security registrations in the External branch

| Field | Value |
| --- | --- |
| **Finding** | **Duplicate security registrations in the External branch.** `SecurityApiHandler` is added as `IAuthorizationHandler` twice in [App startup configure services](operations/app-startup-configure-services.md)'s External branch; ASP.NET Core runs every registered handler, so each `[SecurityApiAuthorize]` check calls the SecurityApi twice per role*. `ISecurityClient` is registered Transient then Singleton, so lifetime depends on resolution style. |
| **Severity** | Low (performance/clarity) |
| **Confidence** | verified (registrations); inferred (double call)* |

### SEC-06 Host-location fallback picks the internal auth stack

| Field | Value |
| --- | --- |
| **Finding** | **Host-location fallback picks the internal auth stack.** If `ASPNETCORE_HOST_LOCATION` is missing or unrecognized, `HostLocation = NotDefined` falls into the internal (dual IIS/JWT) branch instead of OIDC. On an externally facing host, a missing env var silently switches auth stacks, and no OIDC middleware runs. |
| **Severity** | Medium (misconfiguration) |
| **Confidence** | verified |

### SEC-07 Edge APIs have no SecurityApi policy provider

| Field | Value |
| --- | --- |
| **Finding** | **Edge APIs have no SecurityApi policy provider.** [Register Edge API auth services](operations/register-edge-api-auth-services.md) does not call `AddSecurityApiAuthorizeAttribute`. A consumer applying `[SecurityApiAuthorize("X")]` on an Edge API resolves the `SecurityAPI.X` policy through the default policy provider, which is not registered for it — authorization throws at run time instead of enforcing the role (fails closed, but as an error rather than a 403)*. |
| **Severity** | Low |
| **Confidence** | verified (absence); inferred (runtime behavior)* |

### SEC-08 DisableAuthServices removes all authentication

| Field | Value |
| --- | --- |
| **Finding** | **`DisableAuthServices` removes all authentication** for `CoreAPIStartup` derivatives with one protected flag; `UseAuthorization` still runs with no scheme registered. Intended as an opt-out, but a single switch for the whole auth stack. |
| **Severity** | Low (by design) |
| **Confidence** | verified |

### SEC-09 HTTPS redirection can be turned off by a machine env var

| Field | Value |
| --- | --- |
| **Finding** | **HTTPS redirection can be turned off by a machine env var.** `ASPNETCORE_REDIRECT_SSL=false` disables `UseHttpsRedirection` for `AppStartup` apps (default `true`, fail-secure); HSTS stays on. `CoreAPIStartup`/`EdgeAPIStartup` always redirect. |
| **Severity** | Low |
| **Confidence** | verified |

### SEC-10 Claim parsing in JwtControllerBase

| Field | Value |
| --- | --- |
| **Finding** | **Claim parsing in `JwtControllerBase`** (see [JWT controller claim helpers](operations/jwt-controller-claim-helpers.md)): `GetUsernameFromClaim` takes the first claim whose type *contains* `nameidentifier`, splits on `@`, upper-cases. Any exception yields `"Unknown"`; a missing claim yields `null`. Callers using this value for authorization or auditing get a non-validated, substring-matched identity. |
| **Severity** | Low |
| **Confidence** | verified |

### SEC-11 Secure credential bootstrap

| Field | Value |
| --- | --- |
| **Finding** | **Secure credential bootstrap.** [Register DB connection client](operations/register-db-connection-client.md) splits the `connectionservicecreds`/`dbconnectionclient` secure setting on `\|` without validating the format; a malformed value throws `IndexOutOfRangeException` at first resolution. No credential literal exists in source. |
| **Severity** | Low (robustness) |
| **Confidence** | verified |


## Data-level, segregation-of-duties, and machine authorization

None detected. No ownership validation (`CheckValidContext`, `IsValidPolicyForCurrentUser`, `ValidateOwnership`, or equivalent), no composite identity+resource check, no SOD class/method/privilege-combination query, and no machine-account (`$`-suffix) SAMAccountName handling exists in this library. This library composes framework-level authorization only.

## Security interfaces and contracts

| Interface/type | Role | Source library |
| --- | --- | --- |
| `ISecurityClient` | REST client for role/authorization checks, registered by this library on behalf of consumers | `SAIF.NetCore.AuthService` |
| `IAuthorizationPolicyProvider` (`SecurityApiPolicy`) | Dynamic authorization policy resolution for `SecurityAPI.*` policy names | `SAIF.NetCore.AuthService` |
| `IAuthorizationHandler` (`SecurityApiHandler`) | Evaluates `[SecurityApiAuthorize]` requirements via `ISecurityClient` | `SAIF.NetCore.AuthService` |
| `IIdentityService` / `IIdentityServiceAccessor` | Resolves the current identity depending on the active authentication scheme | `SAIF.NetCore.AuthService` |
| `IOidcSettings`, `RoleClaimTransformer`, `ILoginRedirectService` | OIDC settings, role-claim transformation, and login redirection composed into web applications | `SAIF.NetCore.OIDC` |
| `ISystemHashService` | Application-identity hash used to gate secure-setting retrieval (credential plumbing, not authorization) | `SAIF.NetCore.SystemHash` |

## Notes
- This page covers a REST SecurityApi composition root: there is no WCF SecurityService and no AD-group catalog owned by this library (see [AD resource catalog](#ad-resource-catalog) above).
- Severity labels (High/Medium/Low/latent) reflect this page's own risk assessment of the composed security posture, not a value read from any source artifact.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Configuration](configuration.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Service registration](service-registration.md)
- [API reference](api/index.md)
- [SAIF.NetCore.AuthService security and authorization](../saif-netcore-authservice/security-authorization.md)
- [SAIF.NetCore.OIDC overview](../saif-netcore-oidc/overview.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts. Statements marked with `**` could not be confirmed; treat
> as unknown until verified.

## Sources
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Middleware/AspNetSessionIdMiddleware.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Middleware/LegacyBolAuthMiddleware.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Middleware/DebugRequestHandler.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Middleware/DynamicErrorHandler.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs`, `CoreAPIStartup.cs`, `EdgeAPIStartup.cs`, `BaseApiStartup.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IAppBuilderExtensions.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/ControllerBaseExtensions.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/JwtControllerBase.cs`
- `src/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/Extensions/AuthenticationServiceExtensions.cs`
- `src/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/Authorization/SecurityAPIPolicy.cs`, `SecurityApiHandler.cs`
- `src/SAIF.NetCore.ErrorHandler/SAIF.NetCore.ErrorHandler/SAIF.NetCore.ErrorHandler/ErrorHandler.cs`
- `src/SAIF.NetCore.Logging/SAIF.NetCore.Logging/SAIF.NetCore.Logging/ExceptionFormatter/WebRequestDetails.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions.Integration.Tests/Controllers/AuthController.cs`, `ValuesController.cs`
