Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(oxshibboleth): implement forceauthn in shibboleth IDP for unsolicited SSO #63 #64

Merged
merged 2 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,24 +28,34 @@ public class OxAuthReuseResultByAcr implements Predicate<ProfileRequestContext>
private final Logger LOG = LoggerFactory.getLogger(OxAuthReuseResultByAcr.class);

private Function<ProfileRequestContext,AuthenticationContext> authnContextLookupStrategy;
private Function<ProfileRequestContext,GluuScratchContext> 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<ProfileRequestContext,AuthenticationContext>(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<String,AuthenticationResult> activeResultsMap = authnContext.getActiveResults();
if(!activeResultsMap.containsKey(OX_AUTH_FLOW_ID)) {
LOG.debug("Session does not have any authn/oxAuth results. Re-using authentication result");
Expand Down Expand Up @@ -102,5 +113,20 @@ private final List<String> 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");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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) {
Expand Down
Loading