Skip to content

Application security and authorization

This page documents the application-wide authorization architecture for LegalMaintenance, consolidating authorization patterns from all libraries and the front-end layer. Authentication is handled entirely by infrastructure (NTLM/AD) and is not application-level — all code receives a WindowsIdentity on the request context.

Authentication architecture

Authentication is handled entirely by infrastructure and is not part of application code. All requests arrive with a WindowsIdentity established by IIS via NTLM/Windows-integrated authentication (<authentication mode="Windows" />); the application has no code for the authentication mechanism itself.

Authorization architecture

All authorization in this application resolves to a single primitive: clsSecurityPrincipal.IsAuthorized(resourceName), supplied by the SAIF.BOF.Framework NuGet package (SAIF.Framework.Security). The web tier never names an AD group directly — it names a base resource name, and the framework appends an environment suffix (Resource in production, TestResource in non-production) before performing the AD group-membership lookup.* The clsSecurityPrincipal travels from Model.Context.SecurityPrincipal (session-held view state) → manager constructor → LegalManagerBase.SecurityPrincipal → IsAuthorized; the web tier never constructs or mutates a principal.

flowchart TD
    User[User Request] --> IIS[IIS NTLM Authentication]
    IIS --> Identity[WindowsIdentity Established]
    Identity --> Manager["LegalManagerBase-derived<br>Manager"]
    Manager --> Principal[clsSecurityPrincipal]
    Principal --> IsAuth[IsAuthorized resourceName]
    IsAuth --> AD[("Active Directory group<br>membership")]
    AD --> Result[Access Decision]

AD resource catalog

Resource name Purpose Libraries using Enforcement type
LNView Legal view-only membership; when the principal is in the group, editing is suppressed SAIF.Application.Claim.Legal Programmatic (LegalManagerBase.IsInViewOnly) — the only resource reached by LegalMaintenance web-tier code (6 call sites)
LNAdmin Legal administrator; bypasses claim conflict/exposure gating in manager retrieve logic SAIF.Application.Claim.Legal Programmatic (LegalManagerBase.IsInAdminGroup) — no direct screen call, reached transitively
LNCaseUpdate Legal case update authority SAIF.Application.Claim.Legal Programmatic (LegalManagerBase.IsInCaseUpdateGroup) — not consumed by LegalMaintenance; used by sibling LegalNet case managers
LNConflict Visibility of worker-conflict (confidential) claims SAIF.Application.Claim.Legal Programmatic (LegalManagerBase.HasLegalConflictAccess) — manager-internal, no direct screen call
LNExposure Visibility of exposure / health-issue claims SAIF.Application.Claim.Legal Programmatic (LegalManagerBase.HasLegalExposureAccess) — manager-internal, no direct screen call
ConflictClaim Claim-level conflict access token SAIF.Application.Claim Programmatic (ClaimUserAccess.ConflictAccess → UserAccess.HasAccess) — requires a claim context, which LegalMaintenance never sets
LNNoteView Legal case-note read access SAIF.Application.Claim.Legal Programmatic (clsCaseNotesManager) — LegalNet application only, not LegalMaintenance
LNUpdate Legal case-note update access SAIF.Application.Claim.Legal Programmatic (clsCaseNotesManager) — LegalNet application only
LNLCEUpdate Legal calendar-event update SAIF.Application.Claim.Legal Programmatic (clsScheduleManager) — LegalNet application only
LNDueDateUpdate Legal due-date update SAIF.Application.Claim.Legal Programmatic (clsScheduleManager) — LegalNet application only

Security enforcement summary

Layer Enforcement mechanism Count Libraries
Presentation No [SAIFAuthorize]/[SaifAuthorize] attributes found; screens display/hide toolbar state based on manager properties 0 LegalMaintenance
Business logic Programmatic IsAuthorized/HasAccess calls 10 (13 total resources in reachable hierarchy, 1 actually evaluated by web-tier code) SAIF.Application, SAIF.Application.Claim.Legal, SAIF.Application.Claim
Data access Data ownership validation 1 (confidential-claim/case gating, computed but only ConflictAccess hard-blocked) SAIF.Application.Claim, SAIF.Application.Claim.Legal
Infrastructure SOD checks 0 n/a

Authorization enforcement points

Every screen builds its manager in Page_Init with the identical two-argument pattern Model.SetActiveManager(New Manager(Model.DatabaseEnvironment, Model.Context.SecurityPrincipal)). The clsSecurityPrincipal travels Model.Context.SecurityPrincipal (session-held view state) → manager constructor → LegalManagerBase.SecurityPrincipal → IsAuthorized; the web tier never constructs or mutates a principal.

