App startup configure services¶
This operation is the service-configuration phase of the web UI startup archetype. It selects between the OIDC and Core dual-authentication stacks based on ASPNETCORE_HOST_LOCATION, and composes session, logging, and MVC services.
| Field | Value |
|---|---|
| Operation ID | OP-14 |
| Trigger | The ASP.NET Core host calls ConfigureServices(IServiceCollection services) on an AppStartup-derived class (OidcMvcStartup/OidcRazorStartup). |
| Inputs | The IServiceCollection; AppStartup's instance flags (EnableSessionMiddleware, EnableLegacyBolAuthMiddleware, EnableNewtonsoftJsonSerializer, HostLocation, AuthenticationChallengeType, UseJwtRefreshMiddleware). |
| Outputs | A fully composed DI container for the web application. |
| Primary components | AppStartup.ConfigureServices |
| Entry point | src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs (L100–137) |
Steps¶
AddHttpContextAccessor,AddAuthorization, and delegate to Register secure environment client viaRegisterSecureEnvironmentClient(GetType())(BR-SE-03)- The hash identity is keyed on the derived Startup class's own assembly, not
AppStartupitself.
Origin:
RegisterSecureEnvironmentClientperforms three concrete registrations, all deferred to first resolution (none run during this call): (1) the sameAddHttpContextAccessor/ISystemWrapper/IHostResolver/IHttpJsonClientregistrations as Register environment client steps 1–3; (2) a SingletonIEnvironmentClient → SecureEnvironmentClienttype-based descriptor; (3) a SingletonISystemHashServicefactory that constructsnew SystemHashService(Assembly.GetAssembly(type)), wheretypeis theGetType()passed in above. See Register secure environment client for the full step-by-step detail, including its documentedArgumentNullExceptionedge case whentypeisnull.
- If
EnableSessionMiddleware:AddSession()and register ScopedAspNetSessionIdMiddleware(BR-SE-17) - If
EnableLegacyBolAuthMiddleware: register ScopedLegacyBolAuthMiddleware(BR-SE-16) - This registration is never added to the request pipeline (dead code*; see App startup configure pipeline).
AddControllersWithViews(), plusAddNewtonsoftJson()ifEnableNewtonsoftJsonSerializeris set.- Delegate to Register logging and error handler via
RegisterLoggingService().
Origin:
RegisterLoggingService()registers a SingletonISaifLogService → SaifLog; registration only adds the descriptor —SaifLog's own configuration/logging logic runs later, as documented on Register logging and error handler step 1 andConfigure web logger(SAIF.NetCore.Logging). 6. IfHostLocation == External: delegate to Register OIDC services viaRegisterOidcServices(AuthenticationChallengeType, UseJwtRefreshMiddleware); additionally register TransientISecurityClient → SecurityClient; TransientIAuthorizationPolicyProvider → SecurityApiPolicy+ SingletonIAuthorizationHandler → SecurityApiHandler; callAddIdentityAccessor(); callAddSecurityApiAuthorizeAttribute()(BR-SE-18) -ISecurityClientends up registered both Transient (here) and Singleton (insideAddIdentityAccessor/AddSecurityApiAuthorizeAttribute), and the SecurityApi policy-provider/handler pair is registered twice; the last registration wins when the container resolves a single instance (duplicate-registration defect*).Origin:
RegisterOidcServicesregisters ScopedJwtClaimMiddleware/LowerCaseUrlMiddleware/RefreshJwtMiddleware, SingletonIOidcSettings → OidcSettings, role-claim/login-redirect/cookie-claim/data-protection-certificate services, then synchronously callsAddWebAuthentication(type), which configures the deferred Cookie/OpenIdConnect option configurators and sets the default authenticate/sign-in/challenge schemes ("Cookies"for authenticate/sign-in; challenge defaults to"OpenIdConnect"only whentype == OpenIdConnect). See Register OIDC services for its full embedded registration steps and timing. 7. Else (internal host location): delegate to Register Core API auth services viaRegisterCoreAPIAuthServices()(BR-SE-18)Origin:
RegisterCoreAPIAuthServices()configures JWT bearer options, registers the identity accessor, adds the "dual" JWT/Windows policy scheme, and registers SecurityApi dynamic authorization. See Register Core API auth services for its full embedded registration steps and per-request scheme-selection timing. 8. Delegate to Register logging and error handler viaRegisterFactoryActivatedMiddleware().Origin:
RegisterFactoryActivatedMiddleware()registers a ScopedIErrorHandleablefactory (ErrorHandler) plus TransientDynamicErrorHandlerandDebugRequestHandler; registration only adds these descriptors —ErrorHandler's exception handling runs later, per request, as documented on Register logging and error handler steps 2–3 andLog and return exception(SAIF.NetCore.ErrorHandler).
Process flow¶
This diagram shows the one-time ConfigureServices composition that runs once during host startup for a web-app AppStartup-derived class, not any per-request behavior of the services it registers.
flowchart TD
Start([ConfigureServices invoked]) --> S1["AddHttpContextAccessor / AddAuthorization /<br>RegisterSecureEnvironmentClient"]
S1 --> S2{EnableSessionMiddleware?}
S2 -->|Yes| S2a["AddSession + register AspNetSessionIdMiddleware"]
S2 -->|No| S3{EnableLegacyBolAuthMiddleware?}
S2a --> S3
S3 -->|Yes| S3a[Register LegacyBolAuthMiddleware - never piped]
S3 -->|No| S4[AddControllersWithViews]
S3a --> S4
S4 --> S5[RegisterLoggingService]
S5 --> S6{HostLocation == External?}
S6 -->|Yes| S6a["RegisterOidcServices + duplicate SecurityApi registrations"]
S6 -->|No| S6b[RegisterCoreAPIAuthServices]
S6a --> S7[RegisterFactoryActivatedMiddleware]
S6b --> S7
S7 --> EndOk([DI container composed])
Failure and edge-case behavior¶
- Duplicate
ISecurityClient/SecurityApi registrations in the External branch mean the last registration wins on a single-instance resolve, which may not be the intended implementation. LegacyBolAuthMiddlewareis registered in DI but never wired into the pipeline, so enablingEnableLegacyBolAuthMiddlewarehas no observable effect on request handling (dead code*).
Related documentation¶
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/Startup/AppStartup.cs