Register OIDC services¶
This operation registers the full set of OIDC-related middleware and services (claim synchronization, role transformation, JWT refresh, login redirects, data-protection certificates), then delegates to Add web authentication to configure the authentication schemes. It is used by App startup configure services when HostLocation == External.
| Field | Value |
|---|---|
| Operation ID | OP-07 |
| Trigger | AppStartup.ConfigureServices (or a consumer) calls RegisterOidcServices(type = Cookie, useJwtRefreshMiddleware = true). |
| Inputs | type — the authentication challenge type (Cookie or OpenIdConnect); useJwtRefreshMiddleware — whether IJwtRefreshService is registered in the service collection (this method performs DI registration only; it does not construct or alter the HTTP request pipeline). |
| Outputs | OIDC middleware/services registered; web authentication schemes configured via OP-08. |
| Primary components | IServiceCollectionExtensions.RegisterOidcServices |
| Entry point | src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs (L137–168) |
Steps¶
- Register Scoped
JwtClaimMiddleware,LowerCaseUrlMiddleware,RefreshJwtMiddlewareunconditionally (BR-SE-10) - All three middleware types are registered in the container regardless of the
useJwtRefreshMiddlewareflag; that flag gates only theIJwtRefreshServiceregistration in step 4.AppStartupseparately passes itsUseJwtRefreshMiddlewareproperty into this parameter during service configuration and reads the same property again duringConfigureto decide whether to insertRefreshJwtMiddlewareinto the pipeline (see App startup configure pipeline). This registration method itself performs no pipeline insertion.
Origin:
JwtClaimMiddleware's claim-synchronization logic is implemented inSync JWT claimsandLowerCaseUrlMiddleware's logic inEnforce URL casing(SAIF.NetCore.OIDC). 2. Register SingletonIOidcSettings → OidcSettings.OidcSettings's constructor only stores its injectedIEnvironmentClient/ISystemHashServicedependencies; it does not itself require or call a secure environment client, and most of its property/indexer getters read ordinary (non-secure) settings. Only the laterAppCredentialsgetter needs a usable (non-null)ISystemHashService— see the failure section below (see Register secure environment client for how a secureISystemHashServiceis registered).Origin: Settings resolution logic is implemented in
Resolve OIDC settings(SAIF.NetCore.OIDC); this step only registers theOidcSettingstype.OidcSettings's constructor only stores its injectedIEnvironmentClient/ISystemHashServicedependencies — it performs no environment/secure-setting reads itself. Construction happens once, at first resolution ofIOidcSettings. Each individual setting (for exampleDPCertName,CookieName) is instead fetched lazily, on every call to its corresponding property or indexer getter, which can happen many times after construction, not just once "at first resolution." 3. Register ScopedIUrlCaseService → UrlCaseService; ScopedRoleClaimTransformer; ScopedIRoleClaimService → RoleClaimService; SingletonIClaimTransformCacheService → ClaimTransformationCacheService; TransientILoginRedirectService → LoginRedirectService.Origin: Role-claim transformation and caching is implemented in
Transform role claimsandRole transform cache; login redirection inRedirect to login(SAIF.NetCore.OIDC). 4. IfuseJwtRefreshMiddleware: register ScopedIJwtRefreshService → JwtRefreshService(BR-SE-10)Origin: Token refresh logic is implemented in
Refresh tokens(SAIF.NetCore.OIDC); this step only registers theJwtRefreshServicetype, and its token-refresh logic runs later, at request time. 5. Register ScopedIJwtAuthorizationCookieClaimService → JwtAuthorizationCookieClaimService; SingletonIDataProtectionCertService → DataProtectionCertService.Origin: Certificate resolution logic is implemented in
Resolve DP certificate(SAIF.NetCore.OIDC); this step only registers theDataProtectionCertServicetype. Its constructor stores the injectedIOidcSettings/ISaifLogServiceand immediately callsIEnvironmentClient.IsDeveloperMachine()at construction time (first resolution ofIDataProtectionCertService) — it does not inject or resolveISystemHashServicedirectly. The actual certificate lookup is inGetCertificate(), which is not called during construction: it only runs whenConfigureCookieAuthenticationOptions.Configure(name, options)(anIConfigureNamedOptions<CookieAuthenticationOptions>) executes, which itself happens later, the first time the framework resolves namedCookieAuthenticationOptionsfor the"Cookies"scheme (typically on the first request that evaluates cookie authentication), not during this registration call or duringDataProtectionCertServiceconstruction. 6. CallAddWebAuthentication(type), a same-library registration operation that is executed synchronously as part of this call (BR-SE-11): it registersConfigureOptions<ConfigureCookieAuthenticationOptions>()/ConfigureOptions<ConfigureOpenIdConnectOptions>()(deferredIConfigureOptions<CookieAuthenticationOptions>/IConfigureOptions<OpenIdConnectOptions>, each applied later, only the first time the framework resolves that named-scheme options instance), callsAddAuthentication(options => ...)to setDefaultAuthenticateScheme = DefaultSignInScheme = "Cookies"andDefaultChallengeScheme = "OpenIdConnect"iftype == OpenIdConnectelse"Cookies", then.AddCookie("Cookies").AddOpenIdConnect()to register both handlers regardless of which one is the default challenge scheme.Origin:
AddWebAuthentication(type)'s full step-by-step registration behavior (the exact deferred-configurator and scheme-default wiring summarized above) is documented on Add web authentication (same library,IServiceCollectionExtensions.AddWebAuthentication); unlike the OIDC registrations in steps 1–5, this call executes immediately, synchronously, as part ofRegisterOidcServicesitself — it is not deferred to first resolution.
Process flow¶
This diagram shows the one-time DI registration sequence performed when RegisterOidcServices(type, useJwtRefreshMiddleware) is called during service configuration, including the synchronous AddWebAuthentication(type) delegation in the final step; it does not depict per-request middleware/claim-transformation behavior.
flowchart TD
Start([RegisterOidcServices called]) --> S1[Register OIDC middleware]
S1 --> S2[Register IOidcSettings]
S2 --> S3[Register role-claim / login-redirect services]
S3 --> S4{useJwtRefreshMiddleware?}
S4 -->|Yes| S4a[Register IJwtRefreshService]
S4 -->|No| S5[Register cookie-claim / data-protection cert services]
S4a --> S5
S5 --> S6[AddWebAuthentication]
S6 --> EndOk([OIDC services registered])
Failure and edge-case behavior¶
- Resolving
IOidcSettingsitself never requires a secure environment client:OidcSettings's constructor only stores its injectedIEnvironmentClient/ISystemHashServicedependencies. The secure-client requirement is lazy and property-specific — only theAppCredentialsgetter later calls_systemHashService.ComputeHash(SystemType.Other, Assembly.GetExecutingAssembly().GetName().Name)(OIDC's own executing assembly, not the caller's) and_environmentClient.GetSecureSetting(Constants.AppCredentialsKey, Constants.EnvironmentSection, hash), so registeringRegisterOidcServiceswithout a prior secure environment-client registration (a null-hashISystemHashService) only fails the first time code readsOidcSettings.AppCredentials— for example fromConfigureOpenIdConnectOptions— not atIOidcSettingsresolution or construction. Every otherOidcSettingsproperty/indexer getter reads an ordinary (non-secure) setting and does not require a secure client (see BR-SE-01).
Related documentation¶
Sources¶
src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs