Hi,
We are using AEM6.5 version, I would a mechanism to capture the saml response in JAVA code .
I would need to read data like email id , username like first and last name, other details which are part of saml response. I would want to capture in java code to do other processing checks
Any sample code that I could use, will be very helpful
Regards,
Srinivas
Solved! Go to Solution.
Views
Replies
Total Likes
Dear @srinivas_chann1
You may refer to the below sample code here
@Component(immediate = true, metatype = false) @Service public class SAMLResponsePostProcessor implements AuthenticationInfoPostProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(SAMLResponsePostProcessor.class); @Reference private SlingSettingsService slingSettingsService; public void postProcess(AuthenticationInfo info, HttpServletRequest request, HttpServletResponse response) throws LoginException { HttpServletResponse httpResponse = null; HttpServletRequest httpRequest = null; try { LOGGER.info("SAMLResponse Post Processor invoked"); httpResponse = response; httpRequest = request; String pathInfo = httpRequest.getPathInfo(); Set<String> runModes = slingSettingsService.getRunModes(); if (runModes.contains("publish") && StringUtils.isNotEmpty(pathInfo) && pathInfo.contains("saml_login")) { LOGGER.info("SAMLResponse Post Processor processing ..."); String responseSAMLMessage = httpRequest.getParameter("saml_login"); if (StringUtils.isNotEmpty(responseSAMLMessage)) { LOGGER.debug("responseSAMLMessage:" + responseSAMLMessage); String base64DecodedResponse = decodeStr(responseSAMLMessage); LOGGER.debug("base64DecodedResponse:" + base64DecodedResponse); parseSAMLResponse(httpResponse, httpRequest, runModes, base64DecodedResponse); } else { LOGGER.info("responseSAMLMessage is empty or null"); } } } catch (ParserConfigurationException e) { LOGGER.error("Unable to get Document Builder ", e); } catch (SAXException e) { LOGGER.error("Unable to parse the xml document ", e); } catch (IOException e) { LOGGER.error("IOException ", e); } } /** * This method will parse the SAML response to create the Cookie by reading the attributes. * * @param httpResponse * @param httpRequest * @param runModes * @param base64DecodedResponse * @throws ParserConfigurationException * @throws SAXException * @throws IOException * @throws UnsupportedEncodingException */ private void parseSAMLResponse(HttpServletResponse httpResponse, HttpServletRequest httpRequest, Set<String> runModes, String base64DecodedResponse) throws ParserConfigurationException, SAXException, IOException, UnsupportedEncodingException { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder(); Map<String, String> samlAttributeMap = new HashMap<String, String>(); StringReader strReader = new StringReader(base64DecodedResponse); InputSource inputSource = new InputSource(strReader); Document document = docBuilder.parse(inputSource); NodeList samlAssertion = document.getElementsByTagName("saml:Assertion"); populateSAMLAttrMap(samlAttributeMap, samlAssertion); } /** * This method would populate the SAML attribute map object based on the attributes present in the response. * * @param samlAttributeMap * @param samlAssertion */ private void populateSAMLAttrMap(Map<String, String> samlAttributeMap, NodeList samlAssertion) { for (int i = 0; i < samlAssertion.getLength(); i++) { Node item = samlAssertion.item(i); NodeList childNodes = item.getChildNodes(); for (int j = 0; j < childNodes.getLength(); j++) { Node subChildNode = childNodes.item(j); if (subChildNode.getNodeName().equalsIgnoreCase("saml:AttributeStatement")) { NodeList childNodes2 = subChildNode.getChildNodes(); for (int k = 0; k < childNodes2.getLength(); k++) { Node item2 = childNodes2.item(k); if (item2.getNodeName().equalsIgnoreCase("saml:Attribute")) { String attributeValue = item2.getAttributes().item(0).getNodeValue(); NodeList attributeValueNodeList = item2.getChildNodes(); for (int l = 0; l < attributeValueNodeList.getLength(); l++) { if (attributeValueNodeList.item(l).getNodeName() .equalsIgnoreCase("saml:AttributeValue")) { samlAttributeMap.put(attributeValue, attributeValueNodeList.item(l).getTextContent()); } } } } } } } } /** * This method would decode the SAML response. * * @param encodedStr * @return */ public static String decodeStr( String encodedStr) { String decodedXML = ""; org.apache.commons.codec.binary.Base64 base64Decoder = new org.apache.commons.codec.binary.Base64(); byte[] xmlBytes = encodedStr.getBytes(); byte[] base64DecodedByteArray = base64Decoder.decode(xmlBytes); decodedXML = new String(base64DecodedByteArray); return decodedXML; } }
Hope that helps!
Regards,
Santosh
Dear @srinivas_chann1
You may refer to the below sample code here
@Component(immediate = true, metatype = false) @Service public class SAMLResponsePostProcessor implements AuthenticationInfoPostProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(SAMLResponsePostProcessor.class); @Reference private SlingSettingsService slingSettingsService; public void postProcess(AuthenticationInfo info, HttpServletRequest request, HttpServletResponse response) throws LoginException { HttpServletResponse httpResponse = null; HttpServletRequest httpRequest = null; try { LOGGER.info("SAMLResponse Post Processor invoked"); httpResponse = response; httpRequest = request; String pathInfo = httpRequest.getPathInfo(); Set<String> runModes = slingSettingsService.getRunModes(); if (runModes.contains("publish") && StringUtils.isNotEmpty(pathInfo) && pathInfo.contains("saml_login")) { LOGGER.info("SAMLResponse Post Processor processing ..."); String responseSAMLMessage = httpRequest.getParameter("saml_login"); if (StringUtils.isNotEmpty(responseSAMLMessage)) { LOGGER.debug("responseSAMLMessage:" + responseSAMLMessage); String base64DecodedResponse = decodeStr(responseSAMLMessage); LOGGER.debug("base64DecodedResponse:" + base64DecodedResponse); parseSAMLResponse(httpResponse, httpRequest, runModes, base64DecodedResponse); } else { LOGGER.info("responseSAMLMessage is empty or null"); } } } catch (ParserConfigurationException e) { LOGGER.error("Unable to get Document Builder ", e); } catch (SAXException e) { LOGGER.error("Unable to parse the xml document ", e); } catch (IOException e) { LOGGER.error("IOException ", e); } } /** * This method will parse the SAML response to create the Cookie by reading the attributes. * * @param httpResponse * @param httpRequest * @param runModes * @param base64DecodedResponse * @throws ParserConfigurationException * @throws SAXException * @throws IOException * @throws UnsupportedEncodingException */ private void parseSAMLResponse(HttpServletResponse httpResponse, HttpServletRequest httpRequest, Set<String> runModes, String base64DecodedResponse) throws ParserConfigurationException, SAXException, IOException, UnsupportedEncodingException { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder(); Map<String, String> samlAttributeMap = new HashMap<String, String>(); StringReader strReader = new StringReader(base64DecodedResponse); InputSource inputSource = new InputSource(strReader); Document document = docBuilder.parse(inputSource); NodeList samlAssertion = document.getElementsByTagName("saml:Assertion"); populateSAMLAttrMap(samlAttributeMap, samlAssertion); } /** * This method would populate the SAML attribute map object based on the attributes present in the response. * * @param samlAttributeMap * @param samlAssertion */ private void populateSAMLAttrMap(Map<String, String> samlAttributeMap, NodeList samlAssertion) { for (int i = 0; i < samlAssertion.getLength(); i++) { Node item = samlAssertion.item(i); NodeList childNodes = item.getChildNodes(); for (int j = 0; j < childNodes.getLength(); j++) { Node subChildNode = childNodes.item(j); if (subChildNode.getNodeName().equalsIgnoreCase("saml:AttributeStatement")) { NodeList childNodes2 = subChildNode.getChildNodes(); for (int k = 0; k < childNodes2.getLength(); k++) { Node item2 = childNodes2.item(k); if (item2.getNodeName().equalsIgnoreCase("saml:Attribute")) { String attributeValue = item2.getAttributes().item(0).getNodeValue(); NodeList attributeValueNodeList = item2.getChildNodes(); for (int l = 0; l < attributeValueNodeList.getLength(); l++) { if (attributeValueNodeList.item(l).getNodeName() .equalsIgnoreCase("saml:AttributeValue")) { samlAttributeMap.put(attributeValue, attributeValueNodeList.item(l).getTextContent()); } } } } } } } } /** * This method would decode the SAML response. * * @param encodedStr * @return */ public static String decodeStr( String encodedStr) { String decodedXML = ""; org.apache.commons.codec.binary.Base64 base64Decoder = new org.apache.commons.codec.binary.Base64(); byte[] xmlBytes = encodedStr.getBytes(); byte[] base64DecodedByteArray = base64Decoder.decode(xmlBytes); decodedXML = new String(base64DecodedByteArray); return decodedXML; } }
Hope that helps!
Regards,
Santosh
Hi Santosh,
Thanks for the reply with sample code.
Need one more information. How will this component be invoked by saml response after login.
I see entries in our code base like
com.adobe.granite.auth.saml.SamlAuthenticationHandler-app1.xml , we have like this 4 apps,I meant app1,app2,app3,app4.
I also see the as soon as the user logs in it creates a Node for the user details under /home with rep:user.
But don't see any entries in com.adobe.granite.auth.saml.SamlAuthenticationHandler-app1.xml for user creation under
/home with rep:user.
So how is that the above sample code will be hit when we saml login happnes
Please provide inputs
Thanks,
Srinivas