SAML2LogoutAPIAuthenticatorCmd: implement single log out Signed-off-by: Rohit Yadav <rohit.ya...@shapeblue.com>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/7ee4176c Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/7ee4176c Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/7ee4176c Branch: refs/heads/master Commit: 7ee4176c7a8b3f552e48c00dbdb9858dc544c6b3 Parents: b1946e8 Author: Rohit Yadav <rohit.ya...@shapeblue.com> Authored: Mon Aug 25 01:52:05 2014 +0200 Committer: Rohit Yadav <rohit.ya...@shapeblue.com> Committed: Thu Aug 28 19:45:25 2014 +0200 ---------------------------------------------------------------------- .../command/SAML2LogoutAPIAuthenticatorCmd.java | 50 +++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7ee4176c/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LogoutAPIAuthenticatorCmd.java ---------------------------------------------------------------------- diff --git a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LogoutAPIAuthenticatorCmd.java b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LogoutAPIAuthenticatorCmd.java index 723209f..9910074 100644 --- a/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LogoutAPIAuthenticatorCmd.java +++ b/plugins/user-authenticators/saml2/src/org/apache/cloudstack/api/command/SAML2LogoutAPIAuthenticatorCmd.java @@ -20,16 +20,27 @@ import com.cloud.api.response.ApiResponseSerializer; import com.cloud.user.Account; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.ApiServerService; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.auth.APIAuthenticationType; import org.apache.cloudstack.api.auth.APIAuthenticator; import org.apache.cloudstack.api.auth.PluggableAPIAuthenticator; import org.apache.cloudstack.api.response.LogoutCmdResponse; +import org.apache.cloudstack.saml.SAML2AuthManager; +import org.apache.cloudstack.utils.auth.SAMLUtils; import org.apache.log4j.Logger; +import org.opensaml.DefaultBootstrap; +import org.opensaml.saml2.core.LogoutRequest; +import org.opensaml.saml2.core.NameID; +import org.opensaml.xml.ConfigurationException; +import org.opensaml.xml.io.MarshallingException; +import javax.inject.Inject; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import javax.xml.stream.FactoryConfigurationError; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -38,6 +49,10 @@ public class SAML2LogoutAPIAuthenticatorCmd extends BaseCmd implements APIAuthen public static final Logger s_logger = Logger.getLogger(SAML2LogoutAPIAuthenticatorCmd.class.getName()); private static final String s_name = "logoutresponse"; + @Inject + ApiServerService _apiServer; + SAML2AuthManager _samlAuthManager; + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -60,11 +75,34 @@ public class SAML2LogoutAPIAuthenticatorCmd extends BaseCmd implements APIAuthen @Override public String authenticate(String command, Map<String, Object[]> params, HttpSession session, String remoteAddress, String responseType, StringBuilder auditTrailSb, final HttpServletResponse resp) throws ServerApiException { - auditTrailSb.append("=== Logging out ==="); - // TODO: check global config and do either local or global log out + auditTrailSb.append("=== SAML SLO Logging out ==="); LogoutCmdResponse response = new LogoutCmdResponse(); response.setDescription("success"); response.setResponseName(getCommandName()); + + try { + DefaultBootstrap.bootstrap(); + } catch (ConfigurationException | FactoryConfigurationError e) { + s_logger.error("OpenSAML Bootstrapping error: " + e.getMessage()); + throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(), + "OpenSAML Bootstrapping error while creating SP MetaData", + params, responseType)); + } + + NameID nameId = (NameID) session.getAttribute(SAMLUtils.SAML_NAMEID); + String sessionIndex = (String) session.getAttribute(SAMLUtils.SAML_SESSION); + LogoutRequest logoutRequest = SAMLUtils.buildLogoutRequest(_samlAuthManager.getIdpSingleLogOutUrl(), _samlAuthManager.getServiceProviderId(), nameId, sessionIndex); + + try { + String redirectUrl = _samlAuthManager.getIdpSingleLogOutUrl() + "?SAMLRequest=" + SAMLUtils.encodeSAMLRequest(logoutRequest); + resp.sendRedirect(redirectUrl); + } catch (MarshallingException | IOException e) { + s_logger.error("SAML SLO error: " + e.getMessage()); + throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, _apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(), + "SAML Single Logout Error", + params, responseType)); + } + return ApiResponseSerializer.toSerializedString(response, responseType); } @@ -75,5 +113,13 @@ public class SAML2LogoutAPIAuthenticatorCmd extends BaseCmd implements APIAuthen @Override public void setAuthenticators(List<PluggableAPIAuthenticator> authenticators) { + for (PluggableAPIAuthenticator authManager: authenticators) { + if (authManager instanceof SAML2AuthManager) { + _samlAuthManager = (SAML2AuthManager) authManager; + } + } + if (_samlAuthManager == null) { + s_logger.error("No suitable Pluggable Authentication Manager found for SAML2 Login Cmd"); + } } }