Screen File Check Guard condition Effect on evaluation True
Attorney Assignment frmAttorneyAssignment.aspx.vb Manager.IsInViewOnly Inside If Not IsPostBack, after BindObjects() DeleteButton/InsertButton/SaveButton.Enabled = False
Attorney Profile frmAttorneyProfile.aspx.vb Manager.IsInViewOnly Inside If Not IsPostBack, after Manager.GetProfiles() Delete/Insert/Save disabled
Attorney Profile frmAttorneyProfile.aspx.vb Manager.IsViewOnly Inside LoadData(), called from the Page_Load first-load branch Utilities.clsControlManager.EnablePageControl(Me, False) — disables every control on the page*, unreachable in practice (see below)
Hearing Location frmHearingLocation.aspx.vb Manager.IsInViewOnly Inside If Not IsPostBack, after LoadData() + ApplyPrefs() Delete/Insert/Save disabled
Legal Person frmLegalPerson.aspx.vb Manager.IsInViewOnly Inside If Not IsPostBack Delete/Insert/Save disabled
Other Firms frmOtherFirms.aspx.vb Manager.IsInViewOnly Inside If Not IsPostBack Delete/Insert/Save disabled
Rotation frmRotation.aspx.vb Manager.IsInViewOnly Inside If Not IsPostBack, after LoadData() Delete/Insert/Save disabled

Total enforcement points in the web project: 7 (6 × IsInViewOnly + 1 × IsViewOnly). Every IsInViewOnly block is a pure demotion of a toolbar that is set enabled immediately beforehand.

Pages with zero authorization enforcement: Default (redirect-only landing page), frmPrintPreview (streams a generated PDF; relies on the caller having already produced the report into the session model plus possession of the __SAIFPID view ID, with no resource check), SessionPing (keep-alive only), and DataHelper (see below).

frmAttorneyProfile's IsViewOnly gate reads AppManagerBase.SecurityRole, which defaults to AppSecurityRole.NoAccess and is mutated only via ClaimAppManager.OnCheckSecurity, reachable only through SetClaimContext. No LegalMaintenance code-behind calls SetClaimContext, so SecurityRole remains NoAccess for the lifetime of a LegalMaintenance manager and the whole-page lockdown on Attorney Profile never executes — it is dead code.*

DataHelper.aspx (Inherits System.Web.UI.Page, bypassing clsLegalMaintenanceAncestor) copies every Request.Form key/value into a dictionary with no filtering, resolves its manager by reading session directly via an attacker-supplied ViewID, and calls Manager.ProcessAjaxRequest(requestItems) inside a Try/Catch with an empty catch block. It performs no IsInViewOnly/IsViewOnly/resource check — a principal in the LNView group has the toolbar disabled on every screen but is not prevented from posting to this endpoint (see SEC-APP-003 below).

All enforcement is UI-only: no Save/Insert/Delete handler in the web project re-tests authorization before invoking manager mutations, and there is no fail-closed default anywhere in the web tier — the floor of the permission model is a fully enabled toolbar.

Security interfaces and contracts

Interface / contract Type Purpose Consumers
clsSecurityPrincipal.IsAuthorized(resourceName As String) As Boolean Method on SAIF.Framework.Security (SAIF.BOF.Framework NuGet package) Single primitive through which all authorization in this application resolves; the framework appends an environment suffix (Resource in production, TestResource in non-production) to the supplied base resource name before performing the AD group-membership lookup* LegalManagerBase.IsInViewOnly, LegalManagerBase.IsInAdminGroup, LegalManagerBase.IsInCaseUpdateGroup, LegalManagerBase.HasLegalConflictAccess, LegalManagerBase.HasLegalExposureAccess
LegalManagerBase.SecurityPrincipal Property (constructor-injected) Carries the clsSecurityPrincipal from Model.Context.SecurityPrincipal into manager instances; the web tier never constructs or mutates a principal All LegalManagerBase-derived managers
AppSecurityRole enum (ViewOnly, Update, NoAccess) Enum + AppManagerBase.SecurityRole property Non-AD, claim-context-driven authorization role; defaults to NoAccess and is set only via ClaimAppManager.OnCheckSecurity AppManagerBase.IsViewOnly, IsUpdateable, IsRestricted/IsAccessible
ClaimAppManager.OnCheckSecurity() / SetClaimContext(inClaimID) Method pair Would populate AppSecurityRole and claim-level access tokens (ConflictAccess, ExposureAccess, SecureClaimAccess, HealthIssueAccess) for a given claim context Not invoked by any LegalMaintenance code-behind — this application never sets a claim context
clsAttorneyTableManager.ProcessAjaxRequest(requestItems As Dictionary(Of String, String)) Method Entry point for DataHelper.aspx's unauthenticated-at-the-web-tier grid mutation dispatch DataHelper.aspx.vb
WCF SecurityService (resolved inside SAIF.BOF.Framework) External service Backing AD group-membership lookup for IsAuthorized; no endpoint URL/configuration key is present in this repository** clsSecurityPrincipal (framework-internal)

Cross-cutting authorization rules

Field Value
Statement Of the 13 AD resource names in the reachable type hierarchy, exactly one — LNView — is evaluated by LegalMaintenance screen code.
Trigger Every screen load of a LegalManagerBase-derived maintenance screen
Enforcement LegalManagerBase.IsInViewOnly checks LNView; other resources evaluated only transitively inside manager retrieve logic or unused
Enforcing libraries SAIF.Application, SAIF.Application.Claim.Legal
Outcome Toolbar disabled for LNView-authorized users; other resources have no direct enforcement point in this application
Related resources LNView, LNAdmin, LNCaseUpdate, LNConflict, LNExposure

SEC-APP-002 Confidential-claimcase gating is not active in LegalMaintenance

Field Value
Statement LegalManagerBase.OnRetrieve combines AD group membership (LNAdmin, LNConflict, LNExposure) with claim data attributes (IsWorkerConflict, IsExposure) and a database-backed per-claim override — the canonical SAIF data-level authorization pattern — but this composite gate does not fire in LegalMaintenance because no screen sets a claim context or reads CanViewClaim.
Trigger Manager retrieve logic (OnRetrieve) upon a claim-context change
Enforcement LegalManagerBase.OnRetrieve composite gate at LegalManagerBase.vb:334-355
Enforcing libraries SAIF.Application.Claim, SAIF.Application.Claim.Legal
Outcome Documented for architectural completeness; not an active enforcement path from LegalMaintenance screens
Related resources LNAdmin, LNConflict, LNExposure

SEC-APP-003 Inline AJAX grid edit has no authorization gate

Field Value
Statement DataHelper.aspx bypasses the shared page ancestor and performs no IsInViewOnly/IsViewOnly/resource check before dispatching to clsAttorneyTableManager.ProcessAjaxRequest; a principal in the LNView (view-only) group can still mutate data through this path.
Trigger Any AJAX POST issued by a maintenance-screen grid to DataHelper.aspx
Enforcement None — no resource check exists on this endpoint
Enforcing libraries SAIF.Application.Claim.Legal
Outcome View-only users can mutate attorney table data through this endpoint; exceptions are silently swallowed
Related resources LNView

SEC-APP-004 LNView semantics are inverted relative to its name

Field Value
Statement IsInViewOnly returns True when the principal is authorized for LNView, and the screens then disable editing; users in no legal group at all evaluate IsInViewOnly = False and get a fully enabled toolbar — the opposite of what a "view" permission name implies, and unconfirmed by any domain SME.*
Trigger Every screen load evaluating IsInViewOnly
Enforcement LegalManagerBase.IsInViewOnly
Enforcing libraries SAIF.Application.Claim.Legal
Outcome Users in no legal group at all receive a fully enabled toolbar rather than being locked out, contrary to a least-privilege expectation
Related resources LNView

Data-level authorization

Entity type Validation pattern Enforcement library Source
Legal case/claim (confidential) ClaimSecurity.CheckClaim(inClaim) sets ConflictAccess/ExposureAccess/HealthIssueAccess/SecureClaimAccess by testing claim attributes against the user's resource tokens; only invoked from ClaimAppManager.OnCheckSecurity, which requires SetClaimContext (not exercised by LegalMaintenance screens) SAIF.Application.Claim LegalMaintenance web application (LegalMaintenance/*.aspx.vb)

Segregation of duties

No SOD rules exist in the analyzed libraries: no class, method, or constant matching SegregationOfDuties/SOD/employee_access/menu_structure was found in LegalMaintenance or the directly-referenced SAIF.Application* projects, and the five LN* resources are tested independently and combined only with OrElse (permissive union) rather than a mutual-exclusion restriction.

Security dependencies

Dependency Type Purpose
WCF SecurityService / clsSecurityPrincipal (SAIF.BOF.Framework) External service / NuGet package Centralized AD group membership checks via IsAuthorized(<resourceName>)
Active Directory Infrastructure User/group/machine identity store
SAIF.Framework.Security NuGet package Supplies clsSecurityPrincipal and the resource-suffix convention

Notes

  • AD resource names use base names only — the framework appends Resource (production) or TestResource (non-production) at runtime.
  • The absence of any dual-control or SOD constraint on a master-data maintenance application (attorneys, firms, hearing locations, rotation assignments) is worth surfacing to a domain SME.*

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.

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

  • LegalMaintenance web application (LegalMaintenance/*.aspx.vb)