Claims source SPI

1. OpenID Connect claims

OpenID Connect enables client applications to retrieve claims, or assertions, about the end-user after successful login and consent. The client can receive the claims in two different ways — from the protected UserInfo endpoint (requires an acess token), or included in the issued ID token.

Example claims about a logged-in user:

{
  "sub"         : "248289761001",
  "name"        : "Jane Doe",
  "given_name"  : "Jane",
  "family_name" : "Doe",
  "email"       : "[email protected]",
  "picture"     : "http://example.com/janedoe/me.jpg"
}

2. Claims source SPI

The Connect2id server comes with a Java Service Provider Interface (SPI) for collecting claims from one or more arbitrary data sources, such as

  • Active Directory / LDAP (supported out-of-the-box)
  • SQL and NoSQL databases
  • SCIM web service
  • HR system
  • External identity and claims providers

To plug in your own connector check out the ClaimsSource and AdvancedClaimsSource SPIs defined in the Connect2id server toolkit:

https://bitbucket.org/connect2id/server-sdk

Features of the claims source SPI:

  • Provides an initialisation method, e.g. for configuration purposes.

  • Method to let the Connect2id server discover the names of the supported claims.

  • Can handle language tags (BCP47).

  • Supports all OpenID claim types:

    • normal — Claims directly asserted by the provider.

    • aggregated — Claims sourced from an external provider, made available as a signed JWT.

    • distributed — Claims which can be obtained from the endpoint of an external provider using a supplied bearer access token.
  • Enables implementations to release resources on Connect2id server shutdown.

3. Available claim source connectors

Connect2id provides two ready connectors for sourcing claims. Their code is open (Apache 2.0 licensed), so feel free to use them as a starting point if you need to build your own claims sourcing.

3.1 LDAP

An LDAP / Active Directory connector is included in Connect2id server package. Check out its configuration manual for more details.

Git repo:

https://bitbucket.org/connect2id/openid-connect-ldap-claims-source

3.2 HTTP endpoint

This connector sources claims from a protected HTTP endpoint using simple JSON over POST. It is useful when you want to delegate sourcing to a web service, or when you want to implement the claims sourcing in a language other than Java.

https://bitbucket.org/connect2id/openid-connect-http-claims-source

4. Mini how-to

4.1 Aggregated claims

How to return aggregated claims in a ClaimsSource implementation:

import java.net.*;
import java.util.*;

import com.nimbusds.jwt.*;
import com.nimbusds.oauth2.sdk.id.*;
import com.nimbusds.oauth2.sdk.token.*;
import com.nimbusds.openid.connect.provider.spi.*;
import com.nimbusds.openid.connect.provider.spi.claims.*;
import com.nimbusds.openid.connect.sdk.claims*;

UserInfo userInfo = new UserInfo(subject);

AggregatedClaims ac = new AggregatedClaims(
    // the claim names
    new HashSet<>(Arrays.asList("credit_score", "credit_plan")),
    // the claim JWT, signed by the claim provider
    SignedJWT.parse(jwt)
);

userInfo.addAggregatedClaims(ac);

4.2 Distributed claims

How to return distributed claims in a ClaimSource implementation:

import java.net.*;
import java.util.*;

import com.nimbusds.oauth2.sdk.id.*;
import com.nimbusds.oauth2.sdk.token.*;
import com.nimbusds.openid.connect.provider.spi.*;
import com.nimbusds.openid.connect.provider.spi.claims.*;
import com.nimbusds.openid.connect.sdk.claims*;

UserInfo userInfo = new UserInfo(subject);

DistributedClaims dc = new DistributedClaims(
    // the claim names
    new HashSet<>(Arrays.asList("credit_score", "credit_plan")),
    // the claim endpoint
    URI.create("https://credit-score-agency.com/claims"),
    // the token to retrieve the claims
    new BearerAccessToken("Eethahb8ci6Eidii")
);

userInfo.addDistributedClaims(dc);

4.3 Passing the UserInfo access token to upstream claims providers

The claims source may reuse the UserInfo access token to retrieve aggregated and distributed claims from upstream claims providers, if there is an agreement in place to recognise the token upstream. Requires implementation of AdvancedClaimsSource to receive the ClaimsSourceRequestContext:

import java.util.List;
import java.util.Set;

import com.nimbusds.oauth2.sdk.id.Subject;
import com.nimbusds.openid.connect.provider.spi.claims.AdvancedClaimsSource;
import com.nimbusds.openid.connect.provider.spi.claims.ClaimsSourceRequestContext;
import com.nimbusds.openid.connect.sdk.claims.UserInfo;

public class MyClaimsSource implements AdvancedClaimsSource {

    @Override
    public UserInfo getClaims(final Subject subject,
                              final Set<String> claims,
                              final List<LangTag> claimsLocales,
                              final ClaimsSourceRequestContext requestContext)
        throws Exception {

        // If the claims request was triggered by a UserInfo request the 
        // submitted and successfully validated token can be retrieved
        AccessToken userInfoToken = requestContext.getUserInfoAccessToken();

        // Pass the token to upstream providers...
    }
}

4.4 Claims source packaging

In order for your claims source to get picked by the Java ServiceLoader at Connect2id server startup:

  1. It must be packaged in a JAR.
  2. The JAR must contain a /META-INF/services/com.nimbusds.openid.connect.provider.spi.claims.ClaimsSource text file which contains a line with the full class name of your claims source SPI implementation.
  3. The must be placed in the /WEB-INF/lib folder of the Connect2id server WAR package, or in aother CLASSPATH location.

4.5 Logging

At startup the Connect2id server logs each claims source that it detects and then loads. Search for lines with the OP7101 and OP7102 codes:

2017-08-07T13:39:44,634 INFO localhost-startStop-1 MAIN - [OP7101] Loaded claims source [1]: class com.nimbusds.openid.connect.provider.spi.claims.ldap.LDAPClaimsSource
2017-08-07T13:39:44,635 INFO localhost-startStop-1 MAIN - [OP7102] Claims supported by source [1]: sub email_verified address x_employee_number name nickname phone_number_verified phone_number preferred_username given_name family_name email

To aid debugging and monitoring consider adding logging to your claims source, using the Log4j2 library which is included in the Connect2id server WAR package.

5. Receiving support

Our Connect2id support team is available if you need help with integrating a particular claims source.