---
title: SAIF.Framework.SecurityModule business rules
summary: Enumerated business rules with per-rule trigger, enforcement, and outcomes.
status: draft
owner: <owner>
last_reviewed: 2026-07-23
library: SAIF.Framework.SecurityModule
reference_type: package
---

# SAIF.Framework.SecurityModule business rules

This page captures the business rules enforced by this library's authentication pipeline. These rules govern identity establishment (authentication), not access-control decisions (authorization) — no authorization enforcement points were detected in this library.

## BR-001: Already-authenticated users are not re-processed

| Field | Value |
| --- | --- |
| **Statement** | If the current request's `IPrincipal` is already authenticated, the authentication pipeline skips re-authentication for that request. |
| **Trigger** | `HttpApplication.AuthenticateRequest` fires for every inbound request. |
| **Enforcement** | `UserAuthenticator.IsAuthenticated(user)` — returns true when `user IsNot Nothing AndAlso user.Identity.IsAuthenticated`, checked by `clsSecurityModule.AuthRequest_Handler`. |
| **Outcome** | Re-authentication is skipped and an "already authenticated" debug entry is logged; the request proceeds unchanged. |
| **Source** | `SAIF.Framework.SecurityModule\clsSecurityModule.vb`, `SAIF.Framework.SecurityModule\Authenticators\UserAuthenticator.vb` |

---

## BR-002: Host classification as external drives the authentication fallback path

| Field | Value |
| --- | --- |
| **Statement** | A request's host is classified as "external" if its name appears as a case-insensitive substring match within the `ExternalHostNames` application setting; otherwise it is classified as "internal". |
| **Trigger** | Every unauthenticated request, evaluated during authenticator selection. |
| **Enforcement** | `UserAuthenticator.Find(host, externalHostNames)` — `If(externalHostNames, "").ToUpper().Contains(host.ToUpper())`. |
| **Outcome** | Selects `ExternalUserAuthenticator` (login-page redirect fallback) or `InternalUserAuthenticator` (NTLM/Basic browser challenge fallback) when cookie authentication fails. |
| **Source** | `SAIF.Framework.SecurityModule\Authenticators\UserAuthenticator.vb` |

---

## BR-003: A decrypted SAIFAUTH cookie must contain exactly two tab-delimited fields

| Field | Value |
| --- | --- |
| **Statement** | A decrypted `SAIFAUTH` cookie value is treated as a valid username/password pair only if splitting it on the tab character (`Chr(9)`) yields exactly two non-empty segments. |
| **Trigger** | The `SAIFAUTH` request cookie is present and has been successfully DPAPI-decrypted. |
| **Enforcement** | `CookieAuthenticator.DecryptCookie` — `Splits.Length = 2` check on the decrypted string. |
| **Outcome** | On a match, the two segments are assigned as username and password and authentication proceeds; otherwise the cookie is treated as invalid, a warning is logged, and authentication falls through to the browser/login fallback. |
| **Source** | `SAIF.Framework.SecurityModule\Authenticators\CookieAuthenticator.vb` |

---

## BR-004: A failed Windows logon is treated as an authentication failure

| Field | Value |
| --- | --- |
| **Statement** | If the Win32 `LogonUser` call fails, or returns a zero token handle, the logon attempt is treated as a failure and an exception is raised. |
| **Trigger** | `TokenProvider.GetToken` is invoked with decrypted username/password credentials during cookie-based authentication. |
| **Enforcement** | `TokenProvider.LogonWindowsDomainUser` / `GetToken` — throws `Exception("Unable to login")` when `Not loggedOn Or uHandle = 0`. |
| **Outcome** | The exception propagates to `clsSecurityModule.AuthRequest_Handler`, which logs it and redirects the user to the configured error page with the exception message appended (see [BR-006](#br-006-any-unhandled-authentication-exception-redirects-to-the-error-page)). |
| **Source** | `SAIF.Framework.SecurityModule\TokenProvider.vb`, `SAIF.Framework.SecurityModule\clsSecurityModule.vb` |

---

## BR-005: Thread-abort exceptions from Response.Redirect must not be treated as authentication errors

| Field | Value |
| --- | --- |
| **Statement** | A `ThreadAbortException` raised inside the authentication handler (as a side effect of a normal `Response.Redirect` call) is suppressed rather than logged as an authentication error. |
| **Trigger** | Any `Response.Redirect` call inside the authentication flow (e.g., the external-user login redirect). |
| **Enforcement** | `clsSecurityModule.AuthRequest_Handler`'s `Catch ex As System.Threading.ThreadAbortException` branch, which calls `System.Threading.Thread.ResetAbort()`. |
| **Outcome** | The redirect completes normally without a false-positive error log entry or an unintended error-page redirect. |
| **Source** | `SAIF.Framework.SecurityModule\clsSecurityModule.vb` |

---

## BR-006: Any unhandled authentication exception redirects to the error page

| Field | Value |
| --- | --- |
| **Statement** | Any exception raised during the authentication flow that is not a `ThreadAbortException` is logged and results in the user being redirected to a configured error page with the exception message appended. |
| **Trigger** | An unhandled exception is thrown anywhere inside `AuthRequest_Handler`'s try block (for example, from [BR-004](#br-004-a-failed-windows-logon-is-treated-as-an-authentication-failure)). |
| **Enforcement** | `clsSecurityModule.AuthRequest_Handler`'s catch-all `Catch ex As Exception` handler, using the `ErrorPage` property (`sec-errorpage` setting, default `/WebError/ProcessError.aspx`). |
| **Outcome** | User is redirected to `ErrorPage & "?MSG=" & ex.Message`. |
| **Source** | `SAIF.Framework.SecurityModule\clsSecurityModule.vb` |

## Notes
- No authorization business rules (access-control, AD-group-based, or segregation-of-duties) were found in this library; all rules above govern authentication (identity establishment) only.
- No inherited business rules were identified — this library has no `<ProjectReference>` dependencies on other SAIF.Framework.* projects.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Configuration](configuration.md)
- [API reference](api/index.md)

## Sources
- `SAIF.Framework.SecurityModule\clsSecurityModule.vb`
- `SAIF.Framework.SecurityModule\Authenticators\UserAuthenticator.vb`
- `SAIF.Framework.SecurityModule\Authenticators\CookieAuthenticator.vb`
- `SAIF.Framework.SecurityModule\TokenProvider.vb`
