Client secret store codec SPI

1. Encrypt or hash client secrets in storage

If the database used by the Connect2id server isn't configured to encrypt the data at rest the individual client secrets can still be encrypted before committing them to storage. This is made possible by a dedicated plugin interface, a Service Provider Interface in Java, that can apply arbitrary transformations to the value of a client_secret before writing it to the database and then after retrieval.

Encrypting, or alternatively, hashing the client secrets, is a good security policy to minimise the risk of an undetected credential leak from the database.

Recommended methods:

An even better strategy is to dispense with the client secrets entirely and switch to public key based authentication for OAuth clients, such as private_key_jwt, or the tls_client_auth or self_signed_tls_client_auth methods from RFC 8705.

Note, while hashing may be easier to implement as there is no AES key to manage, it will not work for clients for which the Connect2id server requires the secret to be available in plain text:

  • Clients registered for HMAC-based client_secret_jwt authentication, or ID token, UserInfo, request object or JARM with HMAC JWS algorithms: HS256, HS384 and HS512.
  • Clients registered to receive or submit JWTs encrypted with a shared AES key derived from the secret, the JWE algorithm dir.

The plugin SPI can also be used to import client secrets in arbitrary formats from another OAuth 2.0 authorisation server.

The SPI is available since v11.0.

2. Client secret codec SPI

To plug in your own custom checks implement the ClientSecretStoreCodec SPI defined in the Connect2id server toolkit:

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

Features of the client secret codec SPI:

  • Supports arbitrary encoding of client_secret values before writing them to the database.
  • Supports arbitrary decoding of client_secret values after retrieving them from the database.
  • Supports separate encoding / decoding of client_secret values for clients imported from another OAuth 2.0 server.
  • Provides access to the registered information for the client so that encoding decisions (e.g. encrypt or hash) can be made.
  • Provides access to the Connect2id server JWK set where the client secret encryption AES key(s) may be stored.

If the Connect2id server detects an SPI implementation it will log its loading under OP6604.

INFO main MAIN - [OP0138] Loaded client secret store codec: com.nimbusds.openid.connect.provider.spi.secrets.impl.BCryptSecretCodec

3. Example

Sample BCrypt hashing codec with the BCrypt Java library by Patrick Favre-Bulle.

import at.favre.lib.crypto.bcrypt.BCrypt;
import com.nimbusds.openid.connect.provider.spi.secrets.*;
import com.nimbusds.oauth2.sdk.auth.Secret;
import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;

public class BCryptCodec implements ClientSecretStoreCodec {

    @Override
    public String encode(final Secret secret, final SecretCodecContext ctx) {
        return BCrypt
            .withDefaults()
            .hashToString(4, secret.getValue().toCharArray());
    }

    @Override
    public DecodedSecret decode(final String storedValue, final SecretCodecContext ctx) {

        return DecodedSecret.createForHashedSecret(
            otherSecret -> {
                BCrypt.Result result = BCrypt
                    .verifyer()
                    .verify(
                        otherSecret.getValue().toCharArray(),
                        storedValue.toCharArray());
                return result.verified;
            }
        );
    }
}

Example transformation with BCrypt:

Plain text 256-bit secret, BASE64URL encoded: 5k4NOArtKpDYeBoxDoVwXswsIApyibpMIBWRgLdSyNM
BCrypt: $2a$04$a9uQ9Ka0usxqTCp/1je2iuS.qnVsXKe0Gjhh5kPEhnbInkseODhgS

4. Support

Our Connect2id support team is available if you need help with integrating a custom client secret codec.