---
title: Service registration
summary: Services, options, middleware, and claims-transformation registered for this library by the consumer.
status: draft
owner: SAIF Framework Platform Team
last_reviewed: 2026-10-02
library: SAIF.NetCore.OIDC
reference_type: package
---

# Service registration

This library registers **no services of its own** — it exposes concrete types (middleware, options configurators, claims transformer, and DI services implementing `SAIF.NetCore.ServiceContracts` interfaces) that a consuming application must register and wire into the ASP.NET Core pipeline. In the one consumer composition inspected for this documentation, that wiring is done by referencing `SAIF.NetCore.ServiceExtensions` and calling `RegisterOidcServices` (service registration) plus `AppStartup.Configure`/`AddWebAuthentication` (middleware pipeline and named-options activation); whether every consumer of this library does so the same way is not verified*.

## DI registrations (consumer: SAIF.NetCore.ServiceExtensions.RegisterOidcServices)

None of these registrations are made by this library itself; they are reproduced here for context because this library's types are meaningless without them.

| Service type | Implementation | Lifetime | Condition | Source |
| --- | --- | --- | --- | --- |
| `IOidcSettings` | `OidcSettings` | Singleton | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–167 |
| `IClaimTransformCacheService` | `ClaimTransformationCacheService` | Singleton | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–167 |
| `IDataProtectionCertService` | `DataProtectionCertService` | Singleton | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–167 |
| `JwtClaimMiddleware`, `LowerCaseUrlMiddleware`, `RefreshJwtMiddleware` | (concrete types; each implements `IMiddleware` but is registered directly as its own concrete type, not as an `IMiddleware` service key — consumed via `app.UseMiddleware<T>()`) | Scoped | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–167 |
| `IUrlCaseService` | `UrlCaseService` | Scoped | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–167 |
| `RoleClaimTransformer` (**concrete type only** — not registered as `IClaimsTransformation`) | `RoleClaimTransformer` | Scoped | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L149 |
| `IRoleClaimService` | `RoleClaimService` | Scoped | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–167 |
| `IJwtAuthorizationCookieClaimService` | `JwtAuthorizationCookieClaimService` | Scoped | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–167 |
| `IJwtRefreshService` | `JwtRefreshService` | Scoped | Conditional on `useJwtRefreshMiddleware` | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–167 |
| `ILoginRedirectService` | `LoginRedirectService` | Transient | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–167 |
| `IConfigureOptions<CookieAuthenticationOptions>` | `ConfigureCookieAuthenticationOptions` | via `ConfigureOptions<ConfigureCookieAuthenticationOptions>` (options-system lifetime) | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L182 |
| `IConfigureOptions<OpenIdConnectOptions>` | `ConfigureOpenIdConnectOptions` | via `ConfigureOptions<ConfigureOpenIdConnectOptions>` (options-system lifetime) | Always | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L187 |

**Important registration gap (A-07):** `RoleClaimTransformer` implements `IClaimsTransformation`, which ASP.NET Core resolves automatically during `AuthenticateAsync`. It is registered only as its concrete type, so the transformer is **never invoked automatically** by the framework — contrary to its own XML-doc comment ("called automatically"). See [Transform role claims](operations/op-09-transform-role-claims.md) and [Security and authorization](security-authorization.md).

## Middleware pipeline order (consumer: src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs)

The middleware this library ships is wired only when `HostLocation == External` (see [Configuration](configuration.md) for the `ASPNETCORE_HOST_LOCATION` variable). The composed request pipeline, in order:

1. Request buffering enabled (`EnableBuffering`).
2. Session middleware.
3. Error handling.
4. `UseAuthentication()`.
5. *(External only)* `LowerCaseUrlMiddleware` — only when `ChallengeType == OpenIdConnect`.
6. `JwtClaimMiddleware`.
7. `RefreshJwtMiddleware` — only if `UseJwtRefreshMiddleware` is `true`.
8. HSTS.
9. HTTPS redirection.
10. Static files.
11. Routing.
12. Authorization.

Source: `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` L150–185.

## Feature flags

Host-level code properties/environment inputs (not `appsettings.json` keys) that change whether this library's middleware/services are active. See [Configuration](configuration.md) for the full environment-variable catalog.

