Color scheme: Light
You are here: start » en » Documentation » Data integration and data access » WKL Database Gateway » Reference » Identity pass-through and database identities (reference)

Identity pass-through and database identities (reference)

Rules and responses when the service runs statements under the login of a person (Impersonate) or under an assigned shared login. The model is explained in Sign-in and identity pass-through.

Syntax

"Databases": [
  { "Name": "fachdaten", "Provider": "sqlserver", "ConnectionString": "…",
    "Persons": "Impersonate",       // Service | Impersonate; default Service
    "DenyImpersonate": [
      { "Logins": [ "sa", "CORP\\Database-Operations" ] },                 // never
      { "Roles": [ "sysadmin" ], "ExceptFrom": [ "192.168.0.0/16" ] }    // sysadmins only from the corporate network
    ] }
],
"Security": {
  "AuthMode": "ApiKey, Windows",
  "TrustedProxies": [ "10.0.0.5" ]  // X-Forwarded-For is trusted only from here
}

For this, the alias login needs the following in SQL Server:

GRANT IMPERSONATE ANY LOGIN TO [<alias login>];
-- also possible, see below: DENY IMPERSONATE ON LOGIN::[sa] TO [<alias login>];

Parameters

Pass-through rules

RuleReason
The service rules (Clients) remain an outer barrier; inside, SQL Server decidesThe service determines which aliases, resource types and verbs can be reached over HTTP at all; SQL Server knows the permissions on the individual objects
EXECUTE AS LOGIN, not EXECUTE AS USERThe person appears in SQL Server with their login, as with a direct connection—server-wide, not just in one database, and with one login per person instead of one user per person and database
EXECUTE AS with a cookie, reverted at the end of each request; if the revert fails, the alias connections are discardedA pooled connection must not carry a person's context into the next request—SQL Server terminates such a session the next time it's used, and the request that picks it up fails (596). The cookie prevents a passed-through statement from jumping back to the alias login with REVERT
ORIGINAL_LOGIN() still returns the alias loginThat's the connection that actually exists; in the SQL Server audit, this is how you recognize the service
Custom statements run with the permissions of the personas with a direct connection
The service finds the login via the SID of the Windows loginThat way it finds the login even if its name no longer matches the account. SQL Server can't switch to it, though: it resolves the stored name via Windows and fails (15404, Windows code 0x534, even as sysadmin). After you rename a Windows account, you therefore also need to rename the login: ALTER LOGIN [CORP\old] WITH NAME = [CORP\new]
A Windows account without its own login is rejected, not downgraded to ServiceA silent fallback would give it the permissions of the service account. Exception: a person with a personal key who has no SQL Server login entered runs under the alias login, with their name in the session context
If the person lacks a permission, the service responds with 403Just as SQL Server refuses it to a direct connection. Under Service, a missing permission remains 422: there it's a gap in how the service is set up, not a decision about a person
Which logins the service doesn't switch to is decided solely by the alias's DenyImpersonate list. It applies to every switch (EXECUTE AS), not to sign-in with a SQL Server login via HTTP Basic: there the service opens its own connection with name and password, and SQL Server alone decides. If you want to exclude sa there, for example, list only specific logins in SqlLogins instead of *, or block them in SQL ServerIt's in the configuration and is the one place where this is defined. It applies on every alias, including under Service: a database identity also switches to a login there. An entry names logins (name as SQL Server stores it, or SID) or server roles, plus optionally networks from which it doesn't apply (ExceptFrom) or from which alone it applies (From). Anything no entry matches is accepted as with a direct connection, even with high privileges; there's no hidden additional rule
If an entry matches, the request is rejected (403); the order doesn't matterExceptions are in the entry itself, not in separate allow entries—otherwise the result would depend on the order, which the rest of the configuration avoids for the same reason
Names and SIDs are checked before the switch, roles afterward in the new contextOnly the login's own context reliably shows its roles (IS_SRVROLEMEMBER). If a role entry matches, the switch is reverted immediately and the request rejected
The origin is the address of the peer; X-Forwarded-For counts only if it comes from an address in Security:TrustedProxiesOtherwise anyone could write an address from the own network into it. It's read starting from the nearest hop: the first address that isn't itself a trusted proxy applies—so an entry that the client adds at the front itself doesn't count. An unreadable value makes the origin unknown, and an unknown origin doesn't lift any block. IPv4 addresses in IPv6 notation (::ffff:192.168.1.5) are mapped back to IPv4. The service has no notion of “internet”, only of “outside the listed networks”
Networks are parsed strictly: an IPv4 address needs four decimal parts without leading zeros, and no bits may be set beyond the prefix length.NET reads 192.168 as 192.0.0.168, 0x7f.0.0.1 as 127.0.0.1, 017.0.0.1 as 15.0.0.1 and silently turns 192.168.1.5/16 into 192.168.0.0/16. Each of these readings would silently change what a rule covers; the startup check therefore rejects them. The rule applies equally to TrustedProxies, From, ExceptFrom, the restrictions of personal keys and setup-host --networks
Additionally possible outside the service: DENY IMPERSONATE in SQL Server for the same loginsThis holds even if the service itself is compromised: with IMPERSONATE ANY LOGIN, its login can otherwise assume any login, including a sysadmin login; the DENY blocks it

The responses to a rejection don't name a rule; which entry matched, for whom and from which origin is written as a warning to the log under the correlation ID.

Response (403)Meaning
“Für dieses Windows-Konto gibt es in SQL Server keine eigene Anmeldung.” (There's no individual SQL Server login for this Windows account.)The person has no login of their own, only access via a group, or none at all
“Diese Anmeldung darf über den Dienst nicht verwendet werden.” (This login must not be used via the service.)An entry of DenyImpersonate matches—by name, SID or role
“Der Dienst kann diese Anmeldung in SQL Server nicht annehmen.” (The service can't assume this login in SQL Server.)SQL Server refuses the switch: for example, IMPERSONATE ANY LOGIN is missing, the login is disabled, or the Windows account was renamed (15404)
“Die Datenbank verweigert dieser Anmeldung den Vorgang.” (The database refuses this operation for this login.)The person lacks a permission (error 229, 230, 262, 297, 300 or 916)

Database identities (shared logins)

In many installations, people have no permissions of their own in the database. They work through a shared login per department, such as vertrieb or marketing, whose password everyone knows. The customer decides who belongs to which login. The service maps this in the administration store: each person signs in as themselves, and the service switches to the shared login for them. Nobody needs the password of the shared login for this.

Two sets of the administration API:

SetContent
DatabaseIdentitiesFor each data source, the identities under which a request may run, each under a name that the person uses to choose it (the driver's ROLE=). The name is unique per data source. Kind determines who the request runs as: Login switches to the shared login in Login with EXECUTE AS LOGIN; Own switches to the person's own login (the Windows login of their account or the SqlLogin of their entry); Alias stays with the data source login
IdentityAssignmentsWho may assume an identity: exactly one source per row—a person (PersonId), a Windows account or a Windows group (WindowsAccount, resolved to the SID when saved) or a single personal key (KeyId)

Identity and assignment each have an Enabled switch. A person also has a default (DefaultRole in Persons).

Which identity applies—per request, as soon as the alias is known:

SituationResult
No assignment matches the sign-inThe alias's Persons setting decides
The request chooses (header X-Wkl-Role, otherwise the identity bound to the second-factor session)The chosen one, if it's assigned; otherwise 403 with the list of possible ones
Exactly one assignedthat one
Several, no choice, the person's default is among themthe default
Several, no choice, no matching default403; the response lists the possible identities in X-Wkl-Roles and in the message

An assignment matches via the person to whom the sign-in belongs (via the key or their own Windows account), via the key itself, or via the Windows account and each of its groups. Names in X-Wkl-Role and X-Wkl-Roles are percent-encoded UTF-8 (Au%C3%9Fendienst); the list is comma-separated.

RuleReason
With several identities there's no ranking; without a choice and default, the service refusesA guessed identity would run statements with permissions the person didn't choose
Every choice is checked against the assignments on every request; choosing an identity that isn't assigned is 403The choice isn't an authorization, only a selection among those granted
A service key and a SQL Server login via Basic don't assume an identity; a choice is rejectedA service key isn't a person; a SQL Server login connects as itself
DenyImpersonate applies to shared logins as to peopleThe list is the one place that takes a login out of the service's reach
The person stays visible: SESSION_CONTEXT(N'wkl.person') names them, SESSION_CONTEXT(N'wkl.role') the chosen identity, wkl.key the keyUSER_NAME() and SUSER_SNAME() return the shared login, ORIGINAL_LOGIN() the data source login. For a Windows sign-in without a person entry, wkl.person contains the account
The audit stream names both: Zugriff GET fachdaten/dbo.Auftrag durch Jane Doe (k…) als vertrieb (access GET … by Jane Doe (k…) as vertrieb)Who acted and under which identity. Rate limiting counts per caller: per personal key (not per person), per Windows account, per SQL Server login in the spelling of the request; not per identity
Assignments are looked up on every requestDisabling or deleting takes effect with the next request
A person without their own login who chooses Own is rejectedNo silent fallback to the data source login

Check on save. The service saves an enabled identity of kind Login only after a trial switch: it opens a connection of the data source, switches to the login and immediately reverts the switch. It rejects with 422 and a message for the administrator if the login is missing (or is a Windows group), if an entry of DenyImpersonate names it—on save, every entry counts, including one with a network condition –, if it's a member of a server role named there, if it has no access to the data source's database, or if SQL Server refuses the switch (for example because IMPERSONATE is missing). For this, the data source login needs the following in SQL Server:

GRANT IMPERSONATE ON LOGIN::[vertrieb] TO [<DATA SOURCE login>];   -- per shared login

The customer creates the shared logins themselves and their permissions in SQL Server; the service doesn't manage them. A shared login that people share via Basic with a common password is not recommended: the service then can't tell the people apart.

Clients. The ODBC driver for OData (Wkl.Data.OData.Odbc) chooses with the ROLE= keyword or—where the application allows a dialog—with a drop-down list that shows the list from X-Wkl-Roles. Access and DAO share a connection among all links of a process with the same DATABASE value, even if their ROLE= differs: there, the identity of the first connection applies to all these links. A second identity in the same Access session needs its own DATABASE value in its connection string; the rule is described in the driver documentation (connection keywords).

See also

en/wiki/data-conectivity/database-gateway/reference/identity.txt · Last modified: by Wolfgang van der Stille