Skip to content

SAIF.Framework.Security architecture

SAIF.Framework.Security is the framework-level security primitives layer for SAIF BOF applications. It does not own application authorization policy; instead it provides the mechanisms (clsSecurityPrincipal, Utilities.MachineSecurityService, clsAccountMaintProxy) that consuming applications use to authenticate/impersonate Windows identities and delegate authorization decisions to a centralized WCF SecurityService and, in parallel, to a legacy ASMX clsADServices AD web service. The library currently sits mid-migration between these two integration paths.

Responsibilities

  • Capture and manage the current security principal: Windows/Forms identity initialization, NTLM authentication, and impersonation (clsSecurityPrincipal, clsElevateImpersonate, SAIFCredentials).
  • Delegate resource and role authorization decisions to the centralized WCF SecurityService (clsSecurityPrincipal.IsAuthorized/IsInRole/IsAuthorizedSecurityService).
  • Provide a legacy path to the ASMX clsADServices AD web service for resource-access checks and user lookups (clsAccountMaintProxy, plus clsSecurityPrincipal.GetEmailAddress/GetIDNumber/GetDefaultPrinter).
  • Authorize machine/service accounts against AD security groups via WCF group-membership enumeration (Utilities.MachineSecurityService).
  • Resolve environment/config settings for both integration paths (AppGlobal module, EnvironmentServices\EnvironmentExtensions).
  • Provide general-purpose cryptography helpers (DPAPI, AES, MD5, X.509 certificate operations) used by login/credential flows and otherwise standalone.
  • Expose a COM-visible authorization wrapper for non-.NET/legacy Windows clients (clsSecurityPrincipalCOM).

Component boundaries

  • clsSecurityPrincipal: Core security principal wrapper — identity capture, NTLM authentication, and the primary WCF SecurityService authorization dispatch (IsAuthorized, IsInRole, IsAuthorizedSecurityService).
  • clsSecurityPrincipalCOM: COM interop boundary; delegates IsAuthorized/IsInRole calls to clsSecurityPrincipal for COM-visible Windows clients.
  • clsSecurityPrincipalCollection: Stub/placeholder collection type; holds a single clsSecurityPrincipal field with no working members — effectively a no-op/incomplete type, not part of the active interaction model.
  • clsAccountMaintProxy: Boundary to the legacy ASMX clsADServices web reference — account lookups and resource-access checks (cached/external variants).
  • Utilities.MachineSecurityService (IMachineSecurityService): Machine/service-account authorization boundary — queries WCF SecurityService.GetUsersByGroup directly and performs in-process membership matching (distinct from the boolean IsAuthorized service call used elsewhere).
  • clsElevateImpersonate / SAIFCredentials: Win32 impersonation boundary (LogonUser/DuplicateToken P/Invoke) used for explicit-credential authentication scenarios.
  • clsSAIFLoginInfo: Login orchestration boundary — authenticates via clsSecurityPrincipal, then manages Forms auth and DPAPI-encrypted "automated login" cookies.
  • AppGlobal module: Environment/config resolution boundary — lazily resolves the correct EnvironmentServiceBase (Web vs. Windows) from the SAIF.Framework.Security.EnvironmentApi project reference.
  • Cryptography\ (AES, Certificates, MD5Hash) and DAPIEncrypt.vb (DPAPI): Standalone cryptography utility boundary, consumed by login/credential flows but with no dependency on the authorization paths.
  • Service References\SecurityService\Reference.vb (auto-generated SecurityService.SecurityClient): WCF proxy boundary for the modern authorization/user-lookup path.
  • Web References\ADServices\Reference.vb (auto-generated clsADServices): ASMX proxy boundary for the legacy authorization/user-lookup path.

Interaction model

  • A consuming application obtains clsSecurityPrincipal.Instance (session-cached per HttpContext); the constructor initializes either a Forms identity (decrypted from a FormsAuthentication cookie) or a Windows identity (from Thread.CurrentPrincipal/WindowsIdentity.GetCurrent()).
  • Authorization calls (IsAuthorized, IsInRole) construct a BasicHttpBinding WCF client per call (no client instance reuse/caching) and delegate to the centralized WCF SecurityService, passing the authenticated principal's unqualified user name and a fully-qualified, environment-suffixed resource/role string.
  • Utilities.MachineSecurityService independently resolves its own WCF endpoint and calls SecurityService.GetUsersByGroup to enumerate group membership, then performs a linear case-insensitive match against the supplied machine name — this is membership enumeration, not a boolean authorization call, and fails closed (returns not-authorized) if the WCF call throws.
  • clsAccountMaintProxy and select clsSecurityPrincipal methods (GetEmailAddress, GetIDNumber, GetDefaultPrinter) instead call the legacy ASMX clsADServices proxy (HasAccess/HasAccessCache/HasAccessExternal/HasAccessCacheExternal/WhoHasAccessCache) for resource-access checks and directory lookups.
  • clsSAIFLoginInfo.Login() authenticates via clsSecurityPrincipal, then sets a DPAPI-encrypted SAIFAUTH cookie and a FormsAuthentication cookie for subsequent Forms-identity initialization.
  • This library depends on SAIF.Framework.Security.EnvironmentApi (local project reference) for all configuration/environment resolution; it has no dependency on SAIF BOF business-object base classes and does not participate in the BOF data-portal pipeline.

Architecture diagram

The following diagram shows the two parallel integration paths — the primary WCF SecurityService path and the legacy ASMX clsADServices path — both fed by the same principal/identity layer.

flowchart TD
    Consumer[Consuming application] --> Principal[clsSecurityPrincipal<br>identity + authorization]
    Consumer --> AccountProxy[clsAccountMaintProxy<br>legacy resource checks]
    Consumer --> MachineSvc[Utilities.MachineSecurityService<br>machine/service-account auth]
    Principal -->|IsAuthorized / IsInRole| WCFClient[SecurityService.SecurityClient<br>WCF proxy]
    Principal -->|GetEmailAddress / GetIDNumber / GetDefaultPrinter| ASMXClient[clsADServices<br>ASMX proxy]
    AccountProxy -->|HasAccess / HasAccessCache / WhoHasAccessCache| ASMXClient
    MachineSvc -->|GetUsersByGroup| WCFClient
    WCFClient --> SecuritySvc[WCF SecurityService<br>http://saifonline/WCF/Security]
    ASMXClient --> ADSvc[Legacy clsADServices.asmx]
    Principal --> EnvApi[AppGlobal /<br>SAIF.Framework.Security.EnvironmentApi]
    AccountProxy --> EnvApi
    MachineSvc --> EnvApi

Sequence diagram

The following diagram shows the primary resource-authorization request sequence via the WCF path.

sequenceDiagram
    participant Consumer as Consuming application
    participant Principal as clsSecurityPrincipal
    participant WCFClient as SecurityService.SecurityClient
    participant SecuritySvc as WCF SecurityService

    Consumer->>Principal: IsAuthorized(ResourceName)
    Principal->>Principal: Build Domain\ResourceName[Test]Resource
    Principal->>WCFClient: New SecurityClient(binding, endpoint)
    Principal->>WCFClient: IsAuthorized(m_UserName, RoleName)
    WCFClient->>SecuritySvc: SOAP IsAuthorized call
    SecuritySvc-->>WCFClient: authorization result
    WCFClient-->>Principal: authorization result
    Principal-->>Consumer: True/False

Design constraints

  • The two integration paths (WCF SecurityService and legacy ASMX clsADServices) reflect an in-progress migration: IsAuthorized/IsInRole/MachineSecurityService use the WCF endpoint, while clsAccountMaintProxy and clsSecurityPrincipal.GetEmailAddress/GetIDNumber/GetDefaultPrinter still use the legacy ASMX endpoint.*
  • The WCF and legacy ASMX paths use inconsistent environment-suffix conventions: the WCF path appends Resource/TestResource, while the legacy ASMX path (clsAccountMaintProxy) appends only a plain Test suffix — same intent (environment isolation), different naming format.
  • No resource/AD group names are statically defined in this library; all resource and role names are caller-supplied strings, making this a pure mechanism layer rather than a policy owner.
  • clsSecurityPrincipal constructs a new WCF BasicHttpBinding client per authorization call rather than reusing/caching a client instance.
  • Utilities.MachineSecurityService resolves its environment/config settings via a CustomEnvironmentService instance hard-coded to CustomEnvironment.Prod, distinct from the AppGlobal.EnvironmentService singleton used by clsSecurityPrincipal — the two classes also read the same logical config key under different casings (securityserviceurl vs. securityServiceUrl).*
  • Utilities.MachineSecurityService.IsAuthorized fails closed (returns not-authorized) when the underlying WCF call throws, since the exception handler only logs via Debug.WriteLine and never sets the result to found.
  • clsSecurityPrincipalCollection is a stub/placeholder type with no working members and is not part of the active interaction model.

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

  • SAIF.Framework.Security\clsSecurityPrincipal.vb
  • SAIF.Framework.Security\clsSecurityPrincipalCOM.vb
  • SAIF.Framework.Security\clsSecurityPrincipalCollection.vb
  • SAIF.Framework.Security\clsAccountMaintProxy.vb
  • SAIF.Framework.Security\clsElevateImpersonate.vb
  • SAIF.Framework.Security\SAIFCredentials.vb
  • SAIF.Framework.Security\clsSAIFLoginInfo.vb
  • SAIF.Framework.Security\AppGlobal.vb
  • SAIF.Framework.Security\Utilities\MachineSecurityService.vb
  • SAIF.Framework.Security\Utilities\IMachineSecurityService.vb
  • SAIF.Framework.Security\Service References\SecurityService\Reference.vb
  • SAIF.Framework.Security\Web References\ADServices\Reference.vb
  • SAIF.Framework.Security\app.config