---
title: Authenticate inbound web request
summary: Orchestrate request-time authentication, fallback selection, and top-level error handling.
status: draft
owner: SAIF Documentation Team
last_reviewed: 2026-07-30
library: SAIF.Framework.SecurityModule
reference_type: package
operation_id: authenticate-inbound-web-request
trigger: HttpApplication.AuthenticateRequest fires for an inbound request.
---

# Authenticate inbound web request

This operation is the library's primary request-time workflow, running inside `clsSecurityModule.AuthRequest_Handler` on every ASP.NET `AuthenticateRequest` event. It short-circuits requests that already carry an authenticated principal, classifies the remaining requests as internal or external, hands each one to the matching authenticator, and normalizes redirect and error handling so downstream failures never surface as raw exceptions to the caller.

| Field | Value |
| --- | --- |
| **Operation ID** | `authenticate-inbound-web-request` |
| **Trigger** | `HttpApplication.AuthenticateRequest` fires for an inbound request. |
| **Inputs** | `sender As Object`, current `HttpContext.User`, request host, `ExternalHostNames`, `sec-errorpage` |
| **Outputs** | Request continues with an established principal, redirects to login/error, or returns a 401 challenge response |
| **Primary components** | `clsSecurityModule.AuthRequest_Handler`, `UserAuthenticator.Find`, `UserAuthenticator.IsAuthenticated` |
| **Entry point** | `SAIF.Framework.SecurityModule\clsSecurityModule.vb` |

## Steps

1. Cast `sender` to `HttpApplication`, capture the request context, and log `Begin`.
2. Read `WebContext.Context.User` and determine whether the request already carries an authenticated identity ([BR-001](../business-rules.md#br-001-already-authenticated-users-are-not-re-processed)).
   - If the user is already authenticated, log the identity name and skip the remainder of the authentication workflow — no cookie decryption, logon, or redirect logic runs.
3. For an unauthenticated request, classify the request host by calling `UserAuthenticator.Find(WebContext.Request.Url.Host, AppSettings("ExternalHostNames"))` ([BR-002](../business-rules.md#br-002-host-classification-as-external-drives-the-authentication-fallback-path)).
   - If the configured external-host list contains the request host, choose the external authenticator.
   - Otherwise, choose the internal authenticator.
4. Invoke the selected authenticator's `Authenticate(WebContext)` method.
   - The external path is [Redirect external user to login](redirect-external-user-to-login.md), which first attempts [Perform cookie-based silent re-authentication](perform-cookie-based-silent-reauthentication.md) before redirecting.
   - The internal path attempts [Perform cookie-based silent re-authentication](perform-cookie-based-silent-reauthentication.md) directly, then falls back to [Issue browser credential challenge](issue-browser-credential-challenge.md) when silent authentication does not succeed.
5. If the downstream authenticator's redirect aborts the current thread, catch the resulting `ThreadAbortException` and call `Thread.ResetAbort()` so the redirect is treated as expected control flow rather than an authentication failure ([BR-005](../business-rules.md#br-005-thread-abort-exceptions-from-response-redirect-must-not-be-treated-as-authentication-errors)).
6. If any other exception escapes the authentication flow, write it to `Log.Error` and redirect the response to `ErrorPage & "?MSG=" & ex.Message` ([BR-006](../business-rules.md#br-006-any-unhandled-authentication-exception-redirects-to-the-error-page)).
   - On failure: the error-page redirect itself can raise a `ThreadAbortException`; that exception is caught by the preceding branch on the next unwind of the call stack, not treated as a second failure.
7. In `Finally`, log `End` before returning control to the ASP.NET pipeline.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([AuthenticateRequest]) --> S1[Log begin and read current user]
	S1 --> D1{Already authenticated?}
	D1 -->|Yes| EndOk([Request proceeds unchanged])
	D1 -->|No| S2[Classify host]
	S2 --> D2{External host?}
	D2 -->|Yes| S3[Run external authenticator]
	D2 -->|No| S4[Run internal authenticator]
	S3 --> EndOk
	S4 --> EndOk
	S3 -. exception .-> Err([Redirect to error page])
	S4 -. exception .-> Err
```

## Failure and edge-case behavior

- Already-authenticated requests generate only a debug log entry; they never re-run cookie decryption, Windows logon, or browser-challenge logic ([BR-001](../business-rules.md#br-001-already-authenticated-users-are-not-re-processed)).
- The redirect-based fallbacks intentionally trigger `ThreadAbortException` as a side effect of `Response.Redirect`; this operation suppresses that specific exception so it never becomes an unintended error-page redirect ([BR-005](../business-rules.md#br-005-thread-abort-exceptions-from-response-redirect-must-not-be-treated-as-authentication-errors)).
- Any other exception raised anywhere in downstream authentication — including a failed Windows logon — is converted into an error-page redirect with the exception message appended to the query string ([BR-006](../business-rules.md#br-006-any-unhandled-authentication-exception-redirects-to-the-error-page)).

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

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