SAIF.Framework.Web.Mvc security and authorization¶
This page documents authorization mechanisms implemented or consumed by this library. Authentication itself is supplied by infrastructure (NTLM/AD) and is outside the scope of this library; the analysis did not establish that all code paths receive a WindowsIdentity on the request context.* This library is a framework/provider assembly: it supplies the SaifAuthorizeAttribute enforcement mechanism that consuming applications decorate their own controllers and actions with, so almost all AD resource names enforced through it are supplied by consumers at the call site and are not present in this repository. Only one AD resource name is hard-coded here.
Authorization architecture¶
Authorization is structured as a single declarative MVC filter (SaifAuthorizeAttribute) that delegates the actual role/AD decision to a service injected via Autofac property injection, plus one standalone programmatic role check (HasGlimpseAccess) that has no callers within this repository.
flowchart TD
Caller[Controller action decorated with SaifAuthorize] --> Attr[SaifAuthorizeAttribute.AuthorizeCore]
Attr --> UserSvc[IUserProfileService.GetSystemUser]
UserSvc --> IsAuth[IApplicationUserProfile.IsAuthorized]
IsAuth --> Decision{Any role satisfied?}
Decision -->|Yes| Allow[Action proceeds]
Decision -->|No| Deny[HandleUnauthorizedRequest]
Deny --> Log[LogService.LogException SecurityException]
Deny --> Redirect["RedirectResult:<br>processerror.aspx?MSG=Not Authorized"]
AD resource catalog¶
| Resource name | Purpose | Enforcement point | Source |
|---|---|---|---|
GlimpseUser{env}Resource — resolves to GlimpseUserResource (production) or GlimpseUserTestResource (non-production) |
The confirmed check is negated: an authenticated user who is not a member of the named role currently receives access to the Glimpse diagnostics profiler UI, while a member of the role is denied. Whether this inversion is intentional could not be confirmed from this repository.** | SAIF.Web.HttpContextExtensions.HasGlimpseAccess(HttpContextBase) |
src/Web/Extensions/HttpContextExtensions.cs |
The environment suffix is computed locally by string-matching Server.MachineName.ToLower() for "prod" rather than via IEnvironmentService; a production host name that does not contain "prod" would be evaluated against the test resource name.** No other AD group, resource, or role string literal exists anywhere in this library's source. This library performs no System.DirectoryServices / PrincipalContext / DirectorySearcher / LDAP access — it is not an AD-provider library.
Authorization enforcement points¶
Attribute-based authorization¶
| Controller / Action | Attribute | Resource name(s) | Source |
|---|---|---|---|
| None in this repository — the attribute is defined here, not applied to any controller in this library. Consuming applications apply it to their own controllers/actions. | SaifAuthorizeAttribute (sealed, inherits System.Web.Mvc.AuthorizeAttribute), applied as [SaifAuthorize] |
Supplied by the consumer via SaifAuthorizeAttribute(params string[] roles) or SaifAuthorizeAttribute(bool forceProductionRole, params string[] roles) |
src/Web.Mvc/ActionFilters/SaifAuthorizeAttribute.cs |
Enforcement members inside the attribute:
| Member | Behavior | Source |
|---|---|---|
protected override bool AuthorizeCore(HttpContextBase httpContext) |
Guards httpContext, UserProfileService, EnvironmentService with Enforce.ArgumentNotNull (BR-15). Returns true immediately when Roles is empty — no roles configured means allow (BR-16). Resolves the caller with UserProfileService.GetSystemUser(EnvironmentService.UserId()); returns false when the user is null or UserId is empty (BR-17). Otherwise splits Roles on , and returns true if any role satisfies user.IsAuthorized(role, _ForceProductionRole) — OR semantics, not AND (BR-18). |
src/Web.Mvc/ActionFilters/SaifAuthorizeAttribute.cs |
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) |
Logs a SecurityException ("The user '{userId}' is not authorized for this view.") through LogService.LogException with application name, controller/action, and a context string containing the user id and full request URL (BR-19); then sets filterContext.Result to a RedirectResult to the hard-coded external error page //saifonline/weberror/processerror.aspx?MSG=Not%20Authorized (BR-20). |
src/Web.Mvc/ActionFilters/SaifAuthorizeAttribute.cs |
Roles is normalized in the constructor (string.Join(",", roles.Select(r => r.Trim()))). forceProductionRole (_ForceProductionRole) is forwarded to IApplicationUserProfile.IsAuthorized and instructs the downstream service to use the production resource name regardless of the current environment; the suffix logic itself lives in the dependency implementation, not in this repository.** The attribute's collaborators (IUserProfileService, ILogService, IEnvironmentService) are settable public properties populated by Autofac property injection via RegisterFilterProvider() / RegisterWebApiFilterProvider(GlobalConfiguration.Configuration) in AutofacExtensions.cs; if a consuming application omits that registration, AuthorizeCore throws from Enforce.ArgumentNotNull — the failure mode is fail-closed by exception.*
Programmatic authorization checks¶
| Class | Method | Resource / Role | Check type | Source |
|---|---|---|---|---|
SAIF.Web.HttpContextExtensions |
HasGlimpseAccess(HttpContextBase) |
GlimpseUser{env}Resource |
IPrincipal.IsInRole on context.User, negated |
src/Web/Extensions/HttpContextExtensions.cs |
The verbatim check is context.User != null && !context.User.IsInRole(string.Format("GlimpseUser{0}Resource", env)) — confirmed from source. The role test is negated, so a method named "has access" grants access to every authenticated caller except members of the group whose name identifies it as the Glimpse user group. Read against the SAIF <ResourceName>Resource naming convention (where the group normally enumerates users who should have the privilege), this reads as an inverted check rather than a deliberate deny-list.* HasGlimpseAccess has zero call sites within this repository — it is a public extension consumed only by downstream applications, typically from a Glimpse IRuntimePolicy/configuration hook.* Whether the inversion is intentional cannot be determined from this repository.**
Data-level authorization¶
| Entity type | Validation method | Mechanism | Source |
|---|---|---|---|
| Business Online menu items | MenuService.GetBusinessOnlineMenu(string mailId) |
Strips any DOMAIN\ prefix from mailId, then queries IRepository<BusinessOnlineMenuItem> for rows where MenuUser equals the upper-cased mail id or the literal "UNSECURED", and IsVisible == "Y" |
src/Web.Mvc/Classes/MenuService.cs |
This is menu visibility scoping driven by the menu data model, not an authorization enforcement point — it does not prevent direct navigation to a hidden page. Page-level protection still depends on SaifAuthorizeAttribute being applied by the consuming application.*
Segregation of duties¶
No segregation-of-duties types or mutually-exclusive-permission rules exist in this library.
Security interfaces and contracts¶
| Interface / Class | Role | Consumers | Source |
|---|---|---|---|
IUserProfileService, IApplicationUserProfile |
Resolves the current system user and evaluates IsAuthorized(role, forceProductionRole) |
SaifAuthorizeAttribute, MenuControllerBase (ApplicationUser.IsExternal) |
src/Web.Mvc/ActionFilters/SaifAuthorizeAttribute.cs, src/Web.Mvc/Controllers/MenuControllerBase.cs |
ILogService |
Logs unhandled exceptions and authorization denials | SaifAuthorizeAttribute.HandleUnauthorizedRequest, HandleExceptionAttribute.OnException |
src/Web.Mvc/ActionFilters/SaifAuthorizeAttribute.cs, src/Web.Mvc/ActionFilters/HandleExceptionAttribute.cs |
IEnvironmentService |
Supplies the current user id (UserId()) and configuration lookups |
SaifAuthorizeAttribute, WebContextService, AutofacExtensions |
src/Web.Mvc/ActionFilters/SaifAuthorizeAttribute.cs, src/Web/WebContextService.cs |
Inherited security¶
From IApplicationUserProfile in SAIF.Framework.Core¶
| Field | Value |
|---|---|
| Mechanism | Role/resource authorization decision via IsAuthorized(string role, bool forceProductionRole)† |
| Enforcement | The actual AD group membership evaluation and production/test resource-name suffixing happen inside this dependency method; SaifAuthorizeAttribute only supplies the role name(s) and the forceProductionRole flag† |
| Origin | SAIF.Framework.Core — IApplicationUserProfile |
| Source | Retrieved from indexed documentation via Legends CLI |
Notes¶
- Mark inferred statements with
*and unknown statements with**. Do not use bold inline confidence labels. - AD resource names listed here use base names only. The framework appends
Resource(production) orTestResource(non-production) at runtime.
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.
Related documentation¶
- Index
- Overview
- Architecture
- Dependencies
- Configuration
- Operations and processes
- Business rules
- API reference
Sources¶
src/Web.Mvc/ActionFilters/SaifAuthorizeAttribute.cssrc/Web/Extensions/HttpContextExtensions.cssrc/Web.Mvc/Classes/MenuService.cssrc/Web.Mvc/Controllers/MenuControllerBase.cssrc/Web.Mvc/Extensions/AutofacExtensions.cssrc/Web/WebContextServiceClient.cssrc/app.configsrc/SAIF.Framework.Web.Mvc.csproj