Skip to content

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

  1. AddHttpContextAccessor, AddAuthorization, and delegate to Register secure environment client via RegisterSecureEnvironmentClient(GetType()) (BR-SE-03)
  2. The hash identity is keyed on the derived Startup class's own assembly, not AppStartup itself.

Origin: RegisterSecureEnvironmentClient performs three concrete registrations, all deferred to first resolution (none run during this call): (1) the same AddHttpContextAccessor/ISystemWrapper/IHostResolver/IHttpJsonClient registrations as Register environment client steps 1–3; (2) a Singleton IEnvironmentClient → SecureEnvironmentClient type-based descriptor; (3) a Singleton ISystemHashService factory that constructs new SystemHashService(Assembly.GetAssembly(type)), where type is the GetType() passed in above. See Register secure environment client for the full step-by-step detail, including its documented ArgumentNullException edge case when type is null.

  1. If EnableSessionMiddleware: AddSession() and register Scoped AspNetSessionIdMiddleware (BR-SE-17)
  2. If EnableLegacyBolAuthMiddleware: register Scoped LegacyBolAuthMiddleware (BR-SE-16)
  3. This registration is never added to the request pipeline (dead code*; see App startup configure pipeline).
  4. AddControllersWithViews(), plus AddNewtonsoftJson() if EnableNewtonsoftJsonSerializer is set.
  5. Delegate to Register logging and error handler via RegisterLoggingService().

Origin: RegisterLoggingService() registers a Singleton ISaifLogService → SaifLog; registration only adds the descriptor — SaifLog's own configuration/logging logic runs later, as documented on Register logging and error handler step 1 and Configure web logger (SAIF.NetCore.Logging). 6. If HostLocation == External: delegate to Register OIDC services via RegisterOidcServices(AuthenticationChallengeType, UseJwtRefreshMiddleware); additionally register Transient ISecurityClient → SecurityClient; Transient IAuthorizationPolicyProvider → SecurityApiPolicy + Singleton IAuthorizationHandler → SecurityApiHandler; call AddIdentityAccessor(); call AddSecurityApiAuthorizeAttribute() (BR-SE-18) - ISecurityClient ends up registered both Transient (here) and Singleton (inside AddIdentityAccessor/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: RegisterOidcServices registers Scoped JwtClaimMiddleware/LowerCaseUrlMiddleware/RefreshJwtMiddleware, Singleton IOidcSettings → OidcSettings, role-claim/login-redirect/cookie-claim/data-protection-certificate services, then synchronously calls AddWebAuthentication(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 when type == 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 via RegisterCoreAPIAuthServices() (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 via RegisterFactoryActivatedMiddleware().

Origin: RegisterFactoryActivatedMiddleware() registers a Scoped IErrorHandleable factory (ErrorHandler) plus Transient DynamicErrorHandler and DebugRequestHandler; registration only adds these descriptors — ErrorHandler's exception handling runs later, per request, as documented on Register logging and error handler steps 2–3 and Log 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.
  • LegacyBolAuthMiddleware is registered in DI but never wired into the pipeline, so enabling EnableLegacyBolAuthMiddleware has no observable effect on request handling (dead code*).

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