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
(SPI) which may apply arbitrary
transformations to the value of a client_secret
before writing it to the
database, and then after its retrieval.
Encrypting, or alternatively, hashing the client secrets, is an excellent security measure 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:
Git repo | 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 OP0138
.
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