use of org.keycloak.saml.SignatureAlgorithm in project keycloak by keycloak.
the class AbstractSamlAuthenticationHandler method verifyRedirectBindingSignature.
private void verifyRedirectBindingSignature(String paramKey, KeyLocator keyLocator, String keyId) throws VerificationException {
String request = facade.getRequest().getQueryParamValue(paramKey);
String algorithm = facade.getRequest().getQueryParamValue(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
String signature = facade.getRequest().getQueryParamValue(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
String decodedAlgorithm = facade.getRequest().getQueryParamValue(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
if (request == null) {
throw new VerificationException("SAML Request was null");
}
if (algorithm == null)
throw new VerificationException("SigAlg was null");
if (signature == null)
throw new VerificationException("Signature was null");
// Shibboleth doesn't sign the document for redirect binding.
// todo maybe a flag?
String relayState = facade.getRequest().getQueryParamValue(GeneralConstants.RELAY_STATE);
KeycloakUriBuilder builder = KeycloakUriBuilder.fromPath("/").queryParam(paramKey, request);
if (relayState != null) {
builder.queryParam(GeneralConstants.RELAY_STATE, relayState);
}
builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, algorithm);
String rawQuery = builder.build().getRawQuery();
try {
// byte[] decodedSignature = RedirectBindingUtil.urlBase64Decode(signature);
byte[] decodedSignature = Base64.decode(signature);
byte[] rawQueryBytes = rawQuery.getBytes("UTF-8");
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm);
if (!validateRedirectBindingSignature(signatureAlgorithm, rawQueryBytes, decodedSignature, keyLocator, keyId)) {
throw new VerificationException("Invalid query param signature");
}
} catch (Exception e) {
throw new VerificationException(e);
}
}
use of org.keycloak.saml.SignatureAlgorithm 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.SignatureAlgorithm in project keycloak by keycloak.
the class SamlProtocolUtils method verifyRedirectSignature.
public static void verifyRedirectSignature(SAMLDocumentHolder documentHolder, KeyLocator locator, MultivaluedMap<String, String> encodedParams, String paramKey) throws VerificationException {
String request = encodedParams.getFirst(paramKey);
String algorithm = encodedParams.getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
String signature = encodedParams.getFirst(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
String relayState = encodedParams.getFirst(GeneralConstants.RELAY_STATE);
if (request == null)
throw new VerificationException("SAM was null");
if (algorithm == null)
throw new VerificationException("SigAlg was null");
if (signature == null)
throw new VerificationException("Signature was null");
String keyId = getMessageSigningKeyId(documentHolder.getSamlObject());
// Shibboleth doesn't sign the document for redirect binding.
// todo maybe a flag?
StringBuilder rawQueryBuilder = new StringBuilder().append(paramKey).append("=").append(request);
if (encodedParams.containsKey(GeneralConstants.RELAY_STATE)) {
rawQueryBuilder.append("&" + GeneralConstants.RELAY_STATE + "=").append(relayState);
}
rawQueryBuilder.append("&" + GeneralConstants.SAML_SIG_ALG_REQUEST_KEY + "=").append(algorithm);
String rawQuery = rawQueryBuilder.toString();
try {
byte[] decodedSignature = RedirectBindingUtil.urlBase64Decode(signature);
String decodedAlgorithm = RedirectBindingUtil.urlDecode(encodedParams.getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY));
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm);
// todo plugin signature alg
Signature validator = signatureAlgorithm.createSignature();
Key key = locator.getKey(keyId);
if (key instanceof PublicKey) {
validator.initVerify((PublicKey) key);
validator.update(rawQuery.getBytes("UTF-8"));
} else {
throw new VerificationException("Invalid key locator for signature verification");
}
if (!validator.verify(decodedSignature)) {
throw new VerificationException("Invalid query param signature");
}
} catch (Exception e) {
throw new VerificationException(e);
}
}
use of org.keycloak.saml.SignatureAlgorithm in project keycloak by keycloak.
the class BasicSamlTest method testSpecialCharsInRelayState.
private void testSpecialCharsInRelayState(String encodedRelayState) throws Exception {
AuthnRequestType loginRep = SamlClient.createLoginRequestDocument(SAML_CLIENT_ID_SALES_POST_SIG, SAML_ASSERTION_CONSUMER_URL_SALES_POST_SIG, getAuthServerSamlEndpoint(REALM_NAME));
Document doc = SAML2Request.convert(loginRep);
URI redirect = Binding.REDIRECT.createSamlUnsignedRequest(getAuthServerSamlEndpoint(REALM_NAME), null, doc).getURI();
String query = redirect.getRawQuery();
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RSA_SHA256;
// now add the relayState
String relayStatePart = encodedRelayState == null ? "" : ("&" + GeneralConstants.RELAY_STATE + "=" + encodedRelayState);
String sigAlgPart = "&" + GeneralConstants.SAML_SIG_ALG_REQUEST_KEY + "=" + Encode.encodeQueryParamAsIs(signatureAlgorithm.getXmlSignatureMethod());
Signature signature = signatureAlgorithm.createSignature();
byte[] sig;
signature.initSign(KeyUtils.privateKeyFromString(SAML_CLIENT_SALES_POST_SIG_PRIVATE_KEY));
signature.update(query.getBytes(GeneralConstants.SAML_CHARSET));
signature.update(relayStatePart.getBytes(GeneralConstants.SAML_CHARSET));
signature.update(sigAlgPart.getBytes(GeneralConstants.SAML_CHARSET));
sig = signature.sign();
String encodedSig = RedirectBindingUtil.base64Encode(sig);
String sigPart = "&" + GeneralConstants.SAML_SIGNATURE_REQUEST_KEY + "=" + Encode.encodeQueryParamAsIs(encodedSig);
new SamlClientBuilder().navigateTo(redirect.toString() + relayStatePart + sigAlgPart + sigPart).assertResponse(statusCodeIsHC(Status.OK)).execute();
}
Aggregations