/*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2015-2016 ForgeRock AS.
*/
/**
* Responsible for creating instances of {@link JwtSessionMapper}.
*
* Encryption and signing are optional and can be combined. However, only one means of signing can be applied.
*
* @since 13.0.0
*/
class JwtSessionMapperBuilder {
"org.forgerock.openam.session.stateless.encryption.method";
private static final String RSA_PADDING_METHOD = "org.forgerock.openam.session.stateless.rsa.padding";
JwtSessionMapperBuilder(final SigningManager signingManager, final ISystemProperties systemProperties) {
this.signingManager = signingManager;
this.systemProperties = systemProperties;
}
/**
* Creates a blank session mapping builder with no signing or encryption modes configured.
*/
this(new SigningManager(), new SystemProperties());
}
/**
* Instructs the builder to create instances of {@link JwtSessionMapper} that can sign and verify
* the JWT using RSA using SHA-256 hash algorithm.
*
* @param signingKeyPair Non-null, public-private key-pair to use to sign and verify the JWT.
*
* @return this {@link JwtSessionMapperBuilder}
*
* @see org.forgerock.json.jose.jws.JwsAlgorithm
*/
return this;
}
/**
* Instructs the builder to create instances of {@link JwtSessionMapper} that can sign and verify
* the JWT using HMAC with the SHA-256 hash algorithm.
*
* @param sharedSecret Non-null, shared secret to use to sign and verify the JWT.
*
* @return this {@link JwtSessionMapperBuilder}
*
* @see org.forgerock.json.jose.jws.JwsAlgorithm
*/
return this;
}
/**
* Instructs the builder to create instances of {@link JwtSessionMapper} that can sign and verify
* the JWT using using SHA-384 hash algorithm.
*
* @param sharedSecret Non-null, shared secret to use to sign and verify the JWT.
*
* @return this {@link JwtSessionMapperBuilder}
*
* @see org.forgerock.json.jose.jws.JwsAlgorithm
*/
return this;
}
/**
* Instructs the builder to create instances of {@link JwtSessionMapper} that can sign and verify
* the JWT using using SHA-512 hash algorithm.
*
* @param sharedSecret Non-null, shared secret to use to sign and verify the JWT.
*
* @return this {@link JwtSessionMapperBuilder}
*
* @see org.forgerock.json.jose.jws.JwsAlgorithm
*/
return this;
}
private void signedUsingHSxxx(@Nonnull final JwsAlgorithm jwsAlgorithm, @Nonnull final String sharedSecret) {
this.jwsAlgorithm = jwsAlgorithm;
}
/**
* Instructs the builder to create instances of {@link JwtSessionMapper} that can sign and verify the JWT using
* the ES256 signature algorithm (ECDSA using P-256 curve over SHA-256 hashes).
*
* @param signingKeyPair the signing key pair, not null.
* @return this {@link JwtSessionMapperBuilder}
*
* @see JwsAlgorithm
*/
return this;
}
/**
* Instructs the builder to create instances of {@link JwtSessionMapper} that can sign and verify the JWT using
* the ES384 signature algorithm (ECDSA using P-384 curve over SHA-384 hashes).
*
* @param signingKeyPair the signing key pair, not null.
* @return this {@link JwtSessionMapperBuilder}
*
* @see JwsAlgorithm
*/
return this;
}
/**
* Instructs the builder to create instances of {@link JwtSessionMapper} that can sign and verify the JWT using
* the ES512 signature algorithm (ECDSA using P-521 (not a typo!) curve over SHA-512 hashes).
*
* @param signingKeyPair the signing key pair, not null.
* @return this {@link JwtSessionMapperBuilder}
*
* @see JwsAlgorithm
*/
return this;
}
private void signedUsingESxxx(@Nonnull final JwsAlgorithm jwsAlgorithm, @Nonnull final KeyPair signingKeyPair) {
Reject.ifFalse(signingKeyPair.getPrivate() instanceof ECPrivateKey, "private key is not suitable for " +
Reject.ifFalse(signingKeyPair.getPublic() instanceof ECPublicKey, "public key is not suitable for " +
this.jwsAlgorithm = jwsAlgorithm;
this.signingHandler = signingManager.newEcdsaSigningHandler((ECPrivateKey) signingKeyPair.getPrivate());
this.verificationHandler = signingManager.newEcdsaVerificationHandler((ECPublicKey) signingKeyPair.getPublic());
}
/**
* Instructs the builder to create instances of {@link JwtSessionMapper} that can encrypt and decrypt
* the JWT using RSA encryption. The system property {@literal org.forgerock.openam.session.stateless.rsa .padding}
* can be used to control the RSA padding method (defaults to {@literal RSA-OAEP-256}). The system property
* {@literal org.forgerock.openam.session.stateless.encryption.method} can be used to control the underlying
* content encryption method (defaults to {@literal A128CBC-HS256}).
*
* @param encryptionKeyPair Non-null, public-private key-pair to use to encrypt and decrypt the JWT.
*
* @return this {@link JwtSessionMapperBuilder}
*
* @see JweAlgorithm#RSA_OAEP
* @see JweAlgorithm#RSA_OAEP_256
* @see JweAlgorithm#RSAES_PKCS1_V1_5
* @see org.forgerock.json.jose.jwe.EncryptionMethod
*/
return this;
}
/**
* Instructs the builder to constuct {@link JwtSessionMapper} instances that encrypt the JWT contents using <a
* href="https://tools.ietf.org/html/rfc3394">AES KeyWrap</a>. A unique key is generated for each JWT and then
* wrapped using the provided symmetric key. The strength is determined by the size of the given key: 128-bit key
* corresponds to {@link JweAlgorithm#A128KW} etc. Note that key sizes greater than 128 bits will require
* installation of the JCE Unlimited Strength policy files in the Java Runtime Environment. The system property
* {@literal org.forgerock.openam.session.stateless.encryption.method} can be used to control the underlying
* content encryption method (defaults to {@literal A128CBC-HS256}).
*
* @param symmetricEncryptionKey the symmetric key. Must be 128, 192 or 256 bits in size.
* @return this {@link JwtSessionMapperBuilder}.
*
* @see JweAlgorithm#A128KW
* @see JweAlgorithm#A192KW
* @see JweAlgorithm#A256KW
* @see EncryptionMethod
*/
this.encryptionKey = symmetricEncryptionKey;
this.decryptionKey = symmetricEncryptionKey;
case 16:
break;
case 24:
break;
case 32:
break;
default:
throw new IllegalArgumentException("Invalid key size for AES KeyWrap: must be 128, 192 or 256 bits");
}
return this;
}
/**
* Instructs the builder to construct {@link JwtSessionMapper} instances that encrypt the JWT contents directly
* using the given AES key. The system property
* {@literal org.forgerock.openam.session.stateless.encryption.method} can be used to control the underlying
* content encryption method (defaults to {@literal A128CBC-HS256}).
*
* @param symmetricEncryptionKey the AES encryption key to use. Must be either 128, 192 or 256 bits.
* @return this {@link JwtSessionMapperBuilder}.
*
* @see JweAlgorithm#DIRECT
* @see EncryptionMethod
*/
this.encryptionKey = symmetricEncryptionKey;
this.decryptionKey = symmetricEncryptionKey;
return this;
}
/**
* Indicates that the content should be compressed before encryption using the given algorithm.
*
* @param compressionAlgorithm the compression algorithm to use.
* @return this builder object.
*/
return this;
}
/**
* @return JwtSessionMapper configured to perform signing and encryption as specified.
*/
if (jweAlgorithm != null) {
Reject.ifTrue(jweAlgorithm.getAlgorithmType() == JweAlgorithmType.RSA && jwsAlgorithm == JwsAlgorithm.NONE,
"RSA encryption should not be used without a signature");
} else {
"No encryption or signature scheme specified!");
}
return new JwtSessionMapper(this);
}
return jwsAlgorithm;
}
boolean isConfigured() {
return isCurrentConfigurationValid();
}
}