authenticationazure-active-directorysalesforceprovisioning

How can I receive all roles relating to an Azure application when authenticating with SAML?


I am trying to handle user provisioning in Salesforce. We have decided that we should use a combination of Salesforce JIT (Just-in-time) and Azures provisioning. In order to correctly provision the user I need to send an Auth request to Azure and then Azure returns a payload with various information about that user. Right now it is returning Roles, but it is only returning 1 role.

A user can be in multiple groups that each have different roles in the application. I want to know, is there a way to get Azure to return all the roles a user has in that application after the user has been authenticated?

I have tried looking up documentation but I'm struggling to find something that can point me in the right direction. If you have docs that could help please send them.


Solution

  • I resolved this issue. Long story short, it was the way Salesforce was handling the assertion string in the handleJit method in the JIT Handler class. You need to create a method that will decode the assertion and allow for multi value fields:

    private static Map<String, List<String>> parseSAMLResponse(String encodedSamlResponse) {
            String decodedResponse = EncodingUtil.base64Decode(encodedSamlResponse).toString();
            Dom.Document doc = new Dom.Document();
            doc.load(decodedResponse);
            Map<String, List<String>> attributes = new Map<String, List<String>>();
            Dom.XMLNode assertionNode = doc.getRootElement().getChildElement('Assertion', 'urn:oasis:names:tc:SAML:2.0:assertion');
            if (assertionNode != null) {
                Dom.XMLNode attributeStatementNode = assertionNode.getChildElement('AttributeStatement', 'urn:oasis:names:tc:SAML:2.0:assertion');
                if (attributeStatementNode != null) {
                    List<Dom.XMLNode> attributeNodes = attributeStatementNode.getChildElements();
                    for (Dom.XMLNode attributeNode : attributeNodes) {
                        String attributeName = attributeNode.getAttribute('Name', null);
                        List<Dom.XMLNode> valueNodes = attributeNode.getChildElements();
    
                        List<String> values = new List<String>();
    
                        for (Dom.XMLNode valueNode : valueNodes) {
                            if (valueNode.getName() == 'AttributeValue') {
                                values.add(valueNode.getText());
                            }
                        }
                        if (!values.isEmpty()) {
                            attributes.put(attributeName, values);
                        }
                    }
                }
            }
            return attributes;
        }
    

    Then make sure to call this and adjust the other methods to take a Map<String, List> or something along those lines, then you can handle multiple roles/groups in the provisioning process :)