Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

SAML: last RequestedAttribute is always set to isRequired="false" #8720

Open
localguru opened this issue Nov 4, 2020 · 3 comments
Open

SAML: last RequestedAttribute is always set to isRequired="false" #8720

localguru opened this issue Nov 4, 2020 · 3 comments
Labels
A-SSO Single Sign-On (maybe OIDC) S-Minor Blocks non-critical functionality, workarounds exist. T-Defect Bugs, crashes, hangs, security vulnerabilities, or other reported issues. Z-Help-Wanted We know exactly how to fix this issue, and would be grateful for any contribution

Comments

@localguru
Copy link
Contributor

localguru commented Nov 4, 2020

Description

In the SAML metadata generated under URL /_matrix/saml2/metadata.xml for the last requestedAttribut isRequired is always set to false. If isRequired is evaluated by the IDP, this results in the attribute not being passed from the IDP to the SP.

<ns0:AttributeConsumingService index="1">
 <ns0:ServiceName xml:lang="en">Matrix</ns0:ServiceName>
 <ns0:ServiceDescription xml:lang="en">Matrix</ns0:ServiceDescription>
 <ns0:RequestedAttribute FriendlyName="uid" Name="urn:oid:0.9.2342.19200300.100.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
 <ns0:RequestedAttribute FriendlyName="email" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
 <ns0:RequestedAttribute FriendlyName="displayName" Name="urn:oid:2.16.840.1.113730.3.1.241" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
</ns0:AttributeConsumingService>

Steps to reproduce

  • configure saml2_config in homeserver.yaml
saml2_config:
  [...]
   service:
       sp:
         required_attributes: ["uid", "email", "displayName"]
  • configure saml2-attribute-maps/map.py:
MAP = {
    "identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
    "fro": {
        'urn:oid:0.9.2342.19200300.100.1.1': 'uid',
        'urn:oid:0.9.2342.19200300.100.1.3': 'email',
        'urn:oid:2.16.840.1.113730.3.1.241': 'displayName',
    },
    "to": {
        'uid': 'urn:oid:0.9.2342.19200300.100.1.1',
        'email': 'urn:oid:0.9.2342.19200300.100.1.3',
        'displayName': 'urn:oid:2.16.840.1.113730.3.1.241',
    },
}
  • check your metadata URL /_matrix/saml2/metadata.xml. The last RequestedAttribute, in this example displayName, is set to isRequired="false". I would expect isRequired="true" for all required_attributes.
<ns0:RequestedAttribute FriendlyName="displayName" Name="urn:oid:2.16.840.1.113730.3.1.241" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>

Workaround

As a workaround I have added an optional attribute in the homeserver.yaml. This means that the optional attribute is the last attribute and this one is set to false. I'm not really sure if this is a bug or if my configuration is incorrect.

required_attributes: ["uid", "email", "displayName"]
optional_attributes: ["eduPersonPrincipalName"]

generated metadata URL /_matrix/saml2/metadata.xml:

<ns0:AttributeConsumingService index="1">
 <ns0:ServiceName xml:lang="en">Matrix</ns0:ServiceName>
 <ns0:ServiceDescription xml:lang="en">Matrix</ns0:ServiceDescription>
 <ns0:RequestedAttribute FriendlyName="uid" Name="urn:oid:0.9.2342.19200300.100.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
 <ns0:RequestedAttribute FriendlyName="email" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
 <ns0:RequestedAttribute FriendlyName="displayName" Name="urn:oid:2.16.840.1.113730.3.1.241" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
 <ns0:RequestedAttribute Name="eduPersonPrincipalName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
</ns0:AttributeConsumingService>

Version information

  • synapse 1.22.1 on Ubuntu 18.04 LTS, deb pakage from https://packages.matrix.org/debian/ bionic main
@erikjohnston
Copy link
Member

This seems odd. AFAIK we just pass that config straight through to pysaml2, but will have a dig. What version of pysaml2 are you using?

@erikjohnston
Copy link
Member

erikjohnston commented Nov 5, 2020

Aha, it looks like the default user_mapping_provider automatically adds <mxid_source_attribute> and uid as required attributes (if no required attributes are set) and displayName and email as optional attributes (if no optional parameters are set):

@staticmethod
def get_saml_attributes(config: SamlConfig) -> Tuple[Set[str], Set[str]]:
"""Returns the required attributes of a SAML
Args:
config: A SamlConfig object containing configuration params for this provider
Returns:
The first set equates to the saml auth response
attributes that are required for the module to function, whereas the
second set consists of those attributes which can be used if
available, but are not necessary
"""
return {"uid", config.mxid_source_attribute}, {"displayName", "email"}

So I think what is happening here is that we're creating a metadata file with displayName as both a required and optional attribute, which understandably confuses things. The reason adding optional parameters changes things is simply because that clobbers the default optional parameters.

We should probably do something to correctly remove duplicates between required and optional parameters before passing the config to pysaml2 to actually create the XML metadata. We can either do that while parsing the config, somewhere around here:

_dict_merge(
merge_dict=saml2_config.get("sp_config", {}), into_dict=saml2_config_dict
)

or when we generate the metadata:

metadata_xml = saml2.metadata.create_metadata_string(
configfile=None, config=self.sp_config
)

@erikjohnston erikjohnston added z-bug (Deprecated Label) Z-Help-Wanted We know exactly how to fix this issue, and would be grateful for any contribution A-SSO Single Sign-On (maybe OIDC) labels Nov 5, 2020
@dklimpel
Copy link
Contributor

dklimpel commented Oct 5, 2021

My workaround is to set empty optional_attributes:

    service:
      sp:
        required_attributes: ["uid", "displayName"]
        optional_attributes: []

The result in /_synapse/client/saml2/metadata.xml:

<ns0:RequestedAttribute Name="urn:oid:0.9.2342.19200300.100.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="uid" isRequired="true"/>
<ns0:RequestedAttribute Name="urn:oid:2.16.840.1.113730.3.1.241" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="displayName" isRequired="true"/>

Otherwise:

    service:
      sp:
        required_attributes: ["uid", "displayName"]

The result in /_synapse/client/saml2/metadata.xml:

<ns0:RequestedAttribute Name="urn:oid:0.9.2342.19200300.100.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="uid" isRequired="true"/>
<ns0:RequestedAttribute Name="urn:oid:2.16.840.1.113730.3.1.241" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="displayName" isRequired="true"/>
<ns0:RequestedAttribute Name="urn:oid:2.16.840.1.113730.3.1.241" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="displayName" isRequired="false"/>
<ns0:RequestedAttribute Name="urn:oid:1.2.840.113549.1.9.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="email" isRequired="false"/>

@DMRobertson DMRobertson added T-Defect Bugs, crashes, hangs, security vulnerabilities, or other reported issues. S-Minor Blocks non-critical functionality, workarounds exist. and removed z-bug (Deprecated Label) labels Oct 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A-SSO Single Sign-On (maybe OIDC) S-Minor Blocks non-critical functionality, workarounds exist. T-Defect Bugs, crashes, hangs, security vulnerabilities, or other reported issues. Z-Help-Wanted We know exactly how to fix this issue, and would be grateful for any contribution
Projects
None yet
Development

No branches or pull requests

4 participants