---
title: Service registration
summary: Services, options, startup base classes, middleware, and hosted services this library contributes to a consuming application.
status: draft
owner: SAIF Platform Team
last_reviewed: 2026-10-02
library: SAIF.NetCore.NtlmApiAuth
reference_type: package
---

# Service registration

SAIF.NetCore.NtlmApiAuth exposes two `IServiceCollection` extension methods (one server-side, one client-side), one `IApplicationBuilder` middleware extension, and one `SwaggerGenOptions` extension. `AddNtlmApiAuthorization<T>()` registers five server-side services of its own (3 Scoped, 2 Transient) plus the framework's `AddAuthorization()`; `AddNtmlApiAuthorizationClientServices()` separately registers one additional client-side `ICurrentUserService` (Scoped), selecting either `MvcCurrentUserService` or `BlazorCurrentUserService` depending on `ClientAppType` — not a second, simultaneous registration on top of the server-side five. Calling both extensions on the same `IServiceCollection` (an unusual but possible combination) registers `ICurrentUserService` twice, with the client-side call's implementation winning, rather than producing an unqualified total of seven distinct services. The library requires the consuming application to register `ISecurityClient`, `IEnvironmentClient`, `IHttpJsonClient`, `IHttpContextAccessor`, and host authentication itself.

## Registration extension catalog

| Extension method | Hosting context | Parameters | Source |
| --- | --- | --- | --- |
| `AddNtlmApiAuthorization<T>(this IServiceCollection services)` | API (server-side) | `T : ConfigureRoleAuthorizationOptions` — consumer's policy subclass | `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/IServiceCollectionExtensions.cs` |
| `AddNtmlApiAuthorizationClientServices(this IServiceCollection services, ClientAppType appType = Mvc)` | Web (MVC or Blazor client) | `ClientAppType` — selects `MvcCurrentUserService` or `BlazorCurrentUserService` | same |
| `UseNtlmApiAuthorization(this IApplicationBuilder app)` | API (server-side) | none | `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/IApplicationBuilderExtensions.cs` |
| `AddDebuggerOnBehalfOfHeader(this SwaggerGenOptions options)` | API (server-side, Swagger) | none | `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/SwaggerGenOptionsExtensions.cs` |
| `ConfigureOnBehalfOfUserAuthorization(this IHttpJsonClient client, ICurrentUserService currentUserService)` | Any (client, not DI) | `ICurrentUserService` | `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/IHttpJsonClientExtensions.cs` |
| `ForwardOnBehalfOfUserHeader(this IHttpContextAccessor accessor, IHttpJsonClient client)` | API (server-side, not DI) | `IHttpJsonClient` | `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/HttpContextAccessorExtensions.cs` |

## Service registration catalog

| Service type | Implementation | Lifetime | Registered by | Condition | Source |
| --- | --- | --- | --- | --- | --- |
| `IConfigureOptions<AuthorizationOptions>` | `T` (consumer subclass of `ConfigureRoleAuthorizationOptions`), via `ConfigureOptions<T>()` | Transient | `AddNtlmApiAuthorization<T>` | Always | `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/IServiceCollectionExtensions.cs` |
| `ICurrentUserService` | `MvcCurrentUserService` | Scoped | `AddNtlmApiAuthorization<T>` | Always | same |
| `INtlmApiAuthorizationService` | `NtlmApiAuthorizationService` | Transient | `AddNtlmApiAuthorization<T>` | Always | same |
| `IOnBehalfOfUserClaimService` | `OnBehalfOfUserClaimService` | Scoped | `AddNtlmApiAuthorization<T>` | Always | same |
| `OnBehalfOfUserClaimMiddleware` | self | Scoped | `AddNtlmApiAuthorization<T>` | Always | same |
| framework authorization services | (framework) | (framework) | `AddNtlmApiAuthorization<T>` → `AddAuthorization()` | Always | same |
| `ICurrentUserService` | `MvcCurrentUserService` (Mvc) / `BlazorCurrentUserService` (Blazor) | Scoped | `AddNtmlApiAuthorizationClientServices` | Always (implementation depends on `appType`) | same |

All registrations use `Add*`, not `TryAdd*`: calling both `AddNtlmApiAuthorization<T>()` and `AddNtmlApiAuthorizationClientServices(this IServiceCollection services, ClientAppType appType = ClientAppType.Mvc)` registers `ICurrentUserService` twice — the last call wins. `RoleRequirement` is not registered as `IAuthorizationHandler`; it relies on the framework `PassThroughAuthorizationHandler` because it is a self-handling requirement.

## Options configuration

| Options type | Named instance | Configured by | Configuration keys / services read | Source |
| --- | --- | --- | --- | --- |
| `AuthorizationOptions` | default | Consumer subclass of `ConfigureRoleAuthorizationOptions` (registered as `IConfigureOptions<AuthorizationOptions>`) | None directly — reads the consumer's `SetPolicies()` override | `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Options/ConfigureRoleAuthorizationOptions.cs` |

`ConfigureRoleAuthorizationOptions` is an abstract `IConfigureOptions<AuthorizationOptions>` base class; consumers must implement `SetPolicies`. There is no library-defined options POCO and no `IConfiguration` binding.

## Middleware pipeline

### Consumer Configure

| Order | Middleware | Condition | Notes |
| --- | --- | --- | --- |
| 1 | `OnBehalfOfUserClaimMiddleware` (`IMiddleware`, Scoped) via `UseNtlmApiAuthorization()` | Always | Must run after the request identity is authenticated (IIS Windows auth sets it before the pipeline; otherwise must follow `UseAuthentication()`), and before `UseAuthorization()`/endpoint execution. |

## Required-but-not-registered services

| Service type | Consumer | Expected source |
| --- | --- | --- |
| `ISecurityClient` | `NtlmApiAuthorizationService` (via `ConfigureRoleAuthorizationOptions` → every `RoleRequirement`) | AuthService's `AddTokenIdentityService` / `AddWinIdentityService` / `AddIdentityAccessor` (all register `SecurityClient` Singleton) |
| `IEnvironmentClient` | `NtlmApiAuthorizationService` constructor (injected but unused); AuthService's `SecurityClient` | `SAIF.NetCore.EnvironmentClient`* |
| `IHttpJsonClient` | AuthService's `SecurityClient`; client-side consumer code | `SAIF.NetCore.HttpClients` |
| `IHttpContextAccessor` | `MvcCurrentUserService`; `ForwardOnBehalfOfUserHeader` callers | `services.AddHttpContextAccessor()` |
| `AuthenticationStateProvider` | `BlazorCurrentUserService` | Blazor host |
| Windows/NTLM authentication | Request identity | IIS, or `AddAuthentication(IISServerDefaults.AuthenticationScheme)` / AuthService's `AddIISAuthentication` |
| `SwaggerGenOptions` | `AddDebuggerOnBehalfOfHeader` | `services.AddSwaggerGen(options => options.AddDebuggerOnBehalfOfHeader())` |

## 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)
- [Security and authorization](security-authorization.md)
- [API reference](api/index.md)

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

## Sources
- `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/IServiceCollectionExtensions.cs`
- `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/IApplicationBuilderExtensions.cs`
- `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Options/ConfigureRoleAuthorizationOptions.cs`
- `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/SwaggerGenOptionsExtensions.cs`
- `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/IHttpJsonClientExtensions.cs`
- `src/SAIF.NetCore.NtlmApiAuth/src/SAIF.NetCore.NtlmApiAuth/Extensions/HttpContextAccessorExtensions.cs`
