Active Directory Authentication and access
Troubleshoot the Kerberos second hop
Locate a delegation failure in first-hop authentication, S4U evidence, back-end ticket issuance, or the resource's access check.
Write down the identities before reading flags
Here’s a web-to-SQL example. Use the application’s actual identities and requested SPNs when working through it; the names below are just examples.
| Role | Example | Evidence needed |
|---|---|---|
| User | ACCOUNTS\alice |
First-hop authenticated principal and restrictions |
| Front-end URL | https://portal.contoso.com |
Actual requested name and first-hop authentication package |
| Front-end service | CONTOSO\svc-portal |
Process identity, acceptor credential identity, outbound logon session |
| Back-end service | MSSQLSvc/sql01.contoso.com:1433 |
Actual requested SPN, owning account, accepting process identity |
| Delegation policy | Traditional KCD or RBCD | Relevant account, descriptor/list, and the DC’s view |
The application must be designed to use the user’s identity on the second hop. An application choosing an explicitly configured SQL login or its own service identity will not start delegating merely because an administrator ticks a delegation box. Confirm the application’s authentication and impersonation model first. Microsoft’s Kerberos constrained delegation overview describes the services acting on behalf of the user.
Establish what happened on the first hop
A page can load successfully without Kerberos. Negotiate can select another package, and a reverse proxy can terminate one authentication context and establish another. Check the front end’s logon event and application authentication details, then the client’s ticket for the exact front-end name. Keep the connection time and requesting process with the results.
For ordinary Kerberos constrained delegation, a usable first-hop service ticket can provide the evidence for the second hop. With protocol transition, the front end asks the KDC for an S4U2Self ticket representing the user. The first hop can therefore have used a different authentication mechanism, provided the application and delegation policy support that design. First-hop NTLM is a branch in the investigation, not proof that every form of constrained delegation is impossible.
IIS adds a common identity trap: kernel-mode authentication can accept the first ticket using the machine credentials while the worker process runs as a user account. Verify the effective Windows Authentication settings and useAppPoolCredentials; do not infer the credential used from the pool name. The IIS troubleshooting reference covers this distinction. See SPNs and service identity before moving registrations.
Distinguish S4U2Self from S4U2Proxy
S4U2Self asks for a ticket to the front-end service identifying the user. Getting that ticket doesn’t grant unrestricted delegation. Check the represented user, service, realm, ticket flags and response.
S4U2Proxy asks for the back-end service using an evidence ticket in additional-tickets. In a trace, inspect the requested sname/realm, cname-in-addl-tkt option, evidence ticket’s service and flags, and RBCD indication in PA-PAC-OPTIONS. Microsoft’s S4U2Proxy request processing defines these elements. If the application never sends this request, changing the back-end ACL will not cause it to do so.
Do not treat a successful service-account klist get as an end-to-end delegation test. It asks for a ticket in the selected session’s normal identity; it does not reproduce the application’s request on Alice’s behalf. Likewise, tickets in the administrator’s desktop cache may be unrelated to the worker process.
Read-only local inspection, from an elevated prompt on the front end:
klist sessions
klist -li 0x3e7
0x3e7 selects Local System; choose the actual service LUID when different. A service cache can contain several users’ contexts, and what you can see depends on the application. If you can’t match a cached ticket to the failure, capture a short trace alongside the application logs. The klist reference documents its session selectors.
Read the policy at the KDC that made the decision
Traditional KCD’s destination list is on the front-end account. RBCD’s authorization descriptor is on the back-end service account. The protocol-transition flag and the user’s cannot-be-delegated restriction are separate controls. Use the delegation inventory to collect these settings for computer, user, and managed service accounts.
For RBCD, the KDC uses an authorization context for the requesting front-end service to evaluate the back end’s descriptor. Compare that actual service identity with the descriptor; a familiar server name in the list might belong to a different account. The MS-SFU resource-side access check specifies the decision and its error outcomes.
Record the KDC for each exchange. In another domain, the request can involve referrals and a different domain’s copy of the relevant policy. Read the account from the DC which answered, compare replication metadata if necessary, and separate “the administrator can see the new value” from “the deciding KDC has received the new value.” See trusts and referrals.
Forwardable is a security decision, not a troubleshooting bypass
Inspect the actual evidence ticket’s flags. forwardable, forwarded, and ok-as-delegate describe different properties; a service trusted for delegation does not establish that a particular user’s evidence ticket can be delegated.
The often-repeated shorthand that RBCD accepts any nonforwardable S4U2Self ticket is unsafe on current Windows. KB4577252 introduced protection affecting RBCD and Protected Users, with enforcement from March 2021 updates. Current MS-SFU product behavior qualifies the nonforwardable handling by update and enforcement state. Read the KDC’s actual error and the full ticket path. Inconsistent updates or legacy enforcement overrides can explain a result that follows one DC; disabling protection is not a supported diagnostic conclusion.
Check the user’s AccountNotDelegated state and Protected Users membership. Also check whether the front end is configured for protocol transition and whether the application requested the expected mode. Do not remove a protected administrator from its protections to establish that an application can work for ordinary users.
Branch on the last successful step
| Observation | Investigation branch |
|---|---|
| First hop uses unexpected identity/package | Client target name, proxy termination, SPN/acceptor configuration |
| No S4U request | Application credentials, impersonation support, selected code path and session |
| S4U2Self fails | User name/realm resolution, service identity, request format, KDC response |
| S4U2Self succeeds but S4U2Proxy fails | Evidence ticket, user restrictions, destination SPN, KCD list or RBCD access check |
KDC returns KDC_ERR_BADOPTION |
Capture extended status; a broad error does not identify the failed policy check |
| Back-end ticket issued but rejected | Back-end SPN owner, accepting credentials, key version and encryption support |
| Back end authenticates Alice but denies access | Resource token, group state, application mapping, database or resource permissions |
In RBCD processing, current MS-SFU differentiates a descriptor access-check failure (STATUS_NOT_FOUND) from a nonforwardable evidence restriction (STATUS_ACCOUNT_RESTRICTION) beneath the broad bad-option result. Collect the extended error when available rather than treating all 0xD responses as a missing destination entry.
Verify the resulting identity and connection
A 4769 success is evidence of issuance by the KDC, not acceptance by SQL or authorization in the database. On the back end, establish which principal authenticated, which protocol was selected, and which resource access failed. Where supported, the application or database session’s authentication information can distinguish a user context from a service-account connection.
Use a new, deliberately scoped request after a planned fix. Connection pooling can preserve an earlier authenticated connection; cached tickets and running tokens can preserve earlier authorization state. Local state changes: restarting a worker or purging tickets affects users and destroys part of the original evidence. Collect first, change only the relevant component, and make the next test identify its user, process, target name, KDC, and fresh connection.