Hello,
I am operating CAS 6.2.x as SAML2 IdP. One of our SP needs to get
more complex structure in the attribute statements, basically
something like this:
<saml2:Attribute FriendlyName="groups" Name="groups"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue>
<Group code="bla1" displayName="bla1"/>
</saml2:AttributeValue>
<saml2:AttributeValue>
<Group code="bla2" displayName="bla2"/>
</saml2:AttributeValue>
...
</saml2:Attribute>
This should be possible by defining attribute "groups" with type
XSObject and CAS should then marshall it as a XML document inside
the values.
https://apereo.github.io/cas/6.2.x/installation/Configuring-SAML2-Attribute-Release.html
I am struggling in getting the setup to work... could somebody point
me to the right direction, please?
Cheers,
The result i am getting:
<saml2:Attribute FriendlyName="groups" Name="groups"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue><String>Group@2abf08d0</String></saml2:AttributeValue>
<saml2:AttributeValue><String>Group@86c9d74</String></saml2:AttributeValue>
<saml2:AttributeValue><String>Group@5bdf462c</String></saml2:AttributeValue>
<saml2:AttributeValue><String>Group@6715cd46</String></saml2:AttributeValue>
</saml2:Attribute>
Part of CAS log:
2022-02-10 14:09:36,169 TRACE
[org.apereo.cas.support.saml.util.AbstractSamlObjectBuilder] -
<Attempting to generate SAML attribute [groups] with value(s)
[[Role@2abf08d0, Group@86c9d74, Group@5bdf462c, Group@6715cd46]]>
2022-02-10 14:09:36,169 DEBUG
[org.apereo.cas.support.saml.util.AbstractSamlObjectBuilder] -
<Generating multi-valued SAML attribute [groups] with values
[[Group@2abf08d0, Group@86c9d74, Group@5bdf462c,
Group@6715cd46]]>
2022-02-10 14:09:36,169 TRACE
[org.apereo.cas.support.saml.util.AbstractSamlObjectBuilder] -
<Creating new attribute value XMLObject for value:
[Group@2abf08d0], value type: [XSObject], QName:
[{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue]>
2022-02-10 14:09:36,225 TRACE
[org.apereo.cas.support.saml.util.AbstractSamlObjectBuilder] -
<Created attribute value XMLObject:
[org.opensaml.core.xml.schema.impl.XSAnyImpl@a859946]>
2022-02-10 14:09:36,225 TRACE
[org.opensaml.core.xml.AbstractXMLObject] - <Releasing cached DOM
reprsentation for parent of
{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue with
propagation set to true>
2022-02-10 14:09:36,225 TRACE
[org.opensaml.core.xml.AbstractXMLObject] - <Releasing cached DOM
reprsentation for
{urn:oasis:names:tc:SAML:2.0:assertion}Attribute>
2022-02-10 14:09:36,225 TRACE
[org.opensaml.core.xml.AbstractXMLObject] - <Releasing cached DOM
reprsentation for parent of
{urn:oasis:names:tc:SAML:2.0:assertion}Attribute with propagation
set to true>
My setup:
1. LDAP server configured as attribute repository, each user has a
"memberOf" attribute. This works, CAS can see the "memberOf".
2. I have a set of attributes produced by CAS, defined at service
level. They are produced by inline groovy (works fine) with Mapped
release policy.
3. Attribute "groups" produced by an external groovy script and
GroovySaml policy. This script takes "memberOf" and creates an array
of custom objects called Group. Script executes fine, but objects
and not properly marshalled into SAML response.
Relevant part of service definition:
"attributeReleasePolicy":
{
"@class": "org.apereo.cas.services.ChainingAttributeReleasePolicy",
"mergingPolicy": "add",
"policies": [ "java.util.ArrayList",
[
{
"@class":
"org.apereo.cas.services.ReturnMappedAttributeReleasePolicy",
"allowedAttributes": {
"@class": "java.util.TreeMap",
"attr1": "groovy { return 'val1' }",
"attr2": "groovy { return 'val2' }"
},
"principalAttributesRepository":
{
"@class":
"org.apereo.cas.authentication.principal.DefaultPrincipalAttributesRepository",
"mergingStrategy": "MULTIVALUED",
"ignoreResolvedAttributes": false
}
},
{
"@class":
"org.apereo.cas.support.saml.services.GroovySamlRegisteredServiceAttributeReleasePolicy",
"groovyScript":
"file:/etc/cas/config/groups-SAML.groovy",
"order": 1
}
]
],
"excludeDefaultAttributes": "true",
"authorizedToReleaseAuthenticationAttributes": "false",
"order": 0
},
"attributeValueTypes":
{
"@class": "java.util.LinkedHashMap",
"groups": "XSObject"
}
Relevant part of groups-SAML.groovy script:
def Map<String, Object> run(final Object... args) {
def attributes = args[0];
def service = args[1];
def resolver = args[2];
def facade = args[3];
def entityDescriptor = args[4];
def applicationContext = args[5];
def logger = args[6];
LinkedHashMap<String,Object> res = new
LinkedHashMap<String,Object>();
ArrayList<Object> vals = new ArrayList<Object>();
for (o : attributes["memberOf"]) {
String s = parseName((String) o);
Group r = new Group(s);
vals.add(r);
}
res.put("groups",vals);
return res;
}
class Group extends XSAnyImpl {
private String textContent = null;
private LinkedHashMap<QName,String> unknownAttributes;
private IndexedXMLObjectChildrenList<XMLObject>
unknownXMLObjects = null;
public Group(String s) {
//
https://javadoc.io/static/org.opensaml/opensaml-core/3.4.3/org/opensaml/core/xml/schema/impl/XSAnyImpl.html
//
https://docs.oracle.com/javase/7/docs/api/javax/xml/namespace/QName.html?is-external=true
super("blablabla","Group",null);
this.unknownAttributes = new
LinkedHashMap<QName,String>();
this.unknownAttributes.put(new QName("code"), s);
this.unknownAttributes.put(new QName("displayName"), s);
}
}