Connect2id server 8.0

The start of 2020 marks eight years since the inception of the Connect2id server and, coincidentally or not, the arrival of its 8th major release. Here are the highlights.

PAR

Pushed Authorisation Requests (PAR) is a new spec from the OAuth WG which matured quickly to useful completeness and its PAR endpoint is now implemented by the Connect2id server.

OAuth 2.0 clients, including OpenID relying parties, can post an authorisation request to the PAR endpoint to obtain a request_uri handle for it, which the client then uses to complete the request at the authorisation endpoint in the usual way.

What are the benefits of submitting the authorisation request parameters directly to the Connect2id server?

  • Frees applications from potential browser limitations on URL size which can matter with complex authorisations. Previously, in order to work around that clients' only option was request JWTs passed by URI (request_uri). PAR makes it possible to "store" the request on the Connect2id server.

  • The authorisation parameters are no longer exposed to the browser, end-user, web server logs, etc.

  • Confidential clients get authenticated up-front and the authorisation request validity is checked before triggering a front-end redirection to the authorisation endpoint for login and consent. If necessary additional checks on the authorisation request can be performed at the PAR endpoint.

Example posting of an authorisation request to the PAR endpoint for a client registered for basic authentication:

POST /par HTTP/1.1
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

response_type=code
&scope=openid%20email
&client_id=fcb5e4f1
&state=af0ifjsldkj
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb

On success the PAR endpoint returns an opaque URI handle for the request plus an indication when it's going to expire:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

{
  "request_uri" : "urn:ietf:params:oauth:request_uri:OsL1Z3VqIxAT9R77wB7KCw.5-cQUNt9DygE4XxnYjysnw",
  "expires_in"  : 60
}

The client completes the authorisation request by passing the request_uri handle to the authorisation endpoint, as if it was a regular request object (JWT) passed by URL - no other parameters are required!

GET /login?request_uri=urn%3Aietf%3Aparams%3Aoauth%3Arequest_uri%3A... HTTP/1.1

PAR is simple to use, give it a try!

OpenID Connect eKYC / Identity Assurance

Providers of verified identities, for know-you-customer (KYC) compliance or general identity assurance, should look at the new extension that is being developed at a working group inaugurated in the first days of January at the OpenID Foundation.

The extension defines a JSON schema for requesting verified claims via the standard claims OpenID authentication request parameter and returning them in a specially designated container in UserInfo responses or in ID tokens.

Example UserInfo response with verified claims and metadata explaining the actual verification, based on methods such as ID document (paper or electronic), utility bill or qualified electronic signature (eIDAS):

{
  "sub"             : "478e4589-0145-42e2-a54e-bc291f9c7af3",
  "verified_claims" : {
    "verification" : {
       "trust_framework"      : "eidas_ial_high",
       "time"                 : "2020-01-08T12:12:59+02:00",
       "verification_process" : "6994ca5a-3615-4347-9062-c9037d847d3b",
    },
    "claims"       : {
      "given_name"  : "Alice",
      "family_name" : "Adams",
      "birthdate"   : "1987-12-01"
    }
  }
}

Check out our guide how to configure your Connect2id server for delivering verified claims in this format.

New JWT profiles for access tokens

The default JWT codec for access tokens can now mint them in three different profiles:

  • c2id-1.1 -- Connect2id server specific profile, available since v7.17, with the JWT "typ" (type) header set to "at+jwt". This is the default profile.

  • c2id-1.0 -- Connect2id server specific profile, available since v1.0, outputs identical JWT claims as c2id-1.1 but doesn't set the JWT "typ" (type) header.

  • oauth-1.0 -- Standard profile in development at the OAuth working group.

Set the authzStore.accessToken.codec.jwt.profile configuration property to switch to a profile other than the default c2id-1.1. The standard profile (oauth-1.0) being developed by the OAuth WG is a sensible alternative, but bear in mind that breaking changes to it are possible before it becomes an RFC (we are going to version them though).

Sample JWT for an access token minted in the oauth profile.

Header:

{
  "alg" : "RS256",
  "typ" : "at+jwt",
  "kid" : "CXup"
}

Claims:

{
  "iss"       : "https://c2id.com",
  "sub"       : "alice",
  "aud"       : "https://c2id.com",
  "iat"       : 1579272283,
  "exp"       : 1579272883,
  "jti"       : "BLk7RoQCVKA",
  "client_id" : "000123",
  "scope"     : "openid email",
  "clm"       : [ "!Bg" ],
  "uip"       : { "groups": [ "admin", "audit" ] }
}

Feeding OpenID claims into the access token

Thanks to a clever customer suggestion it is now possible to feed arbitrary consented OpenID claims from a configured claims source into the issued access tokens, for consumption by resource servers / web APIs. To do that simply prefix the claim name with access_token: when submitting consent to the Connect2id server during an authorisation session. This works for all supported OAuth 2.0 grants, not just for authorisation code and implicit.

To feed a patientId claim into the token while letting the rest be delivered by the default method - the UserInfo response:

{
  "scope"  : [ "openid", "email" ],
  "claims" : [ "access_token:patientId", "email", "email_verified" ]
}

If the access token is self-contained (JWT) the patientId claim will be added as a top-level claim with the same name. If the access token is identifier-based the patientId claim will appear as top-level claim in the token introspection response.

Example JWT claims for an access token with patientId:

{
  "iss"       : "https://c2id.com",
  "sub"       : "alice",
  "aud"       : "https://c2id.com",
  "iat"       : 1579272283,
  "exp"       : 1579272883,
  "jti"       : "BLk7RoQCVKA",
  "client_id" : "000123",
  "scope"     : "openid email",
  "clm"       : [ "!Bg" ],
  "uip"       : { "groups": [ "admin", "audit" ] },
  "patientId" : "p041193"
}

Two additional prefixes are supported:

  • access_token:uip: -- Causes the OpenID claim to be merged into the top-level "uip" (optional preset UserInfo claims) JSON object claim.

  • access_token:dat: -- Causes the OpenID claim to be merged into the top-level "dat" (optional data) JSON object claim.

If the claim name clashes with an existing top-level access token claim it will be ignored and not fed into the access token.

Certified OpenID Connect session management and logout profiles

The OpenID Foundation recently piloted a conformance suite for the three OpenID Connect profiles for session management and logout. In December the Connect2id server (v7.18.1) obtained certification for them.

Upgrading to 8.0

Upgrading to Connect2id server 8.0 requires the addition of a new JSON Web Key (JWK) to the server key set and may also require an update to the backend database schema, depending on its type.

New refresh-token-encrypt JWK

Newly issued refresh tokens will have an additional layer of encryption to protect certain token metadata. For that a new AES JWK with kid (key ID) "refresh-token-encrypt" must be present in the server JWK set. You can create one with the updated generator.

To extract the refresh token encryption key from the generated JWK set with help of the jq utility:

cat jwkSet.json | jq '.keys[] | select(.kid=="refresh-token-encrypt")'

Backend database

Identifier-based access tokens will now be persisted in hashed form. The measure is intended to prevent token leakage if the database or a database backup is exposed and the HMAC key of the Connect2id server to attach an authenticity and integrity code to each token identifier is also compromised. Previously the only protection against undetected token identifier leaks from the database or a backup was the HMAC key remaining secret.

To facilitate this and other changes to persisted access tokens the Infinispan data structure for them was updated and so was the database schema, depending on database type.

  • SQL databases -- The Connect2id server will automatically detect if the schema for the "id_access_tokens" table needs updating and will add the required new columns.

  • AWS DynamoDB -- Schema-less, no changes necessary.

  • LDAP -- Manual schema update required, see the release notes for detailed instructions.

  • Redis -- The new access tokens will be simply stored in a different bucket (14) instead of the old one (4) to prevent corruption.

When upgrading to Connect2id server 8.0 if there are existing identifier-based access tokens in the database issued by a older Connect2id server version the authzStore.options.legacyPlainKeysInStorage configuration property can be set to true to enable their successful introspection, otherwise they will be deemed invalid. Note that enabling this configuration imposes imposes additional database reads and a performance penalty during introspection.

Download

To download a ZIP package of Connect2id server 8.0:

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

SHA-256: 0543d751b1a85b8d7bf02c3f58c6008804bd9a96155f31364b9e2603cd0333b1

As WAR package only:

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

SHA-256: d3c85bfbe619b0efa5293a9609eb11a273554497b99f94234e6e66df8e45258c

Questions?

Contact Connect2id support.


Release notes

8.0 (2020-01-01)

Summary

  • Supports OAuth 2.0 Pushed Authorization Requests. See https://tools.ietf.org/html/draft-ietf-oauth-par-00

  • Supports OpenID Connect for Identity Assurance 1.0 (draft 08). See https://openid.net/specs/openid-connect-4-identity-assurance-1_0.html

  • The default self-contained (JWT) access token codec implementing the SelfContainedAccessTokenClaimsCodec SPI now supports multiple JWT profiles:

    • c2id-1.1 -- Connect2id server specific profile, available since v7.17, with the JWT "typ" (type) header set to "at+jwt".

    • c2id-1.0 -- Connect2id server specific profile, available since v1.0, outputs identical JWT claims as c2id-1.1 but doesn't set the JWT "typ" (type) header.

    • oauth-1.0 -- Standard profile in development at the OAuth working group, see draft-ietf-oauth-access-token-jwt-03

    The active JWT profile for access tokens is selected by a new optional "authzStore.accessToken.codec.jwt.profile" configuration property.

  • Consented OpenID claims can now be fed into the access token by prefixing their name with "access_token:". For example, "access_token:email" will cause the "email" claim to be retrieved from the configured OpenID claims source and fed into each access token for the given OAuth 2.0 grant. If the access token is self-contained (JWT) the "email" claim will be added as a top-level claim with the same name. If the access token is identifier-based the "email" claim will appear as top-level claim in the token introspection response.

    Two additional prefixes are supported:

    • "access_token:uip:" -- Causes the OpenID claim to be merged into the top-level "uip" (optional preset UserInfo claims) JSON object claim.

    • "access_token:dat:" -- Causes the OpenID claim to be merged into the top-level "dat" (optional data) JSON object claim.

    If the claim name clashes with an existing top-level access token claim it will be ignored and not fed into the access token.

  • Identifier-based (or key-based) access tokens are now stored in hashed form (SHA-256 truncated to 128 bits) to prevent token leakage if the database or a database backup is exposed and the HMAC SHA-256 key (the Connect2id server JWK with key ID "hmac") to attach an authenticity and integrity code to each token identifier is also compromised. Previously the only protection against undetected token identifier leaks from the database or a backup was the HMAC SHA-256 key remaining secret.

    When upgrading to Connect2id server 8.0 if there are existing identifier-based access tokens in the database issued by a previous Connect2id server version the "authzStore.options.legacyPlainKeysInStorage" configuration property can be set to true to enable their successful introspection, otherwise they will be deemed invalid.

  • Upgrades the Infinispan and backend database schemas for the identifier-based access tokens.

    On startup the Connect2id server will automatically create the new required "id_access_tokens" table columns for a relational MySQL, PostgreSQL and Microsoft SQL Server databases.

    Connect2id server deployments with an LDAP v3 backend database (such as OpenLDAP or OpenDJ) need to update the LDAP schema manually to version 1.10 see https://bitbucket.org/connect2id/server-ldap-schemas/src/1.10/ , the OpenLDAP schema diff https://bitbucket.org/connect2id/server-ldap-schemas/diff/src/main/resources/ oidc-authz-schema-openldap.ldif?at=1.10 &diff1=d9599b598753ec3037b784b29baeac0e28bf7615 &diff2=49115daf531b48c2d9fd0f766721d84c28576eae and the OpenDJ schema diff https://bitbucket.org/connect2id/server-ldap-schemas/diff/src/main/resources/ oidc-authz-schema-opendj.ldif?at=1.10 &diff1=d9599b598753ec3037b784b29baeac0e28bf7615 &diff2=49115daf531b48c2d9fd0f766721d84c28576eae

    Connect2id server deployments with a DynamoDB database are essentially schema-less.

    Connect2id server deployments with Redis as the primary in-memory and caching store use a new bucket (database) with number 14 to store tokens in the new format. Cached tokens in the old format in Redis bucket 4 will remain there until they expire.

  • Introduces a new AES JSON Web Key (JWK) in the Connect2id server JWK set for encrypting and authenticating refresh tokens without the need for a database lookup. The encryption will also enable the inclusion of additional metadata and the implementation of advanced security measures in future Connect2id server versions. Existing refresh tokens without the additional encryption layer will continue to be valid and will be handled transparently.

Configuration

  • /WEB-INF/jwkSet.json

    • Introduces a new AES 256 bit octet sequence JWK with use "enc" (encryption) and ID "refresh-token-encrypt" for encrypting issued refresh tokens. This key is required, starting from Connect2id server 8.0.
  • /WEB-INF/oidcProvider.properties

    • New "op.par.lifetime" configuration property which sets the lifetime of the pushed authorisation requests (PAR), in seconds. Must not be shorter than 10 seconds. The default value is 60 seconds.

    • New "op.authz.includeRawClaimsRequestInPrompt" configuration property which enables / disables inclusion of the raw OpenID "claims" request parameter in the consent prompts of the authorisation session web API, under "claims" -> "raw_request". Access to the raw "claims" request parameter may be required when processing requests for verified claims (OpenID Connect for Identity Assurance 1.0). The default values is false (disabled).

    • New "op.assurance.supportsVerifiedClaims" configuration property which enables / disables advertisement of OpenID Connect for Identity Assurance 1.0 support in OpenID provider metadata and inclusion of the optional transaction specific "purpose" OpenID authentication parameter in the consent prompts of the authorisation session web API. Corresponds to the "verified_claims_supported" OpenID provider metadata parameter. The default values is false (disabled).

    • New "op.assurance.supportedTrustFrameworks" configuration property. Lists the supported trust frameworks if OpenID Connect for Identity Assurance 1.0 support is enabled. Corresponds to the "trust_frameworks_supported" OpenID provider metadata parameter.

    • New "op.assurance.supportedIdentityEvidenceTypes" configuration property. Lists the supported identity evidence types if OpenID Connect for Identity Assurance 1.0 support is enabled. Corresponds to the "evidence_supported" OpenID provider metadata parameter.

    • New "op.assurance.supportedIDDocumentTypes" configuration property. Lists the supported ID document types if OpenID Connect for Identity Assurance 1.0 support is enabled. Corresponds to the "id_documents_supported" OpenID provider metadata parameter.

    • New "op.assurance.supportedIdentityVerificationMethods" configuration property. Lists the supported identity verification methods if OpenID Connect for Identity Assurance 1.0 support is enabled. Corresponds to the "id_documents_verification_methods_supported" OpenID provider metadata parameter.

    • New "op.assurance.supportedVerifiedClaims" configuration property. Lists the supported verified claims if OpenID Connect for Identity Assurance 1.0 support is enabled. Corresponds to the "claims_in_verified_claims_supported" OpenID provider metadata parameter.

  • /WEB-INF/authzStore.properties

    • New "authzStore.accessToken.codec.jwt.profile" configuration property. Sets the JWT profile to use for access tokens minted by the default self-contained access token codec. See the SelfContainedAccessTokenClaimsCodec SPI JavaDoc for more information.

      Supported profiles:

      • c2id-1.1 -- Connect2id server specific profile, available since v7.17, with the JWT "typ" (type) header set to "at+jwt".

      • c2id-1.0 -- Connect2id server specific profile, available since v1.0, outputs identical JWT claims as c2id-1.1 but doesn't set the JWT "typ" (type) header.

      • oauth-1.0 -- Standard profile in development at the OAuth working group, see draft-ietf-oauth-access-token-jwt-03

      The default value is c2id-1.1.

    • New "authzStore.options.legacyPlainKeysInStorage" configuration property. If true the Connect2id server will support retrieval of legacy plain keys for identifier-based access tokens from storage after upgrading to Connect2id server 8.x, false to ignore such keys which will cause the introspection of the linked access tokens to flag them as invalid. Note that enabling this configuration causes additional database reads and a performance penalty during introspection. The default value is false (no support for legacy plain access token keys).

  • /WEB-INF/log4j.xml

    • The root logger level ("INFO") can now be overridden by setting the "log4j.level" Java system property.
  • /WEB-INF/infinispan-*.xml

    • Updates the data structure for the identifier-based access tokens, which is now named "authzStore.idAccessTokenMap".
  • /WEB-INF/infinispan-*-redis-*.xml

    • Deployments using Redis as primary caching and in-memory store will use a new bucket with number 14 for the identifier-based access tokens. Cached tokens in the old format in Redis bucket 4 will remain there until they expire.

Web API

  • /par

    • New endpoint for receiving back-channel OAuth 2.0 authorisation and OpenID authentication requests, also called Pushed Authorization Requests (PAR). Confidential clients must authenticate with the same registered method as for the token endpoint. The complete specification is at https://tools.ietf.org/html/draft-ietf-oauth-par-00
  • /authz-sessions/rest/v3/

    • If op.authz.includeRawClaimsRequestInPrompt=true the raw OpenID "claims" request parameter will be included in the consent prompt API responses (as JSON object member "claims" -> "raw_request").

    • If OpenID Connect for Identity Assurance 1.0 is enabled (op.assurance.supportsVerifiedClaims=true) and the OpenID authentication request includes the transaction specific purpose parameter, the parameter will be included in the consent prompt API responses (as JSON object member purpose).

    • The "claims" parameter of the consent objects enables OpenID claims to be fed into the access token by prefixing their name with "access_token:". For example, "access_token:email" will cause the "email" claim to be retrieved from the configured OpenID claims source and fed into each access token for the given OAuth 2.0 grant. If the access token is self-contained (JWT) the "email" claim will be added as a top-level claim with the same name. If the access token is identifier-based the "email" claim will appear as top-level claim in the token introspection response.

      Two additional prefixes are supported:

      • "access_token:uip:" -- Causes the OpenID claim to be merged into the top-level "uip" (optional preset UserInfo claims) JSON object claim.

      • "access_token:dat:" -- Causes the OpenID claim to be merged into the top-level "dat" (optional data) JSON object claim.

      If the claim name clashes with an existing top-level access token claim it will be ignored and not fed into the access token.

  • /monitor/v1/metrics

    • Adds new meters for the Pushed Authorisation Request (PAR) endpoint:

      • "parEndpoint.successfulRequests" -- Meters successful PAR requests.

      • "parEndpoint.invalidRequests" -- Meters invalid PAR requests.

      • "parEndpoint.invalidClientErrors" -- Meters "invalid_client" errors at the PAR endpoint.

      • "parEndpoint.serverErrors", serverErrors -- Meters server errors (HTTP 500) at the PAR endpoint.

SPI

Upgrades the Connect2id server SDK to com.nimbusds:c2id-server-sdk:4.12

  • com.nimbusds.openid.connect.provider.spi.par.PARValidator

    • New SPI for performing additional validation of received Pushed Authorisation Requests (PAR). See https://www.javadoc.io/doc/com.nimbusds/c2id-server-sdk/4.12/ com/nimbusds/openid/connect/provider/spi/par/PARValidator.html
  • com.nimbusds.openid.connect.provider.spi.tokens

    • The self-contained and identifier-based access token codecs can now be configured via Connect2id server properties which are obtained by calling the TokenCodecContext.getCodecProperties method, for example to enable support of multiple token profiles.

    • The self-contained access token codec interface (SelfContainedAccessTokenClaimsCodec) is extended with new advancedEncode and advancedDecode methods to enable setting and validation of the JWT "typ" (type) header.

    • The AccessTokenAuthorization interface adds support for custom top-level access token claims via the new getOtherTopLevelParameters method.

Resolved issues

  • Fixes the expiration logic for refresh tokens when the Connect2id server is configured with authzStore.refreshToken.alwaysUpdate=true (issue authz-store/166).

  • Fixes "authzStore.accessTokenIssues" metering on successful refresh token usage (issue authz-store/167).

  • Fixes persistence of client_id metadata for cached request_uri claims in multi-tenant Connect2id server deployments (issue server/507).

  • Updates AWS SDK to 1.11.632 to support IAM role for Amazon EKS (issue server/503).

Dependency changes

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

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

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

  • Updates to org.cryptomator:siv-mode:1.2.2

  • Updates to com.nimbusds:oidc-session-store:13.4

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

  • Updates to com.nimbusds:infinispan-cachestore-dynamodb:3.5.2

  • Upgrades to com.nimbusds:infinispan-cachestore-sql:4.1.1

  • Updates to org.postgresql:postgresql:42.2.8

  • Updates to com.unboundid:unboundid-ldapsdk:4.0.14

  • Updates to com.amazonaws:aws-java-sdk-bundle:1.11.632

  • Upgrades to com.nimbusds:c2id-server-ldap-schemas:1.10

  • Updates to Infinispan 9.4.17.Final.

  • Updates to com.nimbusds:jgroups-dynamodb-ping:1.2.3