Friday, September 2, 2016

SAML Multi Valued Attributes in WSO2 Servers - Retrieving Role Claim of Users as a Single or Multi Valued attribute

In my previous article [1], I explained how to retrieve user claims [2] in the SAML response when a relying party application uses SAML authentication with WSO2 Identity Server.  In this article, I am explaining the Single and Multi Valued attributes in SAML protocol and how to deal with them in WSO2 servers.

In the SAML authentication flow, the Identity Provider sends the SAML response to the relying party upon successful authentication. In order to identify the logged in user, the Subject of the SAML assertion can be used by the relying party. If the relying party needs to know more information about the logged in user (first name, last name, roles etc.), Identity Provider can include those attributes in the SAML AttributeStatement in the assertion.

There are user attributes with single values and also multiple values. For example, the lastname of a user would be a single value which would be represented as given below in the SAML response.

<saml2:Attribute Name="lastname">
    <saml2:AttributeValue>Edirisinghe</saml2:AttributeValue>
</saml2:Attribute>

A a user may have multiple roles granted.

Therefore, in the SAML response  can be included as following.

<saml2:Attribute Name="role">
    <saml2:AttributeValue>admin</saml2:AttributeValue>
    <saml2:AttributeValue>developer</saml2:AttributeValue>
    <saml2:AttributeValue>manager</saml2:AttributeValue>
    <saml2:AttributeValue>Internal/everyone</saml2:AttributeValue>
</saml2:Attribute>

Now since you know the difference between single and multi valued attributes, let’s see how it is used for the role claim of WSO2 Identity Server.

In WSO2 Identity Server 5.0.0 version, by default all the user roles were sent in a single value attribute as shown below where the roles were separated by a comma (,).

<saml2:Attribute Name="http://wso2.org/claims/role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
   <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
      admin,Internal/everyone,manager,tester
    </saml2:AttributeValue>
</saml2:Attribute>

When comes to WSO2 Identity Server 5.1.0, this behavior is changed where, by default the roles are treated as a multi valued attribute as given below.

<saml2:Attribute Name="http://wso2.org/claims/role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
   <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
      admin
   </saml2:AttributeValue>
   <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
      Internal/everyone
   </saml2:AttributeValue>
   <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
              manager
   </saml2:AttributeValue>
   <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
              tester
   </saml2:AttributeValue>
</saml2:Attribute>


If you had been using Identity Server 5.0.0 and migrate it to the 5.1.0 version, the relying party would not be able to identify the role claim properly, when processing the SAML response sent by the Identity Server.

In that case, you can achieve the same behavior where to retrieve all user roles in a single valued attribute. This is can be done through a property.

You need to add the property MultiAttributeSeparator in the userstore configuration where the user is in. If the user is in the PRIMARY userstore, you need to configure this in SERVER_HOME/repository/conf/user-mgt.xml file under the particular userstore configuration. If the user is located in a secondary userstore [3], you need to add the property in the particular configuration file located in SERVER_HOME/repository/deployment/server/userstores directory.

Role claim in a Multi Valued attribute
<Property name="MultiAttributeSeparator">,</Property>
Role claim in a Single Valued attribute
<Property name="MultiAttributeSeparator">,,</Property>

This question was raised in Stack Overflow [4] and I hope this article would be useful for those who face the same problem.

References



Tharindu Edirisinghe
Platform Security Team
WSO2

3 comments:

  1. I suppose that it is not the proper place and time to pose a question but...

    We have the following setup with two WSO2 Identity Server 5.3.0:

    WSO2 Identity Server IS1: Sending authentication requests to others IdPs

    WSO2 IDentity Server IS2: doing authentication

    IS1 is configured as a Service Provider in IS2, defining in the Claim Configuration the claim "http://wso2.org/claims/role" as mandatory (and other claims also as mandatory)

    IS2 in configured as Identity Provider in IS1, defining in the Claim Configuration, Advanced Claim Configuration, additional claims with default values

    A Service Provider defined in IS1 is authenticating using SAML with IS2

    IS2 returns the role claim as a multi valued attribute (seen with SAML tracer) but the role is returned to the SP as single valued attribute.

    All the claims defined as mandatory in the configuration of IS1 as SP in IS2, as well as all the claims with default values in the configuration of IS2 as Identity Provider in IS1 are returned correctly, only the role claim (the only multi valued claim) is converted to single valued to the SAML response of ID1 to SP.

    If the claim "http://wso2.org/claims/role" is added in the Claim Configuration of the SP, the role is returned to the SP as a multi valued attribute, but is the only claim provided in the response. All the claims defined as mandatory in the configuration of IS1 as SP in IS2, as well as all the claims with default values in the configuration of IS2 as Identity Provider in IS1 are not included.

    It should not be necessary to add al the claims to return in the Claim Configuration of the SP given that, without it, the claims are returned, albeit with the role claim converted to single valued.

    ¿What configuration is missing?

    Thanks

    ReplyDelete
    Replies
    1. Let me check this scenario and get back to you soon.

      Delete
    2. Hi

      I am the same "Anonymous" ;-)

      In the method buildAttributeStatement in [2], to check if the claim has multiple values, the value of IdentityCoreConstants.MULTI_ATTRIBUTE_SEPARATOR_DEFAULT [1] is used by default (if there is not a claim with name IdentityCoreConstants.MULTI_ATTRIBUTE_SEPARATOR).

      If the claim value contains the separator, then it is built as a multi valued attribute, otherwise it is built as single value attribute with the separator being the one specified in the property "MultiAttributeSeparator" in the userstore configuration.

      As the default value of the property (",") is different to the constant IdentityCoreConstants.MULTI_ATTRIBUTE_SEPARATOR_DEFAULT, the attribute is build as single valued

      The workaround is to change the property "MultiAttributeSeparator" in the userstore configuration to ",,,"

      The problem is that the class (i did not search which) that constructs the Map with the claims does not add a claim with the name of IdentityCoreConstants.MULTI_ATTRIBUTE_SEPARATOR (which is the same as the name of the property "MultiAttributeSeparator" in the userstore configuration) indicating which was the separator used.

      I hope this information is useful.

      Thanks

      [1] IdentityCoreConstants.java
      [https://github.com/wso2/carbon-identity-framework/blob/master/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityCoreConstants.java]

      [2] DefaultSAMLAssertionBuilder.java
      [https://github.com/wso2-extensions/identity-inbound-auth-saml/blob/5.4.x/components/org.wso2.carbon.identity.sso.saml/src/main/java/org/wso2/carbon/identity/sso/saml/builders/assertion/DefaultSAMLAssertionBuilder.java]

      Delete