Skip to content

Authentication and authorization

Callers are identified by IIS using Windows integrated authentication; SAIF.Agency.Api contains no authentication code of its own. Authorization is enforced by [SaifAuthorize] attributes, but only on two of the three controllers: AgenciesController and AgentsController require the AgencyRead role, the agency contact update additionally requires AgencyContactWrite, and AppointmentsController — including its POST — carries no authorization construct at all.

Authentication

Aspect Finding
Mechanism Windows/NTLM via IIS
Established by IIS site configuration; <authentication mode="Windows" /> in Web.config with <anonymousAuthentication enabled="false" /> in the site's system.webServer/security section
Identity type WindowsIdentity, projected onto AgencyCaller by AgencyApiBase
Configured in src/SAIF.Agency.Api/Web.config
Anonymous access Denied

A caller proves identity before any managed code in this repository runs: IIS negotiates Windows authentication, and a request that fails to authenticate is rejected by the server with 401 Unauthorized without reaching the routing stage. AgencyApiBase reads RequestContext.Principal.Identity on every request and resolves it into an AgencyCaller record, which supplies the CHANGED_BY value written by the contact update. Consumers therefore call as their own service identity — the agency portal's application pool account, the SAIF.Claims.Intake application pool account, and the scheduled task account that runs SAIF.Policy.RenewalNotice — not as an end user.

There is no data-level restriction anywhere in the service: a caller holding AgencyRead can read every agency, not only the agency they belong to.

Authorization enforcement

Mechanism Scope Declared in Effect
[SaifAuthorize(Roles = "AgencyRead")] Controller src/SAIF.Agency.Api/Controllers/v1/AgenciesController.cs:18 Permits all four agency endpoints to callers in AgencyRead
[SaifAuthorize(Roles = "AgencyRead")] Controller src/SAIF.Agency.Api/Controllers/v1/AgentsController.cs:16 Permits all three agent endpoints to callers in AgencyRead
[SaifAuthorize(Roles = "AgencyContactWrite")] Action src/SAIF.Agency.Api/Controllers/v1/AgenciesController.cs:141 Replaces the controller requirement on UpdateAgencyContact; AgencyRead alone is not sufficient
None in code AppointmentsController — Every routed request reaches the action, including POST /v1/appointments; access relies entirely on network and IIS controls

Access requirements by endpoint

Endpoint Requirement Enforced by On failure
GET /v1/agencies/{agencyNumber} AgencyRead Controller attribute on AgenciesController 401 Unauthorized
GET /v1/agencies AgencyRead Controller attribute on AgenciesController 401 Unauthorized
GET /v1/agencies/{agencyNumber}/agents AgencyRead Controller attribute on AgenciesController 401 Unauthorized
PUT /v1/agencies/{agencyNumber}/contact AgencyContactWrite Action attribute on UpdateAgencyContact 401 Unauthorized
GET /v1/agents/{agentNumber} AgencyRead Controller attribute on AgentsController 401 Unauthorized
GET /v1/agents AgencyRead Controller attribute on AgentsController 401 Unauthorized
GET /v1/agents/{agentNumber}/appointments AgencyRead Controller attribute on AgentsController 401 Unauthorized
GET /v1/appointments/{appointmentId} None in code — Request proceeds
GET /v1/appointments None in code — Request proceeds
POST /v1/appointments None in code — Request proceeds; any authenticated caller can create an appointment

Roles and resources

Role / resource Grants Used by Source
AgencyRead Read access to agencies, agency rosters, and agents GET /v1/agencies/{agencyNumber}, GET /v1/agencies, GET /v1/agencies/{agencyNumber}/agents, GET /v1/agents/{agentNumber} src/SAIF.Agency.Api/Controllers/v1/AgenciesController.cs:18, src/SAIF.Agency.Api/Controllers/v1/AgentsController.cs:16
AgencyContactWrite Replacing an agency's contact block PUT /v1/agencies/{agencyNumber}/contact src/SAIF.Agency.Api/Controllers/v1/AgenciesController.cs:141

Secrets handling

Secret Retrieved by Consumed by Notes
agencyDb password GetSecureConfigSetting against the Environment API RegisterCommonDependencies in AutofacConfig.Register Read once at start-up and held by the NHibernate session factory; never present in Web.config

Security rules

SEC-API-001 Every request carries an authenticated Windows identity

Field Value
Statement The service accepts no anonymous request; IIS must have authenticated the caller before the request is routed.
Trigger Evaluated by IIS on every request, before managed code runs.
Enforcement <authentication mode="Windows" /> and disabled anonymous authentication in src/SAIF.Agency.Api/Web.config.
Applies to All ten endpoints, including POST /v1/appointments
Outcome IIS returns 401 Unauthorized with no response body; nothing is logged by the application.
Source src/SAIF.Agency.Api/Web.config:34

SEC-API-002 Agency contact changes require the AgencyContactWrite role

Field Value
Statement Only a caller in AgencyContactWrite may change an agency's contact block; read access to agency data does not imply write access.
Trigger Evaluated by the authorization filter before UpdateAgencyContact binds its body.
Enforcement [SaifAuthorize(Roles = "AgencyContactWrite")] on the action, which replaces the controller-level AgencyRead requirement.
Applies to PUT /v1/agencies/{agencyNumber}/contact
Outcome 401 Unauthorized with an empty body; the action does not run and nothing is written.
Source src/SAIF.Agency.Api/Controllers/v1/AgenciesController.cs:141

SEC-API-003 Every write is attributed to the calling identity

Field Value
Statement A contact change must record the Windows account that made it, so an incorrect address can be traced to the caller that supplied it.
Trigger Evaluated when the contact update writes its audit row, inside the same unit of work as the change.
Enforcement AgencyApiBase.Caller resolves RequestContext.Principal.Identity.Name and AgencyService.UpdateContact writes it to AGENCY_CONTACT_AUDIT.CHANGED_BY.
Applies to PUT /v1/agencies/{agencyNumber}/contact
Outcome On success the audit row carries the caller; if the identity cannot be resolved the service raises AgencyValidationException and the caller receives 400 Bad Request rather than an unattributed write.
Source src/SAIF.Agency.Api.Services/AgencyService.cs:212

Notes

  • Mark inferred statements with * and unverifiable statements with **. Do not use bold inline confidence labels.
  • The role memberships behind AgencyRead and AgencyContactWrite are managed in Active Directory and are not visible from this repository.**

Sources

  • src/SAIF.Agency.Api/Web.config
  • src/SAIF.Agency.Api/Controllers/AgencyApiBase.cs
  • src/SAIF.Agency.Api/Controllers/v1/AgenciesController.cs
  • src/SAIF.Agency.Api/Controllers/v1/AgentsController.cs
  • src/SAIF.Agency.Api/Controllers/v1/AppointmentsController.cs
  • src/SAIF.Agency.Api/App_Start/AutofacConfig.cs
  • src/SAIF.Agency.Api.Services/AgencyService.cs