Notifications

1006 views

Description

Some IdPs only support HTTP-POST SAML login requests. Currently ServiceNow does not offer any available settings for a SAML login request to use HTTP-POST.

 

Steps to Reproduce

Some Identity Providers require an HTTP-POST login request. The baseline version of the multi-provider SSO plugin does not support HTTP-POST.

 

Workaround

This issue has been identified as a future product enhancement. The Installation Exit scripts below compose the 3-steps workaround approved by SN development. Please note this was originally based on the Helsinki code base, and should always be tested on a sub-production instance prior to deploy the change into production.

 

1. Modify the Script Include 'SAML2_update1' adding the methods below just after the "getSAMLAssertion" method:


getAuthnRequestFormString : function(isTestConn) {
var AuthnRequestMarshaller = Packages.org.opensaml.saml2.core.impl.AuthnRequestMarshaller;
var samlOptions = null;
if (isTestConn) {
samlOptions = {
forceAuthn: true
}
}

var authnRequest = this.createAuthnRequestWithOptions(samlOptions);

var signAuthn = this.ssoHelper.getProperty("glide.authenticate.sso.saml2.require_signed_authnrequest", "require_signed_authnrequest", false);
if(this.isTrue(signAuthn)) {
this.signSAMLObject(authnRequest);
}

var arm = new AuthnRequestMarshaller();
var elem = arm.marshall(authnRequest);

return SAML2_update1.getEncodedSAMLRequest(elem, false, false);
}

generateAuthnRequestForm: function(request,isTestConn) {
try {
var idpAuthnURL = this.ssoHelper.getProperty("glide.authenticate.sso.saml2.idp_authnrequest_url", "idp_authnrequest_url");

var authReqStr = this.getAuthnRequestFormString(isTestConn);
var origRelayState = this.generateRelayState(request, isTestConn);
// always use serviceUrl as relayState, it will lookup the real relayState using "SAML_RelayState" as the key.
// failed login does not respond a relayState, so we must put the states into session for test corrections.
if (isTestConn)
request.getSession().setAttribute("Test_SAML_RelayState", origRelayState);
else
request.getSession().setAttribute("SAML_RelayState", origRelayState);

var formStr = this.createSAMLRequestPostForm(idpAuthnURL, authReqStr, origRelayState);

var httpSession = request.getSession();
httpSession.setAttribute("glide.saml2.session_request_id", this.getLastGeneratedRequestID());
this.logDebug("Setting glide.saml2.http.post.session_request_id in session to support SAML request with http post");
httpSession.setAttribute("glide.saml2.http.post.session_request_id", this.getLastGeneratedRequestID());

//Add this request id to request id array in the session

var requestIDArr = httpSession.getAttribute("glide.saml2.session_request_id_arr");
if(!requestIDArr){
requestIDArr = [];
}
requestIDArr.push(this.getLastGeneratedRequestID());
httpSession.setAttribute("glide.saml2.session_request_id_arr", requestIDArr);

return formStr;
} catch (e) {
if (e instanceof Packages.java.lang.Throwable){
var stackTrace = GlideLog.getStackTrace(e);
this.logError(stackTrace);
}
else{
this.logError(e.name + ": " + e.message);
}
return null;
}
}


2. Modify the Script Include 'MultiSSO_SAML2_Update1' replacing the existing code that uses the http redirect binding from:

var redirectURL = this.SAML2.generateAuthnRequestRedirectURL(request, false);
if (GlideStringUtil.nil(redirectURL))
return "failed_missing_requirement";

To:

// Refresh login request
if(!samlResponseObject && !relayState) {
this.ssoHelper.debug("Logging in saml using HTTP POST");
var formStr = this.SAML2.generateAuthnRequestForm(request, false);
response.setContentType("text/html");
response.getWriter().write(formStr);
var redirectURL = "true"; // trick so it does not fail
SNC.SecurityEventSender.sendSAMLRedirectSentEventData("", "multisso=true,idpsysid=" + this.propertiesGR.getUniqueValue());
return redirectURL;
}


3: Modify the Script Include 'MultiSSO_SAML2_Update1' replacing the existing code from:

var inResponseTo = httpSession.getAttribute("glide.saml2.session_request_id");

To:

var inResponseTo = httpSession.getAttribute("glide.saml2.session_request_id");

if(GlideStringUtil.nil(inResponseTo)) {
this.logDebug("Getting inResponseTo from new attribute for http post SAML request.");
inResponseTo = httpSession.getAttribute("glide.saml2.http.post.session_request_id");
}



Related Problem: PRB656080

Seen In

Eureka Patch 11 Hot Fix 2
Eureka Patch 13 Hot Fix 2
Fuji Patch 10
Fuji Patch 7 Hot Fix 5
Fuji Patch 8
Geneva Patch 1
Geneva Patch 1 Hot Fix 5
Geneva Patch 6 Hot Fix 2
Geneva Patch 7
Geneva Patch 7 Hot Fix 2
Geneva Patch 8
Helsinki Patch 2
Helsinki Patch 4
Helsinki Patch 7

Associated Community Threads

There is no data to report.

Article Information

Last Updated:2018-11-07 22:54:55
Published:2018-11-08