[java-oidc-common] branch main updated: Move Encrypt and Sign message handlers from the RP to commons
Phil Smart
philip.smart at jisc.ac.uk
Tue Jan 3 15:30:22 UTC 2023
This is an automated email from the git hooks/post-receive script.
philsmart pushed a commit to branch main
in repository java-oidc-common.
View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=b7981cc99d7344857d9271f65609f7c67716eacd
The following commit(s) were added to refs/heads/main by this push:
new b7981cc Move Encrypt and Sign message handlers from the RP to commons
b7981cc is described below
commit b7981cc99d7344857d9271f65609f7c67716eacd
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Tue Jan 3 15:30:19 2023 +0000
Move Encrypt and Sign message handlers from the RP to commons
---
.../oidc/security/impl/EncryptJWTHandler.java | 286 +++++++++++++++++++++
.../oidc/security/impl/SignJWTHandler.java | 281 ++++++++++++++++++++
2 files changed, 567 insertions(+)
diff --git a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/impl/EncryptJWTHandler.java b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/impl/EncryptJWTHandler.java
new file mode 100644
index 0000000..eb11c8e
--- /dev/null
+++ b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/impl/EncryptJWTHandler.java
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package net.shibboleth.oidc.security.impl;
+
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.xmlsec.EncryptionParameters;
+import org.opensaml.xmlsec.context.SecurityParametersContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.jose.EncryptionMethod;
+import com.nimbusds.jose.JWEAlgorithm;
+import com.nimbusds.jose.JWEHeader;
+import com.nimbusds.jose.JWEObject;
+import com.nimbusds.jose.Payload;
+import com.nimbusds.jose.crypto.AESEncrypter;
+import com.nimbusds.jose.crypto.DirectEncrypter;
+import com.nimbusds.jose.crypto.ECDHEncrypter;
+import com.nimbusds.jose.crypto.RSAEncrypter;
+import com.nimbusds.jwt.EncryptedJWT;
+import com.nimbusds.jwt.JWT;
+
+import net.shibboleth.oidc.security.JWTEncryptionParameters;
+import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * A {@link MessageHandler} that encrypts a JWT using the {@link EncryptionParameters} found in the
+ * {@link JWTSecurityParametersContext}. The {@link Payload} to encrypt is determined by lookup strategy.
+ * A consumer takes the {@link EncryptedJWT} and updates the correct object in the {@link MessageContext}.
+ */
+//TODO encrypt action is unpleasent to look at
+public class EncryptJWTHandler extends AbstractMessageHandler {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(EncryptJWTHandler.class);
+
+ /** Strategy used to locate the {@link SecurityParametersContext} to use for signing. */
+ @Nonnull private Function<MessageContext, JWTSecurityParametersContext> securityParametersLookupStrategy;
+
+ /** Strategy used to locate the payload to encrypt.*/
+ @NonnullAfterInit private Function<MessageContext, Payload> payloadToEncryptLookupStrategy;
+
+ /** A consumer that takes the EncryptedJWT and updates the correct object inside the MessageContext.*/
+ @NonnullAfterInit private BiConsumer<JWT, MessageContext> jwtUpdateConsumer;
+
+ /** The signature signing parameters. */
+ @Nullable private JWTEncryptionParameters encryptionParameters;
+
+ /** A friendly name to log as the subject of encryption.*/
+ @Nonnull private String logName;
+
+
+ /** Constructor.*/
+ public EncryptJWTHandler() {
+ logName = "not-specified";
+ securityParametersLookupStrategy = new ChildContextLookup<>(JWTSecurityParametersContext.class);
+ }
+
+ /**
+ * Set the friendly name to log as the subject of encryption.
+ *
+ * @param name the friendly name
+ */
+ public void setLogName(@Nonnull @NotEmpty final String name) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ logName = Constraint.isNotEmpty(name, "ForFriendlyName can not be null or empty");
+ }
+
+ /**
+ * Set the consumer used to update the MessageContext with the supplied EncryptedJWT.
+ *
+ * @param consumer the consumer
+ */
+ public void setJwtUpdateConsumer(final BiConsumer<JWT, MessageContext> consumer) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ jwtUpdateConsumer = Constraint.isNotNull(consumer, "JWT Update Consumer can not be null");
+ }
+
+ /**
+ * Set the strategy used to locate the {@link Payload} to encrypt.
+ *
+ * @param strategy the strategy
+ */
+ public void setPayloadToEncryptLookupStrategy(@Nonnull final Function<MessageContext, Payload> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ payloadToEncryptLookupStrategy =
+ Constraint.isNotNull(strategy, "Payload To Encrypt Lookup Strategy can not be null");
+ }
+
+ /**
+ * Set the strategy used to locate the {@link SecurityParametersContext} to use.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setSecurityParametersLookupStrategy(
+ @Nonnull final Function<MessageContext, JWTSecurityParametersContext> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ securityParametersLookupStrategy =
+ Constraint.isNotNull(strategy, "SecurityParameterContext lookup strategy cannot be null");
+ }
+
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ if (payloadToEncryptLookupStrategy == null) {
+ throw new ComponentInitializationException("Payload To Encrypt Lookup Strategy can not be null");
+ }
+ if (jwtUpdateConsumer == null) {
+ throw new ComponentInitializationException("JWT Update Consumer can not be null");
+ }
+ super.doInitialize();
+ }
+
+
+ @Override
+ protected boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ if (!super.doPreInvoke(messageContext)) {
+ return false;
+ }
+
+ final JWTSecurityParametersContext secParamCtx =
+ securityParametersLookupStrategy.apply(messageContext);
+ if (secParamCtx == null) {
+ log.trace("{} Message context did not contain an encryption parameters context, "
+ + "encryption skipped", getLogPrefix());
+ return false;
+ }
+
+ encryptionParameters = secParamCtx.getEncryptionParameters();
+ if (encryptionParameters == null) {
+ log.debug("{} Message context did not contain encryption parameters, "
+ + "request object will not be encrypted", getLogPrefix());
+ return false;
+ }
+
+ // If we have parameters (so encryption is enabled), but the parameters are not in the correct state,
+ // throw an exception as opposed to skipping encryption
+ if (StringSupport.trimOrNull(encryptionParameters.getKeyTransportEncryptionAlgorithm()) == null ||
+ StringSupport.trimOrNull(encryptionParameters.getDataEncryptionAlgorithm()) == null ||
+ (encryptionParameters.getKeyTransportEncryptionCredential() == null &&
+ encryptionParameters.getDataEncryptionCredential() == null)) {
+ throw new MessageHandlerException("Message context did not contain all required encryption parameters");
+ }
+ if (encryptionParameters.getKeyTransportEncryptionCredential() != null &&
+ encryptionParameters.getDataEncryptionCredential() != null) {
+ throw new MessageHandlerException("Message context contained both a content encryption and "
+ + "key transport credential. Only one required.");
+ }
+
+ return true;
+ }
+
+ @Override
+ protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ final Payload payload = payloadToEncryptLookupStrategy.apply(messageContext);
+ if (payload == null) {
+ log.trace("{} No plain text source payload provided to encrypt, encryption skipped", getLogPrefix());
+ return;
+ }
+
+ final JWEAlgorithm encAlg = JWEAlgorithm.parse(encryptionParameters.getKeyTransportEncryptionAlgorithm());
+ final EncryptionMethod encEnc = EncryptionMethod.parse(encryptionParameters.getDataEncryptionAlgorithm());
+
+
+ final Credential keyTransportCredential = encryptionParameters.getKeyTransportEncryptionCredential();
+ final Credential dataEncryptionCredential = encryptionParameters.getDataEncryptionCredential();
+
+ final String keyTransportKid = keyTransportCredential == null ? null :
+ CredentialConversionUtil.resolveKid(keyTransportCredential);
+ final String dataEncryptionKid = dataEncryptionCredential == null ? null :
+ CredentialConversionUtil.resolveKid(dataEncryptionCredential);
+
+ JWEObject jweObject = null;
+ try {
+ if (JWEAlgorithm.Family.RSA.contains(encAlg) && keyTransportCredential != null &&
+ keyTransportCredential.getPublicKey() != null) {
+
+ jweObject = new JWEObject(new JWEHeader.Builder(encAlg, encEnc).contentType("JWT")
+ .keyID(keyTransportKid).build(), payload);
+ logEncryption(keyTransportKid, encAlg.getName(), encEnc.getName());
+ jweObject.encrypt(new RSAEncrypter((RSAPublicKey) keyTransportCredential.getPublicKey()));
+
+ } else if (JWEAlgorithm.Family.ECDH_ES.contains(encAlg) && keyTransportCredential != null &&
+ keyTransportCredential.getPublicKey() != null) {
+
+ jweObject = new JWEObject(new JWEHeader.Builder(encAlg, encEnc).contentType("JWT")
+ .keyID(keyTransportKid).build(), payload);
+ logEncryption(keyTransportKid, encAlg.getName(), encEnc.getName());
+ jweObject.encrypt(new ECDHEncrypter((ECPublicKey) keyTransportCredential.getPublicKey()));
+
+ } else if ((JWEAlgorithm.Family.AES_KW.contains(encAlg) || JWEAlgorithm.Family.AES_GCM_KW.contains(encAlg))
+ && keyTransportCredential != null && keyTransportCredential.getSecretKey() != null) {
+
+ jweObject = new JWEObject(new JWEHeader.Builder(encAlg, encEnc).contentType("JWT")
+ .keyID(keyTransportKid).build(), payload);
+ logEncryption(keyTransportKid, encAlg.getName(), encEnc.getName());
+ jweObject.encrypt(new AESEncrypter(keyTransportCredential.getSecretKey()));
+
+ } else if (JWEAlgorithm.DIR.equals(encAlg) && dataEncryptionCredential != null &&
+ dataEncryptionCredential.getSecretKey() != null){
+
+ jweObject = new JWEObject(new JWEHeader.Builder(encAlg, encEnc).contentType("JWT")
+ .keyID(dataEncryptionKid).build(), payload);
+ logEncryption(dataEncryptionKid, encAlg.getName(), encEnc.getName());
+ jweObject.encrypt(new DirectEncrypter(dataEncryptionCredential.getSecretKey()));
+
+ } else {
+ log.error("{} Unsupported algorithm '{}' or key '{}'", getLogPrefix(), encAlg.getName(),
+ keyTransportKid);
+ throw new MessageHandlerException("Unsupported algorithm "+encAlg.getName());
+ }
+
+ final EncryptedJWT encryptedJWT = EncryptedJWT.parse(jweObject.serialize());
+ jwtUpdateConsumer.accept(encryptedJWT, messageContext);
+
+ if (log.isDebugEnabled() && !log.isTraceEnabled()) {
+ log.debug("{} Encrypted '{}' JWT", getLogPrefix(), logName);
+ } else if (log.isTraceEnabled()) {
+ log.debug("{} Encrypted '{}' JWT: {}", getLogPrefix(), logName, encryptedJWT.serialize());
+ }
+
+ } catch (final Exception e) {
+ log.error("{} Encryption failed", getLogPrefix(), e);
+ throw new MessageHandlerException("Encryption failed", e);
+ }
+
+ }
+
+ /**
+ * A convince method to log encryption parameters. Avoids some of the clutter in the calling
+ * methods.
+ *
+ * @param keyID the keyID
+ * @param enc the content encryption algorithm
+ * @param alg the key management algorithm
+ */
+ private void logEncryption(@Nullable final String keyID,
+ @Nullable final String enc, @Nullable final String alg) {
+ log.debug("{} Encrypting '{}' with kid '{}' and params alg: {} enc: {}",
+ getLogPrefix(), logName, keyID, alg, enc);
+ }
+
+}
diff --git a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/impl/SignJWTHandler.java b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/impl/SignJWTHandler.java
new file mode 100644
index 0000000..8aff29b
--- /dev/null
+++ b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/impl/SignJWTHandler.java
@@ -0,0 +1,281 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.oidc.security.impl;
+
+import java.security.interfaces.ECPrivateKey;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.xmlsec.context.SecurityParametersContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.jose.Algorithm;
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.JWSObject.State;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.crypto.ECDSASigner;
+import com.nimbusds.jose.crypto.MACSigner;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jwt.JWT;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.oidc.security.JWTSignatureSigningParameters;
+import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
+import net.shibboleth.oidc.security.credential.JWKCredential;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * Action that signs a request object and sets it as the request object to the authentication request.
+ */
+//TODO move to commons?
+public class SignJWTHandler extends AbstractMessageHandler {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SignJWTHandler.class);
+
+ /** Strategy used to locate the {@link SecurityParametersContext} to use for signing. */
+ @Nonnull private Function<MessageContext, JWTSecurityParametersContext> securityParametersLookupStrategy;
+
+ /** A consumer that takes the EncryptedJWT and updates the correct object inside the MessageContext.*/
+ @NonnullAfterInit private BiConsumer<JWT, MessageContext> jwtUpdateConsumer;
+
+ /** Strategy used to locate the payload to encrypt.*/
+ @NonnullAfterInit private Function<MessageContext, JWTClaimsSet> claimsToSignLookupStrategy;
+
+ /** The signature signing parameters. */
+ @Nullable private JWTSignatureSigningParameters signatureSigningParameters;
+
+ /** resolved credential. */
+ @Nullable private Credential credential;
+
+ /** The claims to sign.*/
+ @Nullable private JWTClaimsSet jwtClaimSetToSign;
+
+ /** "typ" header to insert while signing. */
+ @Nullable @NotEmpty private String typeHeader;
+
+ /** A friendly name to log as the subject of signing.*/
+ @Nonnull private String logName;
+
+ /** Constructor.*/
+ public SignJWTHandler() {
+ logName = "not-specified";
+ securityParametersLookupStrategy = new ChildContextLookup<>(JWTSecurityParametersContext.class);
+ }
+
+ /**
+ * Set the friendly name to log as the subject of signing.
+ *
+ * @param name the friendly name
+ */
+ public void setLogName(@Nonnull @NotEmpty final String name) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ logName = Constraint.isNotEmpty(name, "ForFriendlyName can not be null or empty");
+ }
+
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ if (claimsToSignLookupStrategy == null) {
+ throw new ComponentInitializationException("Claims To Sign Lookup Strategy can not be null");
+ }
+ if (jwtUpdateConsumer == null) {
+ throw new ComponentInitializationException("JWT Update Consumer can not be null");
+ }
+ super.doInitialize();
+ }
+
+ /**
+ * Set the strategy used to locate the {@link JWTClaimsSet} to sign.
+ *
+ * @param strategy the strategy
+ */
+ public void setClaimsToSignLookupStrategy(@Nonnull final Function<MessageContext, JWTClaimsSet> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ claimsToSignLookupStrategy =
+ Constraint.isNotNull(strategy, "Claims To Sign Lookup Strategy can not be null");
+ }
+
+ /**
+ * Set the consumer used to update the MessageContext with the supplied EncryptedJWT.
+ *
+ * @param consumer the consumer
+ */
+ public void setJwtUpdateConsumer(final BiConsumer<JWT, MessageContext> consumer) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ jwtUpdateConsumer = Constraint.isNotNull(consumer, "JWT Update Consumer can not be null");
+ }
+
+ /**
+ * Sets the value to be inserted as a "typ" header for the JWS.
+ *
+ * @param type header value
+ */
+ public void setTypeHeader(@Nullable @NotEmpty final String type) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ typeHeader = StringSupport.trimOrNull(type);
+ }
+
+ /**
+ * Set the strategy used to locate the {@link SecurityParametersContext} to use.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setSecurityParametersLookupStrategy(
+ @Nonnull final Function<MessageContext, JWTSecurityParametersContext> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ securityParametersLookupStrategy =
+ Constraint.isNotNull(strategy, "SecurityParameterContext lookup strategy cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ if (!super.doPreInvoke(messageContext)) {
+ return false;
+ }
+
+ final JWTSecurityParametersContext secParamCtx =
+ securityParametersLookupStrategy.apply(messageContext);
+ if (secParamCtx == null) {
+ log.debug("{} Message context did not contain a signing parameters context, "
+ + "signing skipped", getLogPrefix());
+ return false;
+ }
+
+ signatureSigningParameters = secParamCtx.getSignatureSigningParameters();
+ if (signatureSigningParameters == null || signatureSigningParameters.getSigningCredential() == null) {
+ log.debug("{} No signature signing credentials available", getLogPrefix());
+ return false;
+ }
+
+ jwtClaimSetToSign = claimsToSignLookupStrategy.apply(messageContext);
+ if (jwtClaimSetToSign == null) {
+ log.debug("{} No JWT claims, nothing to sign", getLogPrefix());
+ return false;
+ }
+
+ credential = signatureSigningParameters.getSigningCredential();
+
+ return true;
+
+ }
+
+ @Override
+ protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ try {
+ SignedJWT jwt = null;
+ final Algorithm jwsAlgorithm = resolveAlgorithm();
+ final JWSSigner signer = getSigner(jwsAlgorithm);
+ final JWSHeader.Builder headerBuilder = new JWSHeader.Builder(new JWSAlgorithm(jwsAlgorithm.getName()))
+ .keyID(CredentialConversionUtil.resolveKid(credential));
+ if (typeHeader != null) {
+ headerBuilder.type(new JOSEObjectType(typeHeader));
+ }
+ jwt = new SignedJWT(headerBuilder.build(), jwtClaimSetToSign);
+ jwt.sign(signer);
+ if (log.isDebugEnabled() && !log.isTraceEnabled()) {
+ log.debug("{} Signed JWT '{}'", getLogPrefix(), logName);
+ } else if (log.isTraceEnabled()) {
+ log.trace("{} Signed JWT '{}': {}", getLogPrefix(), logName, jwt.serialize());
+ }
+
+ if (jwt.getState() != State.SIGNED) {
+ // Should not really happen, as JOSEException should be thrown
+ log.error("{} JWT '{}' was not signed", getLogPrefix(), logName);
+ throw new MessageHandlerException("JWT was not signed, unknown cause");
+ }
+
+ // Use consumer to update the signed JWT
+ jwtUpdateConsumer.accept(jwt, messageContext);
+
+ } catch (final JOSEException e) {
+ log.error("{} Error signing claim set: {}", getLogPrefix(), e.getMessage());
+ throw new MessageHandlerException("Error signing claims set",e);
+ }
+
+
+ }
+
+ /**
+ * Returns correct implementation of signer based on algorithm type.
+ *
+ * @param jwsAlgorithm JWS algorithm
+ * @return signer for algorithm and private key
+ * @throws JOSEException if algorithm cannot be supported
+ */
+ private JWSSigner getSigner(final Algorithm jwsAlgorithm) throws JOSEException {
+ if (JWSAlgorithm.Family.EC.contains(jwsAlgorithm)) {
+ return new ECDSASigner((ECPrivateKey) credential.getPrivateKey());
+ }
+ if (JWSAlgorithm.Family.RSA.contains(jwsAlgorithm)) {
+ return new RSASSASigner(credential.getPrivateKey());
+ }
+ if (JWSAlgorithm.Family.HMAC_SHA.contains(jwsAlgorithm)) {
+ return new MACSigner(credential.getSecretKey());
+ }
+ throw new JOSEException("Unsupported algorithm " + jwsAlgorithm.getName());
+ }
+
+ /**
+ * Resolves JWS algorithm from signature signing parameters.
+ *
+ * @return JWS algorithm
+ */
+ protected JWSAlgorithm resolveAlgorithm() {
+
+ final JWSAlgorithm algorithm = new JWSAlgorithm(signatureSigningParameters.getSignatureAlgorithm());
+ if (credential instanceof JWKCredential && !algorithm.equals(((JWKCredential) credential).getAlgorithm())) {
+ log.debug("{} Signature signing algorithm {} differs from JWK algorithm {}", getLogPrefix(),
+ algorithm.getName(), (((JWKCredential) credential).getAlgorithm() != null ?
+ ((JWKCredential) credential).getAlgorithm() : "not specified"));
+ }
+ log.trace("{} Algorithm resolved {}", getLogPrefix(), algorithm.getName());
+ return algorithm;
+ }
+
+
+
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list