Skip to content

Handle an unauthorized request

SaifAuthorizeAttribute.HandleUnauthorizedRequest(HttpActionContext) logs the denial (when the user is known) and answers the caller with a structured 401.

Field Value
Operation ID OP-09
Trigger Invoked by AuthorizeAttribute when Authorize a request against SAIF roles returns false.
Inputs HttpActionContext
Outputs sets actionContext.Response to 401
Primary components SaifAuthorizeAttribute.HandleUnauthorizedRequest(HttpActionContext)
Entry point src/SAIF.Web.API/SaifAuthorizeAttribute.cs

Steps

  1. Enforce.ArgumentNotNull(actionContext, "actionContext") (BR-WEBAPI-014).
  2. SAIF.Exceptions.Enforce is implemented in SAIF.Framework.Core; its internal steps could not be embedded — the package is not indexed for this run.**
  3. Resolve ILogService and IEnvironmentService from the request dependency scope; Enforce.ArgumentNotNull each (BR-WEBAPI-014).
  4. Unlike Post-process an API response, logging is mandatory here — a missing ILogService throws.
  5. user = environmentService.UserId().
  6. SAIF.Common.Extensions.UserId() is implemented in SAIF.Framework.Core; its internal steps could not be embedded — the package is not indexed for this run.**
  7. If !user.IsNullOrEmpty(), call logService.LogException(applicationName, controllerAndActionName, state: GetContext(actionContext, environmentService), exception: new SecurityException($"The user '{user}' is not authorized for this view.")) (BR-WEBAPI-018).
  8. Deliberately skipped when the user is unknown — the source comment states "user may be null before credentials are demanded", i.e. the challenge round-trip is not logged as a security event.
  9. GetContext formats the log state as User: {userId}\nPage: {requestUri} (BR-WEBAPI-018).
  10. Set actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, $"The user '{user}' is not authorized.") (BR-WEBAPI-018).
  11. Returns 401 Unauthorized (not 403), and echoes the resolved user name in the response body.

Process flow

flowchart TD
    Start([OP-08 returned false]) --> NullCheck["Enforce.ArgumentNotNull<br>checks"]
    NullCheck --> UserId["user =<br>environmentService.<br>UserId("]
    UserId --> Known{user known?}
    Known -->|Yes| LogSec["LogException(<br>SecurityException)"]
    Known -->|No| Skip[Skip logging]
    LogSec --> Response["Set 401 response with<br>message"]
    Skip --> Response

Failure and edge-case behavior

Note: Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • src/SAIF.Web.API/SaifAuthorizeAttribute.cs