public URI generateRedirectUri(String samlParameterName, String redirectUri, Document document) throws ConfigurationException, ProcessingException, IOException { KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(redirectUri) .replaceQuery(null) .queryParam(samlParameterName, base64Encoded(document)); if (relayState != null) { builder.queryParam("RelayState", relayState); } if (sign) { builder.queryParam( GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getXmlSignatureMethod()); URI uri = builder.build(); String rawQuery = uri.getRawQuery(); Signature signature = signatureAlgorithm.createSignature(); byte[] sig = new byte[0]; try { signature.initSign(signingKeyPair.getPrivate()); signature.update(rawQuery.getBytes("UTF-8")); sig = signature.sign(); } catch (InvalidKeyException | UnsupportedEncodingException | SignatureException e) { throw new ProcessingException(e); } String encodedSig = RedirectBindingUtil.base64URLEncode(sig); builder.queryParam(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, encodedSig); } return builder.build(); }
public void verifyRedirectBindingSignature(PublicKey publicKey, String paramKey) 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); SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm); Signature validator = signatureAlgorithm.createSignature(); // todo plugin signature alg validator.initVerify(publicKey); validator.update(rawQuery.getBytes("UTF-8")); if (!validator.verify(decodedSignature)) { throw new VerificationException("Invalid query param signature"); } } catch (Exception e) { throw new VerificationException(e); } }