From 02ad6a92004f719c7827aa4daf50b9b7cfae36a6 Mon Sep 17 00:00:00 2001 From: Rolain Djeumen Date: Wed, 11 Dec 2024 11:41:41 +0100 Subject: [PATCH] feat(oxshibboleth): implement forceauthn in shibboleth IDP for unsolicited SSO #63 Signed-off-by: Rolain Djeumen --- .../gluu/idp/context/GluuScratchContext.java | 11 +++++++- .../externalauth/OxAuthReuseResultByAcr.java | 26 +++++++++++++++++++ .../externalauth/ShibOxAuthAuthServlet.java | 17 +++++++++++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/context/GluuScratchContext.java b/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/context/GluuScratchContext.java index c121d0fb..30c6a70d 100644 --- a/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/context/GluuScratchContext.java +++ b/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/context/GluuScratchContext.java @@ -70,5 +70,14 @@ public String getExtraHttpParameters() { return null; } } - + + public boolean hasExtraHttpParameter(final String http_param_name) { + + return extraHttpParameters.get(http_param_name) != null; + } + + public String getExtraHttpParameter(final String http_param_name) { + + return extraHttpParameters.get(http_param_name); + } } diff --git a/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/externalauth/OxAuthReuseResultByAcr.java b/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/externalauth/OxAuthReuseResultByAcr.java index 52ace2c7..c915a1e7 100644 --- a/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/externalauth/OxAuthReuseResultByAcr.java +++ b/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/externalauth/OxAuthReuseResultByAcr.java @@ -13,6 +13,7 @@ import net.shibboleth.idp.profile.context.RelyingPartyContext; import net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration; +import org.gluu.idp.context.GluuScratchContext; import org.gluu.orm.util.StringHelper; import org.opensaml.messaging.context.navigate.ChildContextLookup; import org.opensaml.profile.context.ProfileRequestContext; @@ -27,24 +28,34 @@ public class OxAuthReuseResultByAcr implements Predicate private final Logger LOG = LoggerFactory.getLogger(OxAuthReuseResultByAcr.class); private Function authnContextLookupStrategy; + private Function gluuScratchContextLookupStrategy; private static final String OX_AUTH_FLOW_ID = "authn/oxAuth"; + private static final String FORCE_AUTHN_QUERY_PARAM = "forceAuthn_"; public OxAuthReuseResultByAcr() { authnContextLookupStrategy = new ChildContextLookup(AuthenticationContext.class); + gluuScratchContextLookupStrategy = new ChildContextLookup<>(GluuScratchContext.class); } @Override public boolean test(ProfileRequestContext profileRequestContext) { final AuthenticationContext authnContext = authnContextLookupStrategy.apply(profileRequestContext); + final GluuScratchContext gScratchContext = gluuScratchContextLookupStrategy.apply(profileRequestContext); if(authnContext == null) { //In principle this should not happen LOG.debug("No Authentication context found. Re-using result"); return true; } + if(isForceAuthn(authnContext, gScratchContext)) { + // do not re-use the authentication result + LOG.debug("forcedAuthn enabled. Not-reusing results."); + return false; + } + Map activeResultsMap = authnContext.getActiveResults(); if(!activeResultsMap.containsKey(OX_AUTH_FLOW_ID)) { LOG.debug("Session does not have any authn/oxAuth results. Re-using authentication result"); @@ -102,5 +113,20 @@ private final List determineAcrs(ProfileRequestContext profileRequestCon return acrs; } + + private final boolean isForceAuthn(final AuthenticationContext authnContext, final GluuScratchContext gsContext) { + + if(authnContext.isForceAuthn() && gsContext == null) { + return true; + } + + final String forceauthnqueryparam = gsContext.getExtraHttpParameter(FORCE_AUTHN_QUERY_PARAM); + if(forceauthnqueryparam == null) { + + return authnContext.isForceAuthn(); + } + + return forceauthnqueryparam.equalsIgnoreCase("true"); + } } diff --git a/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/externalauth/ShibOxAuthAuthServlet.java b/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/externalauth/ShibOxAuthAuthServlet.java index 060ec2a4..e4a7be43 100644 --- a/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/externalauth/ShibOxAuthAuthServlet.java +++ b/oxShibboleth/shib-oxauth-authn/src/main/java/org/gluu/idp/externalauth/ShibOxAuthAuthServlet.java @@ -86,6 +86,7 @@ public class ShibOxAuthAuthServlet extends HttpServlet { private final String OXAUTH_PARAM_ENTITY_ID = "entityId"; private final String OXAUTH_PARAM_ISSUER_ID = "issuerId"; private final String OXAUTH_PARAM_EXTRA_PARAMS = "extraParameters"; + private final String FORCE_AUTHN_REQUEST_PARAM = "forceAuthn_"; private final String OXAUTH_ATTRIBIUTE_SEND_END_SESSION_REQUEST = "sendEndSession"; public final static String OXAUTH_ACR_USED = "acr_used"; @@ -173,7 +174,21 @@ public String getParameter(String name) { final String flowExecutionKey = ExternalAuthentication.startExternalAuthentication(externalRequest); // Get external authentication properties - final boolean force = Boolean.parseBoolean(request.getAttribute(ExternalAuthentication.FORCE_AUTHN_PARAM).toString()); + boolean force = Boolean.parseBoolean(request.getAttribute(ExternalAuthentication.FORCE_AUTHN_PARAM).toString()); + //override this if the forceAuthn_ request parameter is true + final ProfileRequestContext prContext = ExternalAuthentication.getProfileRequestContext(flowExecutionKey,request); + final GluuScratchContext gsContext = prContext.getSubcontext(GluuScratchContext.class); + if(gsContext != null && gsContext.hasExtraHttpParameter(FORCE_AUTHN_REQUEST_PARAM)) { + LOG.info("Force authn parameter"); + final String forceAuthnParamValue = gsContext.getExtraHttpParameter(FORCE_AUTHN_REQUEST_PARAM); + if(forceAuthnParamValue.equals("true")) { + force = true; + LOG.info("Force authn parameter is true."); + } + }else { + LOG.info("No force authn parameter"); + } + // It's an authentication if (!authorizationResponse) {