Identity and access token impersonation in Connect2id server 4.0

Impersonation and delegation

The 4th major release of the Connect2id server introduces support for impersonation and delegation, two key features for tackling advanced use cases in OAuth and OpenID Connect.

  • Impersonation -- enables a privileged user to log into a client application under a different identity. May also extend to accessing protected protected resources (web APIs) as the impersonated identity and using their permissions. The Connect2id server supports impersonation by issuing ID, access and refresh tokens with a subject that differs from the currently logged-in user.

  • Delegation -- enables one user to act on behalf of another. Delegation is effectively supported by the same means - by issuing tokens that bear the identity of the delegated user as their subject.

Setting the impersonated subject in the code and implicit flows

How to impersonate or delegate a user in the code and implicit flows?

Upon detection of a privileged user at the login page, provide them with the option to log into the requesting application under a different identity. This can be implemented as a suitable UI control in the consent screen to permit selection of a target user identity to be impersonated.

If impersonation is chosen, simply add the subject identifier of the target user using the new impersonated_sub parameter of the consent object that is sent to the authorisation session endpoint of the Connect2id server.

Example: To login a privileged user as the end-user claire:

{
  "scope"            : [ "openid" ],
  "impersonated_sub" : "claire"
}

Example: To login a privileged user as the end-user claire and also obtain an impersonated access token for her for the listed email scope and its associated claims:

{
  "scope"            : [ "openid", "email" ],
  "claims"           : [ "email", "email_verified" ],
  "impersonated_sub" : "claire"
}

The Connect2id server will then proceed to issue the requested ID / access / token(s) for the impersonated user.

Maintaining an impersonated session with an OpenID client

OpenID Connect clients that have logged in an impersonated user may periodically check that the user is still logged in with the IdP by obtaining a new ID token. This may be done via a prompt=none request (the recommended method) or by simply repeating the original request.

In such cases it's important to detect any such subsequent OpenID authentication requests as following up from an original request that has gone through impersonation. If that doesn't happen the IdP will return an ID token for the original user (impersonator), and in case of incremental consent, the access / refresh token subject will also be affected.

To maintain impersonated sessions with an OpenID client continuously, the Connect2id server expects the client to make use of the optional id_token_hint parameter. This parameter is defined in the OpenID spec and has the following meaning:

id_token_hint OPTIONAL. ID Token previously issued by the Authorization Server being passed as a hint about the end-user's current or past authenticated session with the client. [...]

Example OpenID authentication request with an ID token hint:

https://openid.c2id.com/login?
    response_type=code
    &scope=openid%20email
    &client_id=000123
    &state=af0ifjsldkj
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6InMxIn0.eyJlf9Jf...

The Connect2id server will check the ID token hint for a special act claim (see next section) as an indicator whether the impersonation is being implied. If that's detected it will also notify the login page via the authentication and consent prompts (if these get invoked) by setting the impersonated_sub parameter.

This parameter is also new, and if set will specify the ID of the impersonating user.

{
  "type"             : "consent",
  "sid"              : "g6f5K6Kf6EY11zC00errCf64yLtg9lLANAcnXQk2xUE",
  "display"          : "popup",
  "impersonated_sub" : "claire",
  "sub_session"      : { ... },
  "client"           : { ... },
  "scope"            : { ... },
  "claims"           : { ... }
}

In the ideal case no additional parameter should be required to maintain an impersonated session, so we're brainstorming on a alternative way to do that. Hopefully that will become possible in a future release. Stay tuned!

Identifying impersonated ID and access tokens

How can you tell that an ID or access token is impersonated?

Tokens whose subject (end-user) is changed will bear the same attributes as regular ones, save for the act (actor) attribute which signals that there is impersonation / delegation going on.

Example JWT claims set of an impersonated ID token indicating that a privileged user admin is impersonating user claire:

{ 
  "iss" : "https://openid.c2id.com",
  "sub" : "claire",
  "aud" : "000123",
  "iat" : 1455274182,
  "exp" : 1455274782,
  "act" : { "sub" : "admin" }  
}

Example claims set of an impersonated self-contained (JWT) access token:

{ 
  "iss" : "https://openid.c2id.com",
  "sub" : "claire",
  "aud" : "000123",
  "iat" : 1455274182,
  "exp" : 1455274782,
  "scp" : [ "openid", "profile", "email" ],
  "act" : { "sub" : "admin" }  
}

The actor JWT claim is defined according to the upcoming OAuth spec for token exchange. The claims's format permits the privileged user to come from a different domain (iss). It also permits impersonation / delegation chaining:

{ 
  "iss" : "https://openid.c2id.com",
  "sub" : "claire",
  "aud" : "000123",
  "iat" : 1455274182,
  "exp" : 1455274782,
  "act" : { "iss" : "https://openid.trusted.org", 
            "sub" : "admin",
            "act" : { "iss" : "https://openid.authority.org",
                      "sub" : "superuser" } }
}

For now only the simple case - same subject domain, no nesting -- is supported. But if you have a need to handle the more complex use cases, just drop us an email and we'll consider implementing that.

Direct impersonation / delegation

The special Connect2id endpoint for obtaining ID, access and refresh tokens directly, without going through the standard flows, has also been updated to support impersonation and delegation.

Example direct authorisation request with impersonation:

POST direct-authz/rest/v2 HTTP/1.1
Host: c2id.com
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
Content-Type: application/json

{
  "sub_session"      : { "sub" : "admin" },
  "client_id"        : "8cc2043",
  "scope"            : [ "openid", "email", "profile", "app:admin" ],
  "claims"           : [ "name", "email", "email_verified" ],
  "impersonated_sub" : "claire"
}

Querying, inspecting and revoking impersonations / delegations

Once an impersonated access or refresh token is issued, it can be inspected or revoked as any other token of the same type. The Connect2id server endpoint for these purposes was extended accordingly:

  • Querying long-lived (persisted) authorisations with the actor parameter.

  • Inspecting an authorisation code, access token or refresh token that is subject to impersonation / delegation, also done via the new actor parameter.

  • Revoking impersonated / delegation authorisations and tokens.

  • New RESTful resource for listing the actors that performed impersonation or delegation.

Example request to revoke all present tokens and authorisations for an impersonating / delegating actor with the user ID admin:

POST /authz-store/rest/v2/authorizations/revocation HTTP/1.1
Host: server.example.com
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
Content-Type: application/x-www-form-urlencoded

actor=admin

Adding arbitrary data to client registrations

We also closed a long standing ticket to enable the inclusion of arbitrary data with client registrations. Just set the custom "data" parameters, using a JSON object of your choice:

POST /c2id/clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6

{
  "redirect_uris" : [ "https://myapp.example.com/callback" ],
  "data"          : { "reg_type"  : "3rd-party",
                      "approved"  : true,
                      "author_id" : 792440 }
}

The client data will then be automatically included in the consent prompt where you can use it as an input to your authorisation policy.

Note that registration of clients with data set requires extra privileges. Check out the updated client registration howto for more info.

Upgrading to 4.0.x

The new features in 4.x required changes to the underlying data structures, so the LDAP schema for the client registrations and the persisted authorisations must be updated on your servers.

Steps:

  1. Update the LDAP schemas to the latest 1.5 version. We've put together detailed instructions how to do that with OpenLDAP that requires no service downtime.

  2. Replace the /WEB-INF/oidcClientInfoMap.json configuration file which defines the mapping between JSON and LDAP attributes.

  3. Edit your existing /WEB-INF/authzStore.properties configuration:

    1. Make sure it contains the new authzStore.ldapDirectory.attributes.act property for representing actors in long-lived authorisations persisted to LDAP.
    2. Add act (actor) to the list of JWT claims to include in self-contained access tokens, unless your resource servers are not going to use this information. See the authzStore.accessToken.selfContainedClaims config docs for more info.

If you need help with upgrading, don't hesitate to get in touch with Connect2id support.

Download

To download a ZIP package of Connect2id server 4.0.1:

https://connect2id.com/assets/products/server/download/4.0.1/Connect2id-server.zip

As WAR package only:

https://connect2id.com/assets/products/server/download/4.0.1/c2id.war https://connect2id.com/assets/products/server/download/4.0.1/c2id-4.0.1.war

Note that the actual release version is 4.0.1, as we ended up including a fix for a bug that got discovered this morning just before the announcement.

Questions?

Please contact Connect2id support.


Release notes

4.0.1 (2016-02-12)

Configuration

  • /WEB-INF/oidcClientInfoMap.json

    • Corrects the entity mapping between the optional JSON object member "jwks" and the LDAP attribute "oauthJWKSet". See issue server/194 for more information.

Web API

  • No changes

Bug fixes

  • Fixes a bug that affected recreation of registered client JWK sets from persisted LDAP entries (issue server/194).

  • Prevent registration of custom client "data" parameters that are not a JSON object entity (issue server/195).

Dependencies

  • No changes

4.0 (2016-02-11)

Configuration

  • /WEB-INF/authzStore.properties

    • authzStore.accessToken.selfContainedClaims -- Adds support for an optional "act" (actor) JWT claim in issued self-contained access tokens. This claim can be used to indicate the authorised actor in impersonation (act-as) and delegation (on-behalf-of) cases. Its semantics is defined in draft-ietf-oauth-token-exchange-03, section 4.1.

    • authzStore.ldapDirectory.attributes.act -- New required configuration property to specify an LDAP attribute for representing impersonated and delegated authorisations. The LDAP attribute holds the identity of the impersonating or delegating subject (actor) and is intended to be used as part of the LDAP entry's RDN. Set to "authzActor".

  • /WEB-INF/oidcClientInfoMap.json

    • Adds a new entity mapping between the optional JSON object member "data" and the LDAP attribute "oauthClientData". See the client registration web API change log for more information.

Web API

  • /clients

    • Adds support for registering a custom "data" client metadata parameter, represented by a JSON object entity. Registration of this parameter requires the master registration token or an initial registration token with a "client-reg:data" scope.
  • /authz-sessions/rest/v2

    • Adds an optional "impersonated_sub" string parameter to the consent object representation. If set specifies a subject (end-user) to impersonate or delegate by means of the issued ID, access and refresh tokens. May be used to enable privileged users to login into clients and access protected resources under a different identity. The actual authorised subject (the impersonator) will be indicated in the custom "act" -> "sub" ID and access token (JWT) claim.

    • The optional "id_token" -> "impersonated_sub" parameter introduced in Connect2id server 3.x to enable limited ID token impersonation is deprecated in favour of the new top-level "impersonated_sub" parameter (see above).

    • Adds optional "impersonated_sub" string parameter to the authentication and consent prompt representations. If set indicates that the prompt is for a previously impersonated subject (end-user), as implied by an ID token hint submitted by the client. See the OpenID authentication request documentation for the "id_token_hint" parameter for more information.

  • /authz-store/rest/v2

    • Adds an "act" (actor) parameter to the authorisation representation to support impersonation (act-as) and delegation (on-behalf-of) cases.

    • Adds an /authz-store/rest/v2/actors resource for listing the indexed actors in long-lived (persisted) impersonated or delegated authorisations.

    • Adds support for an optional "actor" query parameter for GET requests to the /authz-store/rest/v2/authorizations resource. The "actor" query parameter can be used to retrieve impersonated and delegated authorisations using the actor as a key.

    • Adds support for an optional "actor" query parameter for POST requests to the /authz-store/rest/v2/revocation resource. The "actor" query parameter can be used to revoke impersonated and delegated authorisations using the actor as a key.

Bug fixes

  • Do not log authorisation codes, ID tokens, access tokens and refresh tokens unless at log level "TRACE" (security issue server/192).

  • Improves logging of failed client registration add, read, update and delete requests (issue server/163).

Dependencies

  • Upgrades to com.nimbusds:c2id-server-sdk:3.9

  • Upgrades to com.nimbusds:oauth2-oidc-sdk:5.5

  • Upgrades to com.nimbusds:oauth2-authz-store:4.0.1

  • Upgrades to com.nimbusds.nimbus-jose-jwt:4.12

  • Upgrades to com.nimbusds.common:1.99

Other

  • Upgrades the LDAP schema for client registrations to version 1.5:

    • Adds a new optional oauthClientData attribute for including additional client registration data formatted as a JSON object.
  • Upgrades the LDAP schema for persisted authorisations to version 1.5:

    • Adds a new optional authzActor attribute for representing impersonation and delegation cases.