/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * https://opensso.dev.java.net/public/CDDLv1.0.html or * opensso/legal/CDDLv1.0.txt * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at opensso/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id: SecurityTokenManagerClient.java,v 1.9 2008/08/19 19:11:09 veiming Exp $ * * Portions Copyright 2013-2015 ForgeRock AS. */ package com.sun.identity.liberty.ws.security; import com.sun.identity.shared.locale.Locale; import com.sun.identity.shared.configuration.SystemPropertiesManager; import com.sun.identity.shared.xml.XMLUtils; import com.sun.identity.common.SystemConfigurationUtil; import com.sun.identity.shared.encode.Base64; import com.sun.identity.shared.encode.Base64; import com.sun.identity.liberty.ws.common.wsse.BinarySecurityToken; import com.sun.identity.liberty.ws.disco.EncryptedResourceID; import com.sun.identity.plugin.session.SessionManager; import com.sun.identity.saml.assertion.Assertion; import com.sun.identity.saml.assertion.AssertionIDReference; import com.sun.identity.saml.assertion.Attribute; import com.sun.identity.saml.assertion.NameIdentifier; import com.sun.identity.saml.common.SAMLConstants; import com.sun.identity.saml.common.SAMLException; import com.sun.identity.saml.common.SAMLUtils; import com.sun.identity.shared.jaxrpc.SOAPClient; import com.sun.identity.saml.protocol.AssertionArtifact; import java.net.InetAddress; import java.net.URL; import java.rmi.RemoteException; import java.rmi.ServerException; import java.security.cert.X509Certificate; import java.util.Iterator; import java.util.ResourceBundle; import javax.xml.soap.SOAPException; /** * The class SecurityTokenManagerClient is a final * class that provides interfaces to create, get and destroy * Assertions. *

* The class provides mechanisms to manage the Assertions either * locally (i.e., within the same JVM process) or remotely on another instance * of OpenAM. The default constructor will manage the * Assertions locally if it detects SAML web services running locally, * else will use on of the configured OpenAM. The constructor which * accepts an URL will always use the URL to manage the assertions. *

* Having obtained an instance of AssertionManagerClient, its * methods can be called to create/get Assertion, and * AssertionArtifact, and to obtain decision from an * Query. * * @supported.api */ public final class SecurityTokenManagerClient { // Service name in naming private static String SERVICE_NAME = "securitytokenmanager"; // Flag to determine if AssertionManager is local or remote private static boolean checkedForLocal; private static boolean isLocal; private boolean useLocal; // Remote JAX-RPC server for objects that use default constructor private static SOAPClient remoteStub; // If local pointer to SecurityTokenManager instance private SecurityTokenManager securityTokenManager; private String ssoToken = null; // JAX-RPC remote stub private SOAPClient stub; static ResourceBundle bundle = Locale.getInstallResourceBundle("libLibertySecurity"); /** * Returns an instance of SecurityTokenManagerClient * * @param credential credential of the caller used to see * if access to this security token manager client is allowed. * @throws SecurityTokenException if unable to access the * the security token manager client. */ public SecurityTokenManagerClient(Object credential) throws SecurityTokenException { if (!checkedForLocal) { try { // Construct the URL for local server. remoteStub = getServiceEndPoint( SystemPropertiesManager.get(SAMLConstants.SERVER_PROTOCOL), SystemPropertiesManager.get(SAMLConstants.SERVER_HOST), SystemPropertiesManager.get(SAMLConstants.SERVER_PORT), SystemPropertiesManager.get(SAMLConstants.SERVER_URI)); remoteStub.send("checkForLocal", null, null, null); if (SecurityTokenManagerImpl.isLocal) { isLocal = true; SecurityTokenManager.debug.warning( "STMC(): Using local service"); securityTokenManager = new SecurityTokenManager(credential); } checkedForLocal = true; } catch (Exception e) { checkedForLocal = true; if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "SecurityTokenManagerClient()Exception", e); } throw (new SecurityTokenException(e.getMessage())); } } if (isLocal) { useLocal = true; } else { // Use the remoteStub if set stub = remoteStub; try { ssoToken = SessionManager.getProvider().getSessionID(credential); stub.send("initialization", ssoToken, null, ssoToken); } catch (Exception e) { if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "SecurityTokenManagerClient()Exception", e); } throw (new SecurityTokenException(e.getMessage())); } } } /** * Returns an instance of SecurityTokenManagerClient * that will use the provided URL for the management * of security tokens. * * @param url the SecurityTokenManagerClient service URL that * will be used to get BinarySecurityToken and * SAMLSecurityToken. * @param credential credential of the caller used to see * if access to this security token manager client is allowed. * @throws SecurityTokenException if unable to access the * the security token manager client. */ public SecurityTokenManagerClient(String url, Object credential) throws SecurityTokenException { try { // Construct the JAX-RPC stub and set the URL endpoint ssoToken = SessionManager.getProvider().getSessionID(credential); String[] urls = {url}; stub = new SOAPClient(urls); stub.send("initialization", ssoToken, null, ssoToken); useLocal = false; } catch (Exception e) { if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning("STMC() Exception", e); } throw (new SecurityTokenException(e.getMessage())); } } // Private method to get the service endpoint URL private static SOAPClient getServiceEndPoint(String protocol, String hostname, String port, String uri) throws Exception { // Obtain the URL for the service endpoint int intPort = Integer.parseInt(port); URL weburl = SystemConfigurationUtil.getServiceURL(SERVICE_NAME, protocol, hostname, intPort, uri); String iurl = weburl.toString(); if (SecurityTokenManager.debug.messageEnabled()) { SecurityTokenManager.debug.message( "SecurityTokenManagerClient with URL: " + iurl); } String[] urls = {iurl}; return new SOAPClient(urls); } private static SOAPClient getRemoteStub() throws SecurityTokenException { boolean foundServer = false; Exception ee = null; SOAPClient remoteStub = null; try { // Get the list of platform servers Iterator serverList = SystemConfigurationUtil.getServerList().iterator(); // Get a server that is responding while (serverList.hasNext() && !foundServer) { URL u = new URL((String) serverList.next()); remoteStub = getServiceEndPoint(u.getProtocol(), u.getHost(), Integer.toString(u.getPort()), u.getPath()); // Check if the server is active try { // this call will throw an exception if server is down remoteStub.send("checkForLocal", null, null, null); if (SecurityTokenManager.debug.messageEnabled()) { SecurityTokenManager.debug.message( "STMC(): Using the remote URL: " + u.toString()); } foundServer = true; if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "STMC:getRemoteStub: remote server being used: " + u.toString()); } } catch (Exception e) { ee = e; if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "STMC:getRemoteStub: server (" + u.toString() + ") error: ", e); } } } } catch (Exception f) { ee = f; if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "STMC:getRemoteStub: generic error: ", f); } } if (!foundServer) { // No valid server found. Return the last exception if (ee != null) { throw (new SecurityTokenException(ee.getMessage())); } else { throw (new SecurityTokenException( bundle.getString("serverNotFound"))); } } return (remoteStub); } /** * Sets the alias of the certificate used for issuing WSS * token, i.e. WSS X509 Token, WSS * SAML Token. If the certAlias is never set, a default * certificate will be used for issuing WSS tokens. * * @param certAlias String alias name for the certificate. * @throws SecurityTokenException if certificate for the * certAlias could not be found in key store. * * @supported.api */ public void setCertAlias(java.lang.String certAlias) throws SecurityTokenException { if (useLocal) { securityTokenManager.setCertAlias(certAlias); } else { try { Object[] obj = {certAlias, Boolean.TRUE}; stub.send("setCertificate", obj, null, ssoToken); } catch (Exception e) { if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "STMC:setCertAlias()", e); } throw (new SecurityTokenException(e.getMessage())); } } } /** * Sets the certificate used for issuing WSS token, i.e. * WSS X509 Token, WSS SAML Token. * If the certificate is never set, a default certificate will * be used for issuing WSS tokens * * @param cert X509 certificate * @throws SecurityTokenException if could not set Certificate. */ public void setCertificate(X509Certificate cert) throws SecurityTokenException { if (useLocal) { securityTokenManager.setCertificate(cert); } else { try { String certString = Base64.encode(cert.getEncoded()); Object[] obj = {certString, Boolean.FALSE}; stub.send("setCertificate", obj, null, ssoToken); } catch (Exception e) { if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "STMC:setCertificate()", e); } throw (new SecurityTokenException(e.getMessage())); } } } /** * Gets the X509 certificate Token. * * @return X509 certificate Token. * @throws SecurityTokenException if the binary security token could * not be obtained. */ public BinarySecurityToken getX509CertificateToken() throws SecurityTokenException { if (useLocal) { return securityTokenManager.getX509CertificateToken(); } String bst = null; try { bst = (String) stub.send("getX509CertificateToken", null, null, ssoToken); return (new BinarySecurityToken(XMLUtils.toDOMDocument(bst, SecurityTokenManager.debug).getDocumentElement())); } catch (Exception e) { if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "STMC:getX509CertificateToken()", e); } throw (new SecurityTokenException(e.getMessage())); } } /** * Creates a SAML Assertion for message authentication. * * @param senderIdentity name identifier of the sender. * @return Assertion which contains an AuthenticationStatement. * @throws SecurityTokenException if the assertion could not be obtained. * @throws SAMLException if unable to generate the SAML Assertion. */ public SecurityAssertion getSAMLAuthenticationToken( NameIdentifier senderIdentity) throws SecurityTokenException, SAMLException { if (useLocal) { return (securityTokenManager.getSAMLAuthenticationToken( senderIdentity)); } try { String ni = senderIdentity.toString(true, true); String assertion = (String) stub.send("getSAMLAuthenticationToken", ni, null, ssoToken); return (new SecurityAssertion(XMLUtils.toDOMDocument(assertion, SecurityTokenManager.debug).getDocumentElement())); } catch (Exception re) { if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "STMC:getSAMLAuthenticationToken()", re); } throw (new SAMLException(re.getMessage())); } } /** * Creates a SAML Assertion for message authorization, the assertion could * optionally contain an AuthenticationStatement which will be * used for message authentication. * * @param senderIdentity name identifier of the sender. * @param invocatorSession SessionContext of the invocation * identity, it is normally obtained by the credential reference in * the SAML AttributeDesignator for discovery resource * offering which is part of the liberty ID-FF * AuthenResponse. * @param resourceID id for the resource to be accessed. * @param includeAuthN if true, include an * AutheticationStatement in the Assertion which will be * used for message authentication. * @param includeResourceAccessStatement if true, a * ResourceAccessStatement * will be included in the Assertion * (for AuthorizeRequester directive). If false, * a SessionContextStatement will be included in the * Assertion (for AuthenticationSessionContext * directive). In the case when both AuthorizeRequester * and AuthenticationSessionContext directive need to be * handled, use "true" as parameter here since the * SessionContext will always be included in the * ResourceAccessStatement. * @param recipientProviderID recipient's provider ID. * @return the SecurityAssertion object. * @throws SecurityTokenException if the assertion could not be obtained. * @throws SAMLException if unable to generate the SAML Assertion. */ public SecurityAssertion getSAMLAuthorizationToken( NameIdentifier senderIdentity, SessionContext invocatorSession, String resourceID, boolean includeAuthN, boolean includeResourceAccessStatement, String recipientProviderID) throws SecurityTokenException, SAMLException { if (useLocal) { return (securityTokenManager.getSAMLAuthorizationToken( senderIdentity, invocatorSession, resourceID, includeAuthN, includeResourceAccessStatement, recipientProviderID)); } try { String ni = senderIdentity.toString(true, true); String sc = invocatorSession.toXMLString(true, true); Object[] obj = {ni, sc, resourceID, Boolean.FALSE, Boolean.valueOf(includeAuthN), Boolean.valueOf(includeResourceAccessStatement), recipientProviderID}; String assertion = (String) stub.send("getSAMLAuthorizationToken", obj, null, ssoToken); return (new SecurityAssertion(XMLUtils.toDOMDocument(assertion, SecurityTokenManager.debug).getDocumentElement())); } catch (Exception e) { if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "STMC:createAssertionArtifact:", e); } throw (new SecurityTokenException(e.getMessage())); } } /** * Creates a SAML Assertion for message authorization, the assertion could * optionally contain an AuthenticationStatement which will be * used for message authentication. * * @param senderIdentity name identifier of the sender. * @param invocatorSession SessionContext of the invocation * identity, it is normally obtained by the credential reference in * the SAML AttributeDesignator for discovery resource * offering which is part of the liberty ID-FF * AuthenResponse. * @param encResourceID Encrypted ID for the resource to be accessed. * @param includeAuthN if true, include an * AutheticationStatement in the * Assertion which will be used for message authentication. * @param includeResourceAccessStatement if true, * a ResourceAccessStatement will be included in the * Assertion (for AuthorizeRequester directive). If * false, a SessionContextStatement will be included in * the Assertion (for AuthenticationSessionContext * directive). In the case when both AuthorizeRequester * and AuthenticationSessionContext directive need to be * handled, use "true" as parameter here since the * SessionContext will always be included in the * ResourceAccessStatement. * @param recipientProviderID recipient's provider ID. * @return the SecurityAssertion object. * @throws SecurityTokenException if the assertion could not be obtained. * @throws SAMLException if unable to generate the SAML Assertion. */ public SecurityAssertion getSAMLAuthorizationToken( NameIdentifier senderIdentity, SessionContext invocatorSession, EncryptedResourceID encResourceID, boolean includeAuthN, boolean includeResourceAccessStatement, String recipientProviderID) throws SecurityTokenException, SAMLException { if (useLocal) { return (securityTokenManager.getSAMLAuthorizationToken( senderIdentity, invocatorSession, encResourceID, includeAuthN, includeResourceAccessStatement, recipientProviderID)); } String assertion = null; try { String ni = senderIdentity.toString(true, true); String sc = invocatorSession.toXMLString(true, true); String resourceID = encResourceID.toString(); Object[] obj = {ni, sc, resourceID, Boolean.TRUE, Boolean.valueOf(includeAuthN), Boolean.valueOf(includeResourceAccessStatement), recipientProviderID}; assertion = (String) stub.send("getSAMLAuthorizationToken", obj, null, ssoToken); return (new SecurityAssertion(XMLUtils.toDOMDocument(assertion, SecurityTokenManager.debug).getDocumentElement())); } catch (Exception e) { if (SecurityTokenManager.debug.warningEnabled()) { SecurityTokenManager.debug.warning( "STMC:getSAMLAuthorizationToken() ", e); } throw (new SecurityTokenException(e.getMessage())); } } }