Skip to content

Commit

Permalink
small refactor, spotless, tests, use raw settings to create jwk
Browse files Browse the repository at this point in the history
Signed-off-by: Maciej Mierzwa <[email protected]>
  • Loading branch information
MaciejMierzwa committed Oct 3, 2023
1 parent 1eb397c commit 9a2ef33
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 169 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public SignedJWT getVerifiedJwtToken(String encodedJwt) throws BadCredentialsExc
if (!Strings.isNullOrEmpty(kid)) {
kid = StringEscapeUtils.unescapeJava(escapedKid);
}
JWK key = keyProvider.getKey(kid);
JWK key = keyProvider.getKey(kid);

JWSVerifier signatureVerifier = getInitializedSignatureVerifier(key, jwt);
boolean signatureValid = jwt.verify(signatureVerifier);
Expand Down Expand Up @@ -97,8 +97,8 @@ private JWSVerifier getInitializedSignatureVerifier(JWK key, SignedJWT jwt) thro

validateSignatureAlgorithm(key, jwt);
final JWSVerifier result;
if(key.getClass() == OctetSequenceKey.class) {
result = new DefaultJWSVerifierFactory().createJWSVerifier(jwt.getHeader(), key.toOctetSequenceKey().toSecretKey());
if (key.getClass() == OctetSequenceKey.class) {
result = new DefaultJWSVerifierFactory().createJWSVerifier(jwt.getHeader(), key.toOctetSequenceKey().toSecretKey());
} else {
result = new DefaultJWSVerifierFactory().createJWSVerifier(jwt.getHeader(), key.toRSAKey().toRSAPublicKey());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@

public interface KeyProvider {
JWK getKey(String kid) throws AuthenticatorUnavailableException, BadCredentialsException;

JWK getKeyAfterRefresh(String kid) throws AuthenticatorUnavailableException, BadCredentialsException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import com.onelogin.saml2.authn.SamlResponse;
Expand All @@ -51,6 +50,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joda.time.DateTime;
import org.opensearch.security.authtoken.jwt.JwtVendor;
import org.xml.sax.SAXException;

import org.opensearch.OpenSearchSecurityException;
Expand Down Expand Up @@ -266,46 +266,35 @@ private JWSHeader createJwsHeaderFromSettings() {
}

JWK createJwkFromSettings(Settings settings, Settings jwtSettings) throws Exception {

String exchangeKey = settings.get("exchange_key");
String exchangeKey = JwtVendor.padSecret(settings.get("exchange_key"), JWSAlgorithm.HS512);

if (!Strings.isNullOrEmpty(exchangeKey)) {

return new OctetSequenceKey.Builder(exchangeKey.getBytes(StandardCharsets.UTF_8))
.algorithm(JWSAlgorithm.HS512)
.keyUse(KeyUse.SIGNATURE)
.build();
return new OctetSequenceKey.Builder(exchangeKey.getBytes(StandardCharsets.UTF_8)).algorithm(JWSAlgorithm.HS512)
.keyUse(KeyUse.SIGNATURE)
.build();
} else {

Settings jwkSettings = jwtSettings.getAsSettings("key");

if (jwkSettings.isEmpty()) {
if (jwkSettings.isEmpty() || jwkSettings.get("k") == null || jwkSettings.get("k").isBlank()) {
throw new Exception(
"Settings for key exchange missing. Please specify at least the option exchange_key with a shared secret."
);
}

//TODO nimbus library doesn't accept generic key creation. Decide between RSAKey, OCTET, ECKey and create key from raw settings
// JsonWebKey jwk = new JsonWebKey();
//
// for (String key : jwkSettings.keySet()) {
// jwk.setProperty(key, jwkSettings.get(key));
// }

// for (String key : jwkSettings.keySet()) {
// jwk.setProperty(key, jwkSettings.get(key));
// }

return null;
// try to create OCTET, HMAC key
String k = JwtVendor.padSecret(jwkSettings.get("k"), JWSAlgorithm.HS512);
return new OctetSequenceKey.Builder(k.getBytes(StandardCharsets.UTF_8)).algorithm(JWSAlgorithm.HS512)
.keyUse(KeyUse.SIGNATURE)
.build();
}
}

private String createJwt(SamlResponse samlResponse) throws Exception {
JWTClaimsSet.Builder jwtClaimsBuilder = new JWTClaimsSet.Builder()
//TODO check milis
.notBeforeTime(new Date(new Timestamp(System.currentTimeMillis()).getTime()))
.expirationTime(new Date(getJwtExpiration(samlResponse)))
.claim(this.jwtSubjectKey, this.extractSubject(samlResponse));
JWTClaimsSet.Builder jwtClaimsBuilder = new JWTClaimsSet.Builder().notBeforeTime(
new Date(new Timestamp(System.currentTimeMillis()).getTime())
)
.expirationTime(new Date(new Timestamp(getJwtExpiration(samlResponse)).getTime()))
.claim(this.jwtSubjectKey, this.extractSubject(samlResponse));

if (this.samlSubjectKey != null) {
jwtClaimsBuilder.claim("saml_ni", samlResponse.getNameId());
Expand All @@ -332,14 +321,7 @@ private String createJwt(SamlResponse samlResponse) throws Exception {
String encodedJwt = jwt.serialize();

if (token_log.isDebugEnabled()) {
token_log.debug(
"Created JWT: "
+ encodedJwt
+ "\n"
+ jwt.getHeader().toString()
+ "\n"
+ jwt.getJWTClaimsSet().toString()
);
token_log.debug("Created JWT: " + encodedJwt + "\n" + jwt.getHeader().toString() + "\n" + jwt.getJWTClaimsSet().toString());
}

return encodedJwt;
Expand All @@ -349,20 +331,20 @@ private long getJwtExpiration(SamlResponse samlResponse) throws Exception {
DateTime sessionNotOnOrAfter = samlResponse.getSessionNotOnOrAfter();

if (this.expiryBaseValue == ExpiryBaseValue.NOW) {
return System.currentTimeMillis() / 1000 + this.expiryOffset;
return System.currentTimeMillis() + this.expiryOffset * 1000;
} else if (this.expiryBaseValue == ExpiryBaseValue.SESSION) {
if (sessionNotOnOrAfter != null) {
return sessionNotOnOrAfter.getMillis() / 1000 + this.expiryOffset;
return sessionNotOnOrAfter.getMillis() + this.expiryOffset * 1000;
} else {
throw new Exception("Error while determining JWT expiration time: SamlResponse did not contain sessionNotOnOrAfter value");
}
} else {
// AUTO

if (sessionNotOnOrAfter != null) {
return sessionNotOnOrAfter.getMillis() / 1000;
return sessionNotOnOrAfter.getMillis();
} else {
return System.currentTimeMillis() / 1000 + (this.expiryOffset > 0 ? this.expiryOffset : 60 * 60);
return System.currentTimeMillis() + (this.expiryOffset > 0 ? this.expiryOffset * 1000 : 60 * 60_000);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,35 +71,34 @@ public JwtVendor(final Settings settings, final Optional<LongSupplier> timeProvi

static Tuple<JWK, JWSSigner> createJwkFromSettings(Settings settings) {
String signingKey = settings.get("signing_key");
signingKey = padSecret(signingKey);
signingKey = padSecret(signingKey, JWSAlgorithm.HS512);

if (Strings.isNullOrEmpty(signingKey)) {
throw new OpenSearchException(
"Signing key is required for creation of OnBehalfOf tokens, the '\"on_behalf_of\": {\"signing_key\":{KEY}, ...} with a shared secret."
);
}

final OctetSequenceKey key = new OctetSequenceKey.Builder(signingKey.getBytes(StandardCharsets.UTF_8))
.algorithm(JWSAlgorithm.HS512)
.keyUse(KeyUse.SIGNATURE)
.build();
final OctetSequenceKey key = new OctetSequenceKey.Builder(signingKey.getBytes(StandardCharsets.UTF_8)).algorithm(JWSAlgorithm.HS512)
.keyUse(KeyUse.SIGNATURE)
.build();

try {
return new Tuple<JWK, JWSSigner>(key, new MACSigner(key));
return new Tuple<>(key, new MACSigner(key));
} catch (KeyLengthException kle) {
throw new OpenSearchException(kle);
}
}

private static String padSecret(String signingKey) {
public static String padSecret(String signingKey, JWSAlgorithm jwsAlgorithm) {
int requiredSecretLength;
try {
requiredSecretLength = getMinRequiredSecretLength(JWSAlgorithm.HS512);
requiredSecretLength = getMinRequiredSecretLength(jwsAlgorithm);
} catch (JOSEException e) {
throw new RuntimeException(e);
}
int requiredByteLength = ByteUtils.byteLength(requiredSecretLength);
//padding the signing key with 0s to meet the minimum required length
// padding the signing key with 0s to meet the minimum required length
return StringUtils.rightPad(signingKey, requiredByteLength, "0");
}

Expand Down
Loading

0 comments on commit 9a2ef33

Please sign in to comment.