admin管理员组

文章数量:1352788

I have the following architecture:

  1. Browser requests TGT ticket
  2. Browser requests TGS ticket(sending TGT as argument of request)
  3. Browser requests WEB server and sends TGS ticket(in HTTP header )
  4. Web-server wants to request Backend Servcice(This request should be send from behalf of a user which sends request from browser(impersonation))

From codebase standpoint I have the following code: STEP 3

private val authService: AuthenticationService,
private val ticketValidator: SunJaasKerberosTicketValidator,
....
@Throws(AuthenticationException::class)
override fun authenticate(authentication: Authentication): Authentication {
    val token = (authentication as KerberosServiceRequestToken).token
    val ticketValidation = ticketValidator.validateTicket(token)
     ...
    return KerberosServiceRequestToken(
        authenticatedUser, ticketValidation,
        authenticatedUser.authorities, token,
    ).apply {
        details = authentication.getDetails()
    }
}

Speaking about step4 the idea that I need to take TGT ticket from previous step, put it to the GSS API context and pass to the backend service:

val ssoConnectionProperties = GSSAPIBindRequestProperties(null, null as String?)
    .apply {
        realm = ...
        kdcAddress = ...
        ticketCachePath = krbTgtPath
        keyTabPath = ...

        setUseKeyTab(true)
        setRequireCachedCredentials(true)
        setUseTicketCache(true)
        setEnableGSSAPIDebugging(true)
    }

val bindRequest: BindRequest = GSSAPIBindRequest(ssoConnectionProperties)
return LDAPConnection(connectionOptions, ssoKdcAddress, ldapConnectionProperties.port)

The code above is working but I have no idea how to take tgt ticket from previous step ?

I have the following architecture:

  1. Browser requests TGT ticket
  2. Browser requests TGS ticket(sending TGT as argument of request)
  3. Browser requests WEB server and sends TGS ticket(in HTTP header )
  4. Web-server wants to request Backend Servcice(This request should be send from behalf of a user which sends request from browser(impersonation))

From codebase standpoint I have the following code: STEP 3

private val authService: AuthenticationService,
private val ticketValidator: SunJaasKerberosTicketValidator,
....
@Throws(AuthenticationException::class)
override fun authenticate(authentication: Authentication): Authentication {
    val token = (authentication as KerberosServiceRequestToken).token
    val ticketValidation = ticketValidator.validateTicket(token)
     ...
    return KerberosServiceRequestToken(
        authenticatedUser, ticketValidation,
        authenticatedUser.authorities, token,
    ).apply {
        details = authentication.getDetails()
    }
}

Speaking about step4 the idea that I need to take TGT ticket from previous step, put it to the GSS API context and pass to the backend service:

val ssoConnectionProperties = GSSAPIBindRequestProperties(null, null as String?)
    .apply {
        realm = ...
        kdcAddress = ...
        ticketCachePath = krbTgtPath
        keyTabPath = ...

        setUseKeyTab(true)
        setRequireCachedCredentials(true)
        setUseTicketCache(true)
        setEnableGSSAPIDebugging(true)
    }

val bindRequest: BindRequest = GSSAPIBindRequest(ssoConnectionProperties)
return LDAPConnection(connectionOptions, ssoKdcAddress, ldapConnectionProperties.port)

The code above is working but I have no idea how to take tgt ticket from previous step ?

Share Improve this question edited Mar 31 at 22:08 gstackoverflow asked Mar 31 at 21:21 gstackoverflowgstackoverflow 36.6k138 gold badges418 silver badges785 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Your bind request already has service credentials (the keyTabPath). Do you want to bind using the service keytab or do you want to bind using the user's TGT? Choose one or the other.

In normal operation, service tickets do not contain a TGT inside them. (That's kind of the whole point of Kerberos: the reason tickets are used is so that merely authenticating to a service wouldn't give away your entire "keys to the castle" and let that service act as you.)

To get the TGT, you need to explicitly enable the unconstrained delegation feature. It is a bit risky, as your server becomes a good place for stealing everyone's credentials if someone breaks in.

The web app's account (the one holding the "HTTP" SPN) has to be marked as "Trusted for delegation to all services" in AD. Also, delegation may need to be explicitly enabled in clients (browsers); e.g. both Chrome and Firefox have an "AuthNegotiateDelegateWhitelist" policy separate from the usual "allow negotiate auth". Also, it won't work for domain admins, nor users whose machines are configured with Credential Guard.

(Also, the process is a bit slow as it causes the client to request a fresh "delegated TGT" so it should be limited to just a few specific endpoints if possible. I think Windows might cache such TGTs but Linux doesn't.)

Once enabled, the webapp has to request delegation using securityContext.requestCredDeleg(true). (Or something similar; I merely found this in the docs.)

After receiving an authenticated request, ticketValidation.getDelegationCredential() should allow you to get a GSSCredential that represents the user's delegated TGT.

(Alternatively, after validator.holdOnToGSSContext(true) you might be able to call validation.getGssContext().getDelegCred() to get the same thing.)

There are two alternative ways to authenticate as the user:

  • Constrained delegation (primarily found in AD), where your service uses S4U2Self/S4U2Proxy to craft "impersonated" tickets.

  • Protocol-specific impersonation methods, e.g. OpenLDAP (but not AD) has a concept of separate 'authentication' and 'authorization' identities so the LDAP client could bind as one user (authcid) but act as another (authzid).


TGS (ticket-granting service) is not a ticket type; it is the KDC function that issues tickets. Therefore "TGS tickets", as in tickets granted by the TGS, would be better called "service tickets". (Otherwise you would have to call the TGT an "AS ticket"...)

本文标签: kerberosIs it possible to get TGT ticket from TGSStack Overflow