Delegation — A General Discussion

Robert Broeckelmann
10 min readFeb 6, 2021

--

palmgroove / Adedotun Ajibade

Introduction

This blog post expands on delegation and related concepts introduced in my Kerberos Delegation blog post. It also brings together two blog series I’ve been working on over the years: SAML2 vs. JWT Series and Kerberos and Windows Security Series. Delegation is a critical building block of end-to-end secure identity propagation. The concept exits in several identity protocols including Kerberos, OAuth2 Token Exchange, and WS-Trust. A weaker form of it also exists in three-legged OAuth in OAuth v2.0.

What is Delegation?

In various specifications over the years, this term has been used to describe a system’s need to take actions for a user (or on behalf of a user) independent of that user’s interactions. This can be accomplished in a variety of largely insecure ways (pass the end user’s credentials around with the request), but can be rather tricky to accomplish in a secure fashion. To do it securely will usually require underlying identity protocol support.

This support has been present in several identity protocols over years. Most notably, Kerberos, WS-Trust, and OAuth2 Token Exchange. There is also the Microsoft Kerberos concept of delegation implemented as Kerberos Extensions, which is important because it is so ubiquitous.

There are at several aspects to the concept of delegation:

  1. How the system actor authenticates itself to the IdP.
  2. How the system actor obtains a credential describing the end user.
  3. How the system actor uses that credential to perform an action.
  4. Does the delegation call to the IdP result in a singular (describes only the original user) or composite (describes actors in the call history) token?

Usage of Terms

There are different forms of delegation. In some, the IdP is aware of who the system performing delegation is. In others, the IdP has no concept of it. Even in the delegation functionality that is defined within specs, you can see both approaches. Which one is appropriate depends upon your requirements.

In that blog post, we define a couple of terms that will be useful here, including:

  • Singular Token: A token that describes a single identity (the principal being impersonated or stated another way the identity whose rights / permissions are being temporarily granted to the service requesting the token).
  • Composite Token: A token that describes both the requesting service principal and the identity whose permissions being granted. This can be the basis of an auditing purposes.
  • Delegation: A form of identity propagation wherein a service obtains a token (a composite token) that describes the service identity and the original calling user whose permissions have been delegated to that service identity. When referring to this particular concept, this blog post will use “Delegation” rather than “delegation” — notice, the case of the first letter.
  • Constrained Delegation: A form of Delegation (see definition above) that is limited in terms of which users permissions can be assumed or for which backend services a token can be scoped.
  • Impersonation: A form of identity propagation wherein a service obtains a token (a singular token) that describes just the identity whose permissions are being granted to the requesting service.
  • On-Behalf-Of: A phrase used interchangably with Delegation in this blog post.
  • Act-As: A phrase used interchangably with Impersonation in this blog post.

Note, the terms Impersonation, Delegation, Act-As, and On-Behalf-Of are used inconsistently across vendor products, protocol specifications, and blog posts. This is most likely because the identity protocol specs that define these concepts tend to have abstract definitions that are interpreted differently. What is important is the use case being described, not what name it is given.

History of Delegation

The modern concept of delegation has been developing for 40 years through the following specifications and protocols.

The Needham-Schroeder protocol forms the basis of Kerberos. Microsoft Kerberos provided extensions to extend the out-of-the-box delegation functionality of Kerberos. The WS-Trust Protocol implemented similar concepts to Kerberos with its Act-As and On-Behalf-Of semantics.

Separately, OAuth2 implements a delegated access concept that is built for a variety of use cases (traditional web application, SPAs, mobile apps, native apps, system-to-system communication). On top of this, the OAuth2 Token Exchange RFC implements Act-As and On-Behalf-Of semantics inspired by what the Microsoft Kerberos Extensions and WS-Trust specs provide.

Credential Sharing

This form of delegation isn’t particularly sophisticated. A banking info aggregation web application that asks users for their login credentials (username and password) would be an example of credential sharing. It works, but it isn’t the most secure approach because it depends upon trusting the web application with all those credentials. This type of situations was one of the original motivations for the OAuth 1.x and OAuth2 specs.

This approach to allowing a third-party application to access a resource you own is not recommended. Nor, is it particularly secure. Ten years ago, this was very common in financial information aggregation websites. Today, there is OAuth2 support or something similar available from many (but not all) banks to work these types of sites.

In this most naive implementation of delegation behavior, the original request could contain the user’s password or derived secret; however, this isn’t even remotely secure — so, we aren’t going to be doing that. I spoke with a shop a number of years ago where the same concept was implemented, but the application server was able to connect to an LDAP server and retrieve the unencrypted passwords for any end user who might interact with the services layer. Once again, not secure; we can do better — enter how delegation is implemented with Kerberos.

WS-Trust v1.4

From the WS-Trust v1.4 spec, we have:

/wst:RequestSecurityToken/wst:OnBehalfOfThis OPTIONAL element indicates that the requestor is making the request on behalf of another. The identity on whose behalf the request is being made is specified by placing a security token, <wsse:SecurityTokenReference> element, or <wsa:EndpointReference> element within the <wst:OnBehalfOf> element. The requestor MAY provide proof of possession of the key associated with the OnBehalfOf identity by including a signature in the RST security header generated using the OnBehalfOf token that signs the primary signature of the RST (i.e. endorsing supporting token concept from WS-SecurityPolicy). Additional signed supporting tokens describing the OnBehalfOf context MAY also be included within the RST security header./wst:RequestSecurityToken/wst14:ActAsThis OPTIONAL element indicates that the requested token is expected to contain information about the identity represented by the content of this element and the token requestor intends to use the returned token to act as this identity. The identity that the requestor wants to act-as is specified by placing a security token or <wsse:SecurityTokenReference> element within the <wst14:ActAs> element.

So, what does all of that mean? It means, in the WS-Trust v1.4 spec, there are two types of delegation defined: On-Behalf-Of (OBO) and Act-As. Act-As was introduced in v1.4; On-Behalf-Of. OBO results in a token being issued where the only identity described is that of the principal being impersonated (or that is being on-behalf-of). Another way of saying this is downstream actor (service/resource) that receives this token only sees information about the principal being impersonated. Act-As results in a composite token that contains identity information about the calling intermediary and the original caller who is being impersonated.

Microsoft’s further clarifies this here:

From the WS-Trust protocol standpoint:* An ActAs RST element indicates that the requestor wants a token that contains claims about two distinct entities: the requestor, and an external entity represented by the token in the ActAs element.* An OnBehalfOf RST element indicates that the requestor wants a token that contains claims only about one entity: the external entity represented by the token in the OnBehalfOf element.

Kerberos

The Kerberos v5 spec defines two delegation mechanisms: proxy tickets and forwarded tickets.

Refer to the earlier Kerberos Delegation blog post for the details.

Microsoft Kerberos Extensions

Microsoft has created two Kerberos Extensions: the Protocol Transition Extension (S4U2Self) and the Constrained Delegation Extension (S4U2Proxy).

The Protocol Transition Extension (S4U2Self) allows a trusted service to act on-behalf-of other Principals without something having provided those credentials to begin with. This allows a trusted service to authenticate a user using another identity protocol and then receive a Kerberos ticket for itself that describes the original user that is to be impersonated. This ticket can then be fed into another Kerberos call, such as S4U2Proxy to receive a ticket that describes the impersonated user for the desired service. From here, ‘The WS-Trust “ActAs” mimics the Windows Kerberos Protocol Transition (impersonation) feature as this enables an account to impersonate another account for the purpose of providing access to resources…’, but I haven’t been able to find another source to corroborate this relationship.

The Constrained Delegation Extension(S4U2Proxy) is another foundational building block of a fully-featured Identity Provider and is critical to the use cases of interest because it limits who or what can be impersonated by the service. Of course, this goes beyond what is required by the spec, but one can also see where most real-world Kerberos implementations would need something similar. From here, ‘WS-Trust “OnBehalfOf” mimics the Windows Kerberos Constrained Delegation feature, which lets you [to]limit the back-end services for which a front-end service can request tickets on behalf of another user. “OnBehalfOf” allows a selected services on a server can be granted for access by the impersonating account, whilst other services on the same server, or services on other servers are denied for access…’ but I haven’t been able to find another source to corroborate this relationship.

Refer to the earlier Kerberos Delegation blog post for the details.

OAuth2 Delegation

You’ve probably heard of OAuth2 described as a delegated access protocol before. It’s real power comes from the ability to offer control to the end user (the resource owner) of how their information (stored in the IdP or OAuth2 Provider) is used. From the spec,

OAuth2 addresses these issues by introducing an authorization layer
and separating the role of the client from that of the resource
owner. In OAuth, the client requests access to resources controlled by the resource owner and hosted by the resource server, and is issued a different set of credentials than those of the resource owner.

Instead of using the resource owner's credentials to access protected resources, the client obtains an access token -- a string denoting a specific scope, lifetime, and other access attributes. Access tokens are issued to third-party clients by an authorization server with the approval of the resource owner. The client uses the access token to access the protected resources hosted by the resource server.

The following diagram shows a typical three-legged OAuth (or Authorization Code Grant) that is common in the OAuth2 (OIDC) use cases. The delegated access part comes in where the OAuth2 client obtains an OAuth2 Access Token (Step #4) from the OAuth2 Provider and uses it to access the Resource Server (Step #5). The most important difference between this use case and the others in this blog post is that it assumes the end user is directly interacting the OAuth2 Client. There are other OAuth2 Grant Types involving a human user, the analogy is more-or-less the same. The system-to-system Client Credential Grant doesn’t fit into this model.

Three-Legged OAuth vs OAuth2 Token Exchange

The OAuth2 Access Token that is returned in step #4 may be an opaque token and simply represents the authorization that was granted to the OAuth2 Client to access the Resource Server with the permission of the user (the resource owner). The OAuth2 Provider has knowledge of who the original calling user is and what the OAuth2 Client application is. In this manner, this is similar to composite token semantics, but that information isn’t necessarily conveyed in the token directly. The Resource Server could obtain this information from the Token Introspection endpoint. Still, not quite the same as the other delegation scenarios we are exploring.

What this blog post is really concerned with is a spec-defined mechanism for a system to obtain the credentials needed to take an action of-behalf-of an end user — most likely without that user’s direct involvement in the process. This type of scenario is most applicable in B2E or B2B environments where the end user may not necessarily own the data. The last statement has numerous legal, political, and practical implications that differ by region. For now, let’s just assume that there is a need to allow a system to take an action on behalf of a user without the user’s direct involvement or consent at each turn.

OAuth2 Token Exchange RFC

The OAuth2 Token Exchange provides a mechanism for a system actor to exchange one token (possibly obtained from the client credentials grant) for another token (possibly describing permissions for actions that can be taken as an end user). From the spec:

With delegation semantics, principal A still has its own identity separate from B and it is explicitly understood that while B may have delegated some of its rights to A, any actions taken are being taken by A representing B. In a sense, A is an agent for B.When principal A impersonates principal B, A is given all the rights
that B has within some defined rights context and is indistinguishable from B in that context. Thus, when principal A impersonates principal B, then in so far as any entity receiving such a token is concerned, they are actually dealing with B. It is true that some members of the identity system might have awareness that impersonation is going on, but it is not a requirement. For all intents and purposes, when A is impersonating B, A is B.

So, what the OAuth2 Token Exchange RFC calls delegation matches up with our composite token use case from earlier. This matches the WS-Trust ActAs semantics.

What the OAuth2 Token Exchange RFC calls impersonation matches with the singular token use case from earlier. This matches the WS-Trust OBO semantics.

The high-level pattern is depicted in the earlier diagram “Three-Legged OAuth vs OAuth2 Token Exchange”

The ActAs knowledge of all system actors in the chain of delegation requests has implications for the individual calls made to the IdP. Same for OBO.

Summary

As with so many aspects of the identity topics I’ve discussed, the single, largest contributing factor to what is possible is the functionality your IdP vendor has chosen to implement and support. If your IdP does support one of these forms of delegation (impersonation), then it is more secure alternative to the use of super user accounts for accessing backend services. It only allows an API layer to perform tasks within the context of the user permissions of the original caller.

Image: palmgroove / Adedotun Ajibade

--

--

Robert Broeckelmann

My focus within Information Technology is API Management, Integration, and Identity–especially where these three intersect.