Getting IdP attributes from proxy IdP
Christopher Bongaarts
cab at umn.edu
Wed Jan 31 23:25:43 UTC 2024
I'm trying to check the contents of an attribute returned from a proxied
IdP (Okta) using the authn/SAML flow to influence the
AuthnContextClassRef to be returned to the originating SP. The values
come back OK from the Okta IdP, but I'm having a bit of trouble on the
scripting (Nashorn) end. Here is the script (with a fair bit of
debugging noise unfortunately, and a workaround for the AttributeContext
location since we're still on 4.1.7):
<property name="authnContextTranslationStrategyEx">
<bean parent="shibboleth.Functions.Scripted"
factory-method="inlineScript"
p:inputType="org.opensaml.profile.context.ProfileRequestContext"
p:outputType="java.util.Collection" >
<property name="customObject">
<bean parent="shibboleth.SAML2AuthnContextClassRef"
c:_0="https://refeds.org/profile/mfa"/>
</property>
<constructor-arg>
<value>
<![CDATA[
logger =
Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.attribute.resolver.amr");
logger.debug("authnContextTranslationStrategyEx: {}",
custom.getName());
var Principal =
Java.type("net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal");
var IdpAttribute =
Java.type("net.shibboleth.idp.attribute.IdPAttribute");
var ArrayList = Java.type("java.util.ArrayList");
//logger.debug("got profile req context: {}", input);
//for each (sub in input) {
// logger.debug("Found prc subcontext {}", sub.class)
//}
authnContext =
input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
//logger.debug("got authn context: {}", authnContext);
prc =
authnContext.getSubcontext("org.opensaml.profile.context.ProfileRequestContext");
//logger.debug("got nested pr context: {}", prc);
rp =
prc.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext");
//logger.debug("got rp context: {}", rp);
attrContext =
rp.getSubcontext("net.shibboleth.idp.attribute.context.AttributeContext");
//logger.debug("got attr context: {}", attrContext);
attrs = attrContext.getIdPAttributes();
logger.debug("got typeof attrs: {}", attrs);
amrs = attrs.get("amr");
logger.debug("got amrs type: {}", typeof amrs);
logger.debug("got amrs: {}", amrs);
amrvals = amrs.values;
logger.debug("got amrvals: {}", amrvals);
amrvals = amrs.getValues();
logger.debug("got amrvals2: {}", amrvals);
result = new ArrayList();
if (amrs.contains("mfa")) {
result.add(new
Principal("https://refeds.org/profile/mfa"));
result.add(new
Principal("https://www.umn.edu/shibboleth/classes/authncontext/duo"));
} else {
result.add(new
Principal("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"));
}
result;
]]>
</value>
</constructor-arg>
</bean>
</property>
This fails because Nashorn can't figure out that what is being returned
from the getIdPAttributes() method is a Map<String,IdpAttribute> (since
it doesn't have a concept of generics), and there doesn't appear to be a
way to cast/coerce the type after the fact:
2024-01-31 16:17:40,006 - 128.101.xx.yy - DEBUG
[net.shibboleth.idp.saml.saml2.profile.impl.ValidateSAMLAuthentication:427]
- Profile Action ValidateSAMLAuthentication: Incoming SAML Attributes
mapped to attribute IDs: [amr, uid]
2024-01-31 16:17:40,031 - 128.101.xx.yy - DEBUG
[net.shibboleth.idp.attribute.resolver.amr:2] -
authnContextTranslationStrategyEx: https://refeds.org/profile/mfa
2024-01-31 16:17:40,057 - 128.101.xx.yy - DEBUG
[net.shibboleth.idp.attribute.resolver.amr:20] - got typeof attrs:
{uid=IdPAttribute{id=uid, displayNames={}, displayDescriptions={},
values=[StringAttributeValue{value=cab}]}, amr=IdPAttribute{id=amr,
displayNames={}, displayDescriptions={},
values=[StringAttributeValue{value=okta_verify},
StringAttributeValue{value=swk}]}}
2024-01-31 16:17:40,060 - 128.101.xx.yy - DEBUG
[net.shibboleth.idp.attribute.resolver.amr:22] - got amrs type: object
2024-01-31 16:17:40,064 - 128.101.xx.yy - DEBUG
[net.shibboleth.idp.attribute.resolver.amr:23] - got amrs:
IdPAttribute{id=amr, displayNames={}, displayDescriptions={},
values=[StringAttributeValue{value=okta_verify},
StringAttributeValue{value=swk}]}
2024-01-31 16:17:40,069 - 128.101.xx.yy - DEBUG
[net.shibboleth.idp.attribute.resolver.amr:25] - got amrvals:
[StringAttributeValue{value=okta_verify}, StringAttributeValue{value=swk}]
2024-01-31 16:17:40,072 - 128.101.xx.yy - DEBUG
[net.shibboleth.idp.attribute.resolver.amr:27] - got amrvals2:
[StringAttributeValue{value=okta_verify}, StringAttributeValue{value=swk}]
2024-01-31 16:17:40,073 - 128.101.xx.yy - DEBUG
[org.springframework.webflow.engine.impl.FlowExecutionImpl:592] -
Attempting to handle
[org.springframework.webflow.execution.ActionExecutionException:
Exception thrown executing
net.shibboleth.idp.saml.saml2.profile.impl.ValidateSAMLAuthentication at 4f0120af
in state 'ProcessResponse' of flow 'authn/SAML' -- action execution
attributes were 'map[[empty]]'] with root cause [<eval>:30 TypeError:
amrs.contains is not a function]
It looks like I can dig into the object "manually" (since I can fairly
confidently assume that the values are all StringAttributeValues in this
case) but is there a better way to do "is attribute value X among the
attribute values for attribute Y"?
--
%% Christopher A. Bongaarts %% cab at umn.edu %%
%% OIT - Identity Management %% http://umn.edu/~cab %%
%% University of Minnesota %% +1 (612) 625-1809 %%
More information about the users
mailing list