use of org.keycloak.saml.common.exceptions.ProcessingException in project keycloak by keycloak.
the class XMLEncryptionUtil method encryptElement.
/**
* <p>
* Encrypts an element in a XML document using the specified public key, secret key, and key size. This method
* doesn't wrap
* the encrypted element in a new element. Instead, it replaces the element with its encrypted version.
* </p>
* <p>
* For example, calling this method to encrypt the <tt><b>inner</b></tt> element in the following XML document
*
* <pre>
* <root>
* <outer>
* <inner>
* ...
* </inner>
* </outer>
* </root>
* </pre>
*
* would result in a document similar to
*
* <pre>
* <root>
* <outer>
* <xenc:EncryptedData xmlns:xenc="...">
* ...
* </xenc:EncryptedData>
* </outer>
* </root>
* </pre>
*
* </p>
*
* @param document the {@code Document} that contains the element to be encrypted.
* @param element the {@code Element} to be encrypted.
* @param publicKey the {@code PublicKey} that must be used to encrypt the secret key.
* @param secretKey the {@code SecretKey} used to encrypt the specified element.
* @param keySize the size (in bits) of the secret key.
*
* @throws ProcessingException if an error occurs while encrypting the element with the specified params.
*/
public static void encryptElement(Document document, Element element, PublicKey publicKey, SecretKey secretKey, int keySize) throws ProcessingException {
if (element == null)
throw logger.nullArgumentError("element");
if (document == null)
throw logger.nullArgumentError("document");
XMLCipher cipher = null;
EncryptedKey encryptedKey = encryptKey(document, secretKey, publicKey, keySize);
String encryptionAlgorithm = getXMLEncryptionURL(secretKey.getAlgorithm(), keySize);
// Encrypt the Document
try {
cipher = XMLCipher.getInstance(encryptionAlgorithm);
cipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
} catch (XMLEncryptionException e1) {
throw logger.processingError(e1);
}
Document encryptedDoc;
try {
encryptedDoc = cipher.doFinal(document, element);
} catch (Exception e) {
throw logger.processingError(e);
}
// The EncryptedKey element is added
Element encryptedKeyElement = cipher.martial(document, encryptedKey);
// Outer ds:KeyInfo Element to hold the EncryptionKey
Element sigElement = encryptedDoc.createElementNS(XMLSignature.XMLNS, DS_KEY_INFO);
sigElement.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:ds", XMLSignature.XMLNS);
sigElement.appendChild(encryptedKeyElement);
// Insert the Encrypted key before the CipherData element
NodeList nodeList = encryptedDoc.getElementsByTagNameNS(EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_CIPHERDATA);
if (nodeList == null || nodeList.getLength() == 0)
throw logger.domMissingElementError("xenc:CipherData");
Element cipherDataElement = (Element) nodeList.item(0);
Node cipherParent = cipherDataElement.getParentNode();
cipherParent.insertBefore(sigElement, cipherDataElement);
}
use of org.keycloak.saml.common.exceptions.ProcessingException in project keycloak by keycloak.
the class SamlProtocol method finishLogout.
@Override
public Response finishLogout(UserSessionModel userSession) {
logger.debug("finishLogout");
String logoutBindingUri = userSession.getNote(SAML_LOGOUT_BINDING_URI);
if (logoutBindingUri == null) {
logger.error("Can't finish SAML logout as there is no logout binding set. Please configure the logout service url in the admin console for your client applications.");
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_LOGOUT);
}
String logoutRelayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE);
SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID));
builder.destination(logoutBindingUri);
builder.issuer(getResponseIssuer(realm));
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(session);
binding.relayState(logoutRelayState);
String signingAlgorithm = userSession.getNote(SAML_LOGOUT_SIGNATURE_ALGORITHM);
boolean postBinding = isLogoutPostBindingForInitiator(userSession);
if (signingAlgorithm != null) {
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(signingAlgorithm);
String canonicalization = userSession.getNote(SAML_LOGOUT_CANONICALIZATION);
if (canonicalization != null) {
binding.canonicalizationMethod(canonicalization);
}
KeyManager.ActiveRsaKey keys = session.keys().getActiveRsaKey(realm);
XmlKeyInfoKeyNameTransformer transformer = XmlKeyInfoKeyNameTransformer.from(userSession.getNote(SAML_SERVER_SIGNATURE_KEYINFO_KEY_NAME_TRANSFORMER), SamlClient.DEFAULT_XML_KEY_INFO_KEY_NAME_TRANSFORMER);
String keyName = transformer.getKeyName(keys.getKid(), keys.getCertificate());
binding.signatureAlgorithm(algorithm).signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()).signDocument();
boolean addExtension = (!postBinding) && Objects.equals("true", userSession.getNote(SamlProtocol.SAML_LOGOUT_ADD_EXTENSIONS_ELEMENT_WITH_KEY_INFO));
if (addExtension) {
// Only include extension if REDIRECT binding and signing whole SAML protocol message
builder.addExtension(new KeycloakKeySamlExtensionGenerator(keyName));
}
}
Response response;
try {
response = buildLogoutResponse(userSession, logoutBindingUri, builder, binding);
} catch (ConfigurationException | ProcessingException | IOException e) {
throw new RuntimeException(e);
}
if (logoutBindingUri != null) {
event.detail(Details.REDIRECT_URI, logoutBindingUri);
}
event.event(EventType.LOGOUT).detail(Details.AUTH_METHOD, userSession.getAuthMethod()).client(session.getContext().getClient()).user(userSession.getUser()).session(userSession).detail(Details.USERNAME, userSession.getLoginUsername()).detail(Details.RESPONSE_MODE, postBinding ? SamlProtocol.SAML_POST_BINDING : SamlProtocol.SAML_REDIRECT_BINDING).detail(SamlProtocol.SAML_LOGOUT_REQUEST_ID, userSession.getNote(SAML_LOGOUT_REQUEST_ID)).success();
return response;
}
use of org.keycloak.saml.common.exceptions.ProcessingException in project keycloak by keycloak.
the class SamlProtocol method frontchannelLogout.
@Override
public Response frontchannelLogout(UserSessionModel userSession, AuthenticatedClientSessionModel clientSession) {
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
try {
boolean postBinding = isLogoutPostBindingForClient(clientSession);
String bindingUri = getLogoutServiceUrl(session, client, postBinding ? SAML_POST_BINDING : SAML_REDIRECT_BINDING, false);
if (bindingUri == null) {
logger.warnf("Failed to logout client %s, skipping this client. Please configure the logout service url in the admin console for your client applications.", client.getClientId());
return null;
}
NodeGenerator[] extensions = new NodeGenerator[] {};
if (!postBinding) {
if (samlClient.requiresRealmSignature() && samlClient.addExtensionsElementWithKeyInfo()) {
KeyManager.ActiveRsaKey keys = session.keys().getActiveRsaKey(realm);
String keyName = samlClient.getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate());
extensions = new NodeGenerator[] { new KeycloakKeySamlExtensionGenerator(keyName) };
}
}
LogoutRequestType logoutRequest = createLogoutRequest(bindingUri, clientSession, client, extensions);
JaxrsSAML2BindingBuilder binding = createBindingBuilder(samlClient, "true".equals(clientSession.getNote(JBossSAMLURIConstants.SAML_HTTP_ARTIFACT_BINDING.get())));
// If this session uses artifact binding, send an artifact instead of the LogoutRequest
if ("true".equals(clientSession.getNote(JBossSAMLURIConstants.SAML_HTTP_ARTIFACT_BINDING.get())) && useArtifactForLogout(client)) {
clientSession.setAction(CommonClientSessionModel.Action.LOGGING_OUT.name());
return buildArtifactAuthenticatedResponse(clientSession, bindingUri, logoutRequest, binding);
}
Document samlDocument = SAML2Request.convert(logoutRequest);
if (postBinding) {
// This is POST binding, hence KeyID is included in dsig:KeyInfo/dsig:KeyName, no need to add <samlp:Extensions> element
return binding.postBinding(samlDocument).request(bindingUri);
} else {
logger.debug("frontchannel redirect binding");
return binding.redirectBinding(samlDocument).request(bindingUri);
}
} catch (ConfigurationException | ProcessingException | IOException | ParsingException e) {
throw new RuntimeException(e);
}
}
use of org.keycloak.saml.common.exceptions.ProcessingException in project keycloak by keycloak.
the class SamlProtocol method buildLogoutArtifactResponse.
/**
* This method, instead of sending the actual response with the token, sends
* the artifact message via post or redirect. This method is only to be used for the final LogoutResponse.
*
* @param userSession The current user session being logged out
* @param redirectUri the redirect uri to the client
* @param statusResponseType a Document containing the saml Response
* @param bindingBuilder the current JaxrsSAML2BindingBuilder configured with information for signing and encryption
* @return A response (POSTed form or redirect) with a newly generated artifact
* @throws ProcessingException
* @throws IOException
*/
protected Response buildLogoutArtifactResponse(UserSessionModel userSession, String redirectUri, StatusResponseType statusResponseType, JaxrsSAML2BindingBuilder bindingBuilder) throws ProcessingException, ConfigurationException {
try {
String artifact = buildArtifactAndStoreResponse(statusResponseType, userSession);
String relayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE);
logger.debugf("Sending artifact for LogoutResponse %s to user %s", artifact, userSession.getLoginUsername());
if (isLogoutPostBindingForInitiator(userSession)) {
return artifactPost(redirectUri, artifact, relayState, bindingBuilder);
} else {
return artifactRedirect(redirectUri, artifact, relayState);
}
} catch (ArtifactResolverProcessingException e) {
throw new ProcessingException(e);
}
}
use of org.keycloak.saml.common.exceptions.ProcessingException in project keycloak by keycloak.
the class SamlService method emptyArtifactResponseMessage.
private Response emptyArtifactResponseMessage(ArtifactResolveType artifactResolveMessage, ClientModel clientModel, URI responseStatusCode) throws ProcessingException, ConfigurationException {
ArtifactResponseType artifactResponse = SamlProtocolUtils.buildArtifactResponse(null, SAML2NameIDBuilder.value(RealmsResource.realmBaseUrl(session.getContext().getUri()).build(realm.getName()).toString()).build(), responseStatusCode);
Document artifactResponseDocument;
try {
artifactResponseDocument = SamlProtocolUtils.convert(artifactResponse);
} catch (ParsingException | ConfigurationException | ProcessingException e) {
logger.errorf("Failed to obtain document from ArtifactResponse: %s.", artifactResponse);
throw new ProcessingException(Errors.INVALID_SAML_ARTIFACT_RESPONSE, e);
}
return artifactResponseMessage(artifactResolveMessage, artifactResponseDocument, clientModel);
}
Aggregations