Local SSO integration with IdP 5.1.1

Christopher Bongaarts cab at umn.edu
Thu Apr 18 23:49:28 UTC 2024


On 4/17/2024 8:36 AM, Cantor, Scott wrote:
>> How about an entry in the transition map from authn/External to catch
>> NoCredentials (which for me is the "usual" case of no special SSO
>> cookies present) that runs a next flow strategy function that
>> clears/overwrites whatever is getting passed to Password
>> (AuthenticationError/WarningContext? Spring event?)?
> The event should not be messed with. I don't think that the others would be there, but if they are then yes, they could be cleared or removed without hurting anything.

Closing the loop - this seems to be working for me.

mfa-authn-config.xml excerpt:

<entry key=""> <bean parent="shibboleth.authn.MFA.Transition" 
p:nextFlow="authn/External" /> </entry> <entry key="authn/External"> 
<bean parent="shibboleth.authn.MFA.Transition"> <property 
name="nextFlowStrategyMap"> <map> <!-- if external auth succeeded, stop 
here, else goto password --> <entry key="proceed" value="proceed" /> 
<entry key="*" value-ref="clearExternalError" /> </map> </property> 
</bean> </entry> [...] <bean id="clearExternalError" 
parent="shibboleth.ContextFunctions.Scripted" 
factory-method="inlineScript"> <constructor-arg> <value> <![CDATA[ 
authCtx = 
input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext"); 
errCtx = 
authCtx.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationErrorContext"); 
if (errCtx != null) { errs = errCtx.getClassifiedErrors(); if (errs != 
null && errs.contains("NoCredentials")) { 
authCtx.removeSubcontext(errCtx); } } "authn/Password"; // regardless, 
go to password flow next ]]> </value> </constructor-arg> </bean>

------------------------------------------------------------------------
external.jsp:

<%@ page pageEncoding="UTF-8" %> <%@ page 
import="net.shibboleth.idp.authn.ExternalAuthentication" %> <%@ page 
import="net.shibboleth.idp.authn.ExternalAuthenticationException" %> <%@ 
page import="org.opensaml.profile.context.ProfileRequestContext" %> <%@ 
page import="java.time.Instant" %> <%@ page 
import="java.security.Principal" %> <%@ page 
import="javax.security.auth.Subject" %> <%@ page 
import="net.shibboleth.idp.authn.principal.UsernamePrincipal" %> <%@ 
page 
import="net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal" 
%> <%@ page import="org.opensaml.saml.saml2.core.AuthnContext" %> <%@ 
page import="net.shibboleth.idp.session.context.SessionContext" %> <%@ 
page import="net.shibboleth.idp.session.IdPSession" %> <%@ page 
import="java.util.Collections" %> <%@ page import="java.util.HashSet" %> 
<% try { final String key = 
ExternalAuthentication.startExternalAuthentication(request); /* check 
for an existing IdPSession inside a possibly null SessionContext */ 
final ProfileRequestContext prc = 
ExternalAuthentication.getProfileRequestContext(key, request); final 
SessionContext sc = prc.getSubcontext(SessionContext.class); IdPSession 
idpsession = null; if (sc != null) { idpsession = sc.getIdPSession(); } 
/* only check cookie if no existing session - this SSO only works for 
the first SP you hit */ if (idpsession == null) { try { final CAHUser 
cahUser = processSSOCookies(request); if (cahUser != null) { /* got a 
yummy cookie, lets make a subject out of it */ HashSet<Principal> 
principals = new HashSet<Principal>(); principals.add(new 
UsernamePrincipal(cahUser.getUid())); principals.add(new 
AuthnContextClassRefPrincipal(AuthnContext.UNSPECIFIED_AUTHN_CTX)); 
final Subject subj = new Subject(false, principals, 
Collections.emptySet(), Collections.emptySet()); 
request.setAttribute(ExternalAuthentication.SUBJECT_KEY, subj); 
request.setAttribute(ExternalAuthentication.AUTHENTICATION_INSTANT_KEY, 
Instant.ofEpochSecond(cahUser.getTimestamp())); 
request.setAttribute(ExternalAuthentication.PREVIOUSRESULT_KEY, true); } 
else { /* got yucky or no cookie */ /* do nothing; idp will throw 
NO_CREDENTIALS event which we want */ } } catch (final CAHException e) { 
request.setAttribute(ExternalAuthentication.AUTHENTICATION_EXCEPTION_KEY, 
new ExternalAuthenticationException("CAH handling error", e)); } } else 
{ /* do nothing; idp will throw NO_CREDENTIALS event which we want */ } 
ExternalAuthentication.finishExternalAuthentication(key, request, 
response); } catch (final ExternalAuthenticationException e) { throw new 
ServletException("Error processing external authentication request", e); 
} %>

There are no methods to remove ClassifiedErrors from the 
AuthenticationErrorContext, so I just remove the whole context if I find 
the NoCredentials present.

Thanks Scott for the direction as always, and thanks Steve taking a stab 
at it too!

-- 
%%  Christopher A. Bongaarts   %%cab at umn.edu           %%
%%  OIT - Identity Management  %%http://umn.edu/~cab   %%
%%  University of Minnesota    %%  +1 (612) 625-1809    %%
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://shibboleth.net/pipermail/dev/attachments/20240418/e6aee565/attachment.htm>


More information about the dev mailing list