---
title: Authorize a request against SAIF roles
summary: Decide whether the current user is authorized for any of the roles declared on the filter.
status: draft
owner: SAIF Documentation
last_reviewed: 2026-09-17
library: SAIF.Framework.Web.Mvc
reference_type: package
operation_id: OP-09
trigger: MVC authorization filter stage on any controller/action decorated with `SaifAuthorizeAttribute` (applied as `[SaifAuthorize]`)
---

# Authorize a request against SAIF roles

Decide whether the current user is authorized for any of the roles declared on the filter. Trigger: MVC authorization filter stage on any controller/action decorated with `SaifAuthorizeAttribute` (applied as `[SaifAuthorize]`).

| Field | Value |
| --- | --- |
| **Operation ID** | OP-09 |
| **Trigger** | MVC authorization filter stage on any controller/action decorated with `SaifAuthorizeAttribute` (applied as `[SaifAuthorize]`) |
| **Inputs** | `HttpContextBase`; `Roles` (comma-joined from the constructor); `_ForceProductionRole`; injected `IUserProfileService` and `IEnvironmentService` |
| **Outputs** | `bool` authorization decision |
| **Primary components** | `SaifAuthorizeAttribute.AuthorizeCore(HttpContextBase)` |
| **Entry point** | `src/Web.Mvc/ActionFilters/SaifAuthorizeAttribute.cs` |

## Steps

1. `Enforce.ArgumentNotNull` on `httpContext`, `UserProfileService`, and `EnvironmentService` — missing property injection fails fast ([BR-01](../business-rules.md#br-01-guarded-arguments-reject-null-or-empty-input), [BR-15](../business-rules.md#br-15-authorization-filter-requires-its-injected-services)).
2. If `Roles` is empty, return `true` — an attribute constructed with no roles authorizes everyone ([BR-16](../business-rules.md#br-16-no-roles-declared-authorizes-everyone)).
3. Resolve the current user with `UserProfileService.GetSystemUser(EnvironmentService.UserId())` and cache `user.UserId` into `_userId` for later logging.
4. If the user is null or its `UserId` is empty, return `false` ([BR-17](../business-rules.md#br-17-no-resolvable-system-user-is-denied)).
5. Strip spaces from `Roles`, split on `,`, and return `true` when any role satisfies `user.IsAuthorized(role, _ForceProductionRole)` — OR semantics across roles ([BR-18](../business-rules.md#br-18-access-granted-on-any-satisfied-role)).
   > **Origin**: Step 5's role check delegates to `IApplicationUserProfile.IsAuthorized`, owned by `SAIF.Framework.Core`† (retrieved via the Legends CLI RAG service) and executed on behalf of this operation; the underlying AD group membership evaluation itself is not visible in this repository.**

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Authorization filter stage])
	Guard[Guard httpContext/services]
	Empty{Roles empty?}
	AllowAll([Return true])
	Resolve[Resolve system user]
	NoUser{User resolvable?}
	Deny([Return false])
	AnyRole{Any role authorized?}
	Allow([Return true])
	DenyRole([Return false])
	Start --> Guard
	Guard --> Empty
	Empty -->|Yes| AllowAll
	Empty -->|No| Resolve
	Resolve --> NoUser
	NoUser -->|No| Deny
	NoUser -->|Yes| AnyRole
	AnyRole -->|Yes| Allow
	AnyRole -->|No| DenyRole
```

## Failure and edge-case behavior

- No unexpected failure paths beyond argument-guard exceptions and delegated dependency behavior were identified for this operation.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

> **Note:** Statements marked with `†` are derived from dependency library
> documentation via the Legends CLI. Statements marked with `*` were inferred
> from code structure or contextual evidence. Statements marked with `**` could
> not be confirmed; treat as unknown until verified.


## Sources
- `src/Web.Mvc/ActionFilters/SaifAuthorizeAttribute.cs`