| Name | Kind | Default | Effect | Source |
| --- | --- | --- | --- | --- |
| `HostLocation` (`ASPNETCORE_HOST_LOCATION`) | Environment variable, read by `AppStartup` | `NotDefined` | Only `External` registers OIDC services and wires the OIDC middleware. | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` |
| `AuthenticationChallengeType` | Code property (`AppStartup`) | `Cookie` | When `OpenIdConnect`, `LowerCaseUrlMiddleware` is included in the pipeline and `OpenIdConnect` becomes the default challenge scheme. Both the `"Cookies"` and `"OpenIdConnect"` named-options configurators, and both authentication schemes, are registered unconditionally by `AddWebAuthentication` regardless of this property's value. | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` |
| `UseJwtRefreshMiddleware` | Code property (`AppStartup`) | `true` | `RefreshJwtMiddleware` is **always** registered as a concrete scoped type regardless of this flag. This flag only controls (a) whether `IJwtRefreshService` is registered in DI, and (b) whether `RefreshJwtMiddleware` is inserted into the pipeline — when `false`, the middleware type exists in DI but is never added to the pipeline and is therefore never invoked. | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` (DI, always-registered); `Startup/AppStartup.cs` (pipeline insertion, conditional) |

## Registration extension catalog

Both extension methods below are consumer-owned — they are defined in `SAIF.NetCore.ServiceExtensions`, not in this library (`SAIF.NetCore.OIDC`). This library ships only the concrete types they register.

| Extension method | Declaring library | Purpose | Always runs | Source |
| --- | --- | --- | --- | --- |
| `RegisterOidcServices(IServiceCollection, AuthenticationChallengeType, bool)` | `SAIF.NetCore.ServiceExtensions` | Registers every OIDC service and middleware concrete type listed above, then calls `AddWebAuthentication`. | Yes, when invoked by the consuming host's `Startup`. | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L137–169 |
| `AddWebAuthentication(IServiceCollection, AuthenticationChallengeType)` | `SAIF.NetCore.ServiceExtensions` | Adds the `AddAuthentication().AddCookie().AddOpenIdConnect()` scheme chain and registers both named-options configurators; sets the default challenge scheme. | Yes, called from inside `RegisterOidcServices`; both configurators and both schemes are added unconditionally regardless of `type`. | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` L177+ |

## Required-but-not-registered services

Services this library's types resolve that none of its own methods add — the consuming application, through `RegisterOidcServices`/`AddWebAuthentication`, is responsible for supplying them.

| Service type | Consumer | Expected source |
| --- | --- | --- |
| `IEnvironmentClient` | `OidcSettings`, `DataProtectionCertService` (`IsDeveloperMachine`) | `SAIF.NetCore.EnvironmentClient` |
| `ISystemHashService` | `OidcSettings.AppCredentials` (secure-setting hash) | `SAIF.NetCore.SystemHash` |
| `ISaifLogService` | Options configurators, middleware, `DataProtectionCertService` | `SAIF.NetCore.Logging` |
| `IHttpJsonClient` | `JwtRefreshService` | `SAIF.NetCore.HttpClients` |
| `IHttpContextAccessor` | Several services that need the current request | ASP.NET Core (`AddHttpContextAccessor`) |
| `IAuthenticationService` | `JwtClaimMiddleware`, `RefreshJwtMiddleware` | ASP.NET Core (`AddAuthentication`) |

## 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)
- [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. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Sources
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/SAIF.NetCore.OIDC.csproj`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Constants.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Contracts/RefreshTokenResult.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Exceptions/HttpContextAuthenticateException.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Exceptions/JwtRefreshException.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Exceptions/MissingDataProtectionCertificateException.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Extensions/ClaimsPrincipalExtensions.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Extensions/HttpContextExtensions.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Middleware/JwtClaimMiddleware.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Middleware/LowerCaseUrlMiddleware.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Middleware/RefreshJwtMiddleware.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Options/ConfigureCookieAuthenticationOptions.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Options/ConfigureOpenIdConnectOptions.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/ClaimTransformationCacheService.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/DataProtectionCertService.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/JwtAuthorizationCookieClaimService.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/JwtRefreshService.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/LoginRedirectService.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/OidcSettings.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/RoleClaimService.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/RoleClaimTransformer.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/UrlCaseService.cs`
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` (consumer composition; `RegisterOidcServices`/`AddWebAuthentication` registrations documented on this page)
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` (consumer composition; middleware pipeline order and feature-flag gating documented on this page)

