Skip to content

SAIF.NetCore.DBConnectionClient security and authorization

This page documents the outbound authentication behavior of SAIF.NetCore.DBConnectionClient and how it reacts to server-side authorization decisions. The library defines no AD resources, roles, or authorization-decision logic of its own — all authorization of secret access is delegated to the remote DBConnectionAPI, which is outside this repository.

Authorization architecture

Authorization is delegated entirely to a remote service: access to a given connection string is decided by the DBConnectionAPI based on the NTLM identity this library presents. The library is a pure consumer of that decision — it chooses which credential to present, then reacts to the API's 401/403/404 responses. It implements no IsAuthorized, IsInRole, HasAccess, or CheckAccess logic, and has no controllers, endpoints, or attribute-based enforcement surface.

flowchart TD
    Setup["ConnectionClient.Setup()<br>SetNtlmAuthentication() — process identity"] --> Request["Get*Connection call"]
    Creds["ConnectionClient.SetupClientCredentials(username, password)<br>(called by ServiceExtensions)"] --> Request
    Request -->|GetAsync with NTLM identity| API["DBConnectionAPI<br>(external HTTP service)"]
    API -->|200 success| Return([Return connection string])
    API -->|401 / 403 / 404| Deny(["DBClientException, fail fast, no retry"])

AD resource catalog

The library references no AD groups or resource names*. The only security principal involved is the Windows service account presented over NTLM; its name and password are not in the repository and are supplied at runtime.

Resource / principal Context Enforcement point Source
Service account (NTLM identity, name not in repo) The Windows identity presented to the DBConnectionAPI; the API decides whether that identity may read a given connection string server-side** Presented by ConnectionClient.Setup (process identity) or ConnectionClient.SetupClientCredentials (explicit credentials) src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs
Secure setting connectionservicecreds / section dbconnectionclient Stores the service-account credential as one username\|password string, unlocked with a system hash computed over the ConnectionClient assembly SAIF.NetCore.ServiceExtensions.IServiceCollectionExtensions.RegisterDBConnectionClient (consumer code, not this library) src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs

Authorization enforcement points

Programmatic authorization checks

No programmatic authorization-decision checks exist in this library — it never decides whether a caller may access something*. The following points instead document credential presentation (outbound caller identity) and reaction to server-side authorization outcomes:

Class Method Behavior Source
ConnectionClient Setup() Calls SetNtlmAuthentication() with no arguments — NTLM using the current process (app-pool / service) account. src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs:56-64
ConnectionClient SetupClientCredentials(string username, string password) Calls SetNtlmAuthentication(username, password), replacing the process identity with an explicit service-account credential; neither argument is validated. src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs:71-74
ConnectionClient Setup() → SetClientInfo(ServiceUrl, "DBConnectionClient", ApplicationHost, ApplicationName) Sets identification headers (Client-User, Client-Name, Application-Id) — identification, not credentials; whether the API uses them for authorization is unknown**. src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs:62
ConnectionClient RetrieveConnectionString On HTTP 401: throws DBClientException "Failed to retrieve database connection string due to 401 error - denied access: {connectionName}" with no retry. src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs:94-116
ConnectionClient RetrieveConnectionString On HTTP 403: throws DBClientException "Access denied retrieving the database connection string" with no retry. src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs:94-120
ConnectionClient GetCachedConnectionString A 401/403 exception means _connections.Add is never reached, so denials are not cached; a later call for the same key hits the API again. src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs:203-216

Both Setup and SetupClientCredentials are virtual, so a subclass can change or skip credential setup. The 401 and 403 messages include only the connection name — never the server's ErrorMessage, the connection string, or the credential. ConnectionClient's own outer retry loop (see Retrieve with retry) never retries a 401/403 itself, so this library does not amplify a denial by re-issuing the same outer request. This is not an end-to-end guarantee, though: when the standard HttpJsonClient implementation (SAIF.NetCore.HttpClients) is registered, its independent inner retry policy defaults to retrying on HTTP 401 (along with 502/503) and re-presents the same NTLM credentials for up to three further inner attempts before this library's outer step ever observes the final result, so a single outer 401 can still correspond to multiple authentication attempts against the server beneath this operation.

Security interfaces and contracts

Interface / Class Role Consumers Source
IDBConnectionClient (ServiceContracts) Contract implemented by ConnectionClient; its XML doc states the deployment requirement that the application must use a service account in IIS to retrieve SQL and Oracle connection strings. ConnectionClient src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/IDBConnectionClient.cs
IHttpJsonClient (ServiceContracts) Exposes SetClientInfo and the SetNtlmAuthentication overloads this library calls to present credentials. ConnectionClient src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/IHttpJsonClient.cs

Notes

  • Database connection strings, which probably include passwords, stay in managed memory as plain strings with no expiry or invalidation; a memory dump of the host process would expose them*.
  • The service-account password travels as a plain string, not SecureString/NetworkCredential, and remains in memory as long as the HTTP client keeps it*.
  • Transport security (HTTP vs. HTTPS) is not enforced by this library; ServiceUrl comes from configuration and is not checked**.
  • Database-secret rotation on the server side is not reflected until the cached entry is refreshed, which requires replacing the ConnectionClient instance — restarting the usual singleton-hosted process is the typical way to do this. Rotating the outbound NTLM service-account credential is a separate concern: it changes the identity presented on the next uncached request but does not itself clear any already-cached connection string*.

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

  • src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs
  • src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ClientException.cs
  • src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/IDBConnectionClient.cs
  • src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/IHttpJsonClient.cs
  • src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/HttpClientOptions.cs (default RetryOnStatusCodes includes 401)
  • src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs (ExecuteRestCall — inner retry-on-401 detail reached when the standard IHttpJsonClient implementation is registered)
  • src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs