001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: SecurityTokenManager.java,v 1.4 2008/08/06 17:28:11 exu Exp $
026 *
027 */
028
029
030package com.sun.identity.liberty.ws.security;
031
032import com.sun.identity.shared.debug.Debug;
033import com.sun.identity.shared.locale.Locale;
034import com.sun.identity.shared.configuration.SystemPropertiesManager;
035
036import com.sun.identity.liberty.ws.common.wsse.BinarySecurityToken;
037import com.sun.identity.liberty.ws.disco.EncryptedResourceID;
038
039import com.sun.identity.saml.assertion.Assertion;
040import com.sun.identity.saml.assertion.NameIdentifier;
041import com.sun.identity.saml.common.SAMLException;
042import com.sun.identity.saml.xmlsig.XMLSignatureManager;
043
044import java.util.ResourceBundle;
045
046import java.security.cert.X509Certificate;
047
048/**
049 * The class <code>SecurityTokenManager</code> is a final class that
050 * provides interfaces to manage Web Service Security (WSS) Tokens.
051 *
052 * @supported.api
053 */
054
055public final class SecurityTokenManager {
056    
057    //TODO : make those public methods remotable
058    private static String TOKEN_PROVIDER =
059            "com.sun.identity.liberty.ws.security.TokenProviderImpl";
060    private static String providerClass = SystemPropertiesManager.get(TOKEN_PROVIDER);
061    static ResourceBundle bundle = Locale.getInstallResourceBundle(
062            "libLibertySecurity");
063    static Debug debug = Debug.getInstance("libIDWSF");
064    private SecurityTokenProvider provider = null;
065    
066    /**
067     * Default constructor
068     */
069    private SecurityTokenManager() {}
070    
071    /**
072     * Returns the security token manager instance, the default
073     * <code>XMLSignatureManager</code> instance will be used for signing
074     * and accessing the data store.
075     *
076     * @param credential The credential of the caller used
077     *   to see if access to this security token manager is allowed.
078     * @throws SecurityTokenException if unable to access the
079     *         the security token manager.
080     * @supported.api
081     */
082    public SecurityTokenManager(java.lang.Object credential)
083                                throws SecurityTokenException {
084        
085        // no null checking for credential since provider may allow it
086        // check for null
087        if (providerClass == null || providerClass.trim().length() == 0) {
088            debug.error("Con: Security Token Provider class is not defined");
089            throw new SecurityTokenException(bundle.getString("noProvider"));
090        }
091        
092        // get provider class instance
093        try {
094            provider = (SecurityTokenProvider)
095            Class.forName(providerClass).newInstance();
096        } catch (Exception e) {
097            debug.message("Con: Unable to get instance of Token Provider", e);
098            throw new SecurityTokenException(
099                    bundle.getString("noProviderInstance"));
100        }
101        
102        // get default XML signature manager class instance
103        XMLSignatureManager manager = null;
104        try {
105            manager = XMLSignatureManager.getInstance();
106        } catch (Exception e) {
107            // unerline provider implementation might not need this, return null
108            // leave the check to the implementor
109            debug.message("Con: Unable to get instance of XMLSigManager", e);
110        }
111        
112        // initialize security token provider
113        provider.initialize(credential, manager);
114    }
115    
116    
117    /**
118     * Gets the security token manager instance, this constructor is only
119     * applicable when the client is running in the same JVM as server.
120     *
121     * @param credential The credential of the caller used
122     *   to see if access to this security token manager is allowed.
123     * @param signatureManager instance of XML digital
124     *         signature manager class, used for accessing the certificate
125     *         datastore and digital signing of the assertion.
126     * @throws SecurityTokenException if unable to access the
127     *         the security token manager.
128     */
129    public SecurityTokenManager(java.lang.Object credential,
130            XMLSignatureManager signatureManager)
131            throws SecurityTokenException {
132        
133        // no null checking for credential since provider may allow it
134        // no null checking for signatureManager since provider may allow it
135        // check for null
136        if (providerClass == null || providerClass.trim().length() == 0) {
137            debug.error("Con2: Security Token Provider class is not defined");
138            throw new SecurityTokenException(bundle.getString("noProvider"));
139        }
140        
141        // get provider class instance
142        try {
143            provider = (SecurityTokenProvider)
144            Class.forName(providerClass).newInstance();
145        } catch (Exception e) {
146            debug.message("Con2: Unable to get instance of Token Provider", e);
147            throw new SecurityTokenException(
148                    bundle.getString("noProviderInstance"));
149        }
150        
151        // initialize security token provider
152        provider.initialize(credential, signatureManager);
153    }
154    
155    /**
156     * Sets the alias of the certificate used for issuing <code>WSS</code>
157     * token, i.e. <code>WSS</code> <code>X509</code> Token, <code>WSS</code>
158     * SAML Token. If the <code>certAlias</code> is never set, a default
159     * certificate will be used for issuing <code>WSS</code> tokens.
160     *
161     * @param certAlias String alias name for the certificate.
162     * @throws SecurityTokenException if certificate for the
163     *            <code>certAlias</code> could not be found in key store.
164     * @supported.api
165     */
166    public void setCertAlias(java.lang.String certAlias)
167    throws SecurityTokenException {
168        provider.setCertAlias(certAlias);
169    }
170    
171    /**
172     * Sets the  certificate used for issuing <code>WSS</code> token, i.e.
173     * <code>WSS</code> <code>X509</code> Token, <code>WSS</code> SAML Token.
174     * If the certificate is never set, a default certificate will
175     * be used for issuing <code>WSS</code> tokens
176     *
177     * @param cert <code>X509</code> certificate
178     * @throws SecurityTokenException if could not set Certificate.
179     */
180    public void setCertificate(X509Certificate cert) 
181                                throws SecurityTokenException {
182        provider.setCertificate(cert);
183    }
184    
185    /**
186     * Returns the <code>X509</code> certificate Token.
187     *
188     * @return <code>X509</code> certificate Token.
189     * @throws SecurityTokenException if the binary security token could
190     * not be obtained.
191     * @supported.api
192     */
193    public BinarySecurityToken getX509CertificateToken()
194    throws SecurityTokenException {
195        return provider.getX509CertificateToken();
196    }
197    
198    /**
199     * Creates a SAML Assertion for message authentication.
200     *
201     * @param senderIdentity name identifier of the sender.
202     * @return Assertion which contains an AuthenticationStatement.
203     * @throws SecurityTokenException if the assertion could not be
204     * obtained.
205     */
206    public SecurityAssertion getSAMLAuthenticationToken(
207            NameIdentifier senderIdentity)
208            throws SecurityTokenException, SAMLException {
209        return provider.getSAMLAuthenticationToken(senderIdentity);
210    }
211    
212    
213    /**
214     * Creates a SAML Assertion for message authorization, the assertion could
215     * optionally contain an AuthenticationStatement which will be used for
216     *  message authentication.
217     *
218     * @param senderIdentity name identifier of the sender.
219     * @param invocatorSession SessionContext of  the invocation identity, it
220     *        is normally obtained by the credential reference in the SAML
221     *        AttributeDesignator for discovery resource offering which is part 
222     *        of the liberty ID-FF AuthenResponse.
223     * @param resourceID id for the resource to be accessed.
224     * @param includeAuthN if true include an AutheticationStatement in
225     *        the Assertion which will be used for message authentication.
226     * @param includeResourceAccessStatement if true, a ResourceAccessStatement
227     *        will be included in the Assertion (for AuthorizeRequester
228     *        directive). If false, a SessionContextStatement will be included
229     *        in the Assertion (for AuthenticationSessionContext directive). 
230     *        In the case when both AuthorizeRequester and 
231     *        AuthenticationSessionContext directive need to be handled, use
232     *        "true" as parameter here since the SessionContext will always be 
233     *        included in the ResourceAccessStatement.
234     * @param recipientProviderID recipient's provider ID.
235     * @return the <code>SecurityAssertion</code> object.
236     * @throws SecurityTokenException if the assertion could not be obtained.
237     */
238    public SecurityAssertion getSAMLAuthorizationToken(
239            NameIdentifier senderIdentity,
240            SessionContext invocatorSession,
241            String resourceID,
242            boolean includeAuthN,
243            boolean includeResourceAccessStatement,
244            String recipientProviderID)
245            throws SecurityTokenException, SAMLException {
246        return provider.getSAMLAuthorizationToken(senderIdentity,
247                invocatorSession,
248                resourceID,
249                includeAuthN,
250                includeResourceAccessStatement,
251                recipientProviderID);
252    }
253    
254    /**
255     * Creates a SAML Assertion for message authorization, the assertion could
256     * optionally contain an AuthenticationStatement which will be used for
257     * message authentication.
258     * @param senderIdentity name identifier of the sender.
259     * @param invocatorSession SessionContext of  the invocation identity, it
260     *        is normally obtained by the credential reference in the SAML
261     *        AttributeDesignator for discovery resource offering which is part 
262     *        of the liberty ID-FF AuthenResponse.
263     * @param encResourceID Encrypted ID for the resource to be accessed.
264     * @param includeAuthN if true, include an AutheticationStatement in the
265     *        Assertion which will be used for message authentication. 
266     * @param includeResourceAccessStatement if true, a ResourceAccessStatement
267     *        will be included in the Assertion (for AuthorizeRequester 
268     *        directive). If false, a SessionContextStatement will be included 
269     *        in the Assertion (for AuthenticationSessionContext directive).
270     *        In the case when both AuthorizeRequester and 
271     *        AuthenticationSessionContext directive need to be handled, use
272     *        "true" as parameter here since the SessionContext will always be 
273     *        included in the ResourceAccessStatement.
274     * @param recipientProviderID recipient's provider ID.
275     * @return the <code>SecurityAssertion</code> object.
276     * @throws SecurityTokenException if the assertion could not be obtained.
277     */
278    public SecurityAssertion getSAMLAuthorizationToken(
279            NameIdentifier senderIdentity,
280            SessionContext invocatorSession,
281            EncryptedResourceID encResourceID,
282            boolean includeAuthN,
283            boolean includeResourceAccessStatement,
284            String recipientProviderID)
285            throws SecurityTokenException {
286        return provider.getSAMLAuthorizationToken(senderIdentity,
287                invocatorSession,
288                encResourceID,
289                includeAuthN,
290                includeResourceAccessStatement,
291                recipientProviderID);
292    }
293    
294    
295    /**
296     * Creates a SAML assertion. The confirmationMethod will be set to
297     * "urn:oasis:names:tc:SAML:1.0:cm:bearer".
298     *
299     * @param senderIdentity name identifier of the sender.
300     * @param invocatorSession SessionContext of  the invocation identity, it
301     *                  is normally obtained by the credential reference in the
302     *                  SAML AttributeDesignator for discovery resource
303     *                  offering which is part of the liberty ID-FF
304     *                  AuthenResponse.
305     * @param resourceID id for the resource to be accessed.
306     * @param includeAuthN if true, include an AutheticationStatement in the
307     *                  Assertion which will be used for message
308     *                  authentication. if false, no AuthenticationStatement
309     *                  will be included.
310     * @param includeResourceAccessStatement if true, a ResourceAccessStatement
311     *                  will be included in the Assertion (for
312     *                  AuthorizeRequester directive). If false, a
313     *                  SessionContextStatement will be included in the
314     *                  Assertion (for AuthenticationSessionContext directive).
315     *                  In the case when both AuthorizeRequester and
316     *                  AuthenticationSessionContext directive need to be
317     *                  handled, use "true" as parameter here since the
318     *                  SessionContext will always be included in the
319     *                  ResourceAccessStatement.
320     * @param recipientProviderID recipient's provider ID.
321     * @return the <code>SecurityAssertion</code> object.
322     * @throws SecurityTokenException if the assertion could not be obtained
323     */
324    public SecurityAssertion getSAMLBearerToken(
325            NameIdentifier senderIdentity,
326            SessionContext invocatorSession,
327            String resourceID,
328            boolean includeAuthN,
329            boolean includeResourceAccessStatement,
330            String recipientProviderID)
331            throws SecurityTokenException, SAMLException {
332        return provider.getSAMLBearerToken(senderIdentity,
333                invocatorSession,
334                resourceID,
335                includeAuthN,
336                includeResourceAccessStatement,
337                recipientProviderID);
338    }
339    
340    
341    /**
342     * Creates a SAML assertion. The confirmationMethod will be set to
343     * "urn:oasis:names:tc:SAML:1.0:cm:bearer".
344     *
345     * @param senderIdentity name identifier of the sender.
346     * @param invocatorSession SessionContext of  the invocation identity, it
347     *                  is normally obtained by the credential reference in the
348     *                  SAML AttributeDesignator for discovery resource
349     *                  offering which is part of the liberty ID-FF
350     *                  AuthenResponse.
351     * @param encResourceID Encrypted ID for the resource to be accessed.
352     * @param includeAuthN if true, include an AutheticationStatement in the
353     *                  Assertion which will be used for message
354     *                  authentication. if false, no AuthenticationStatement
355     *                  will be included.
356     * @param includeResourceAccessStatement if true, a ResourceAccessStatement
357     *                  will be included in the Assertion (for
358     *                  AuthorizeRequester directive). If false, a
359     *                  SessionContextStatement will be included in the
360     *                  Assertion (for AuthenticationSessionContext directive).
361     *                  In the case when both AuthorizeRequester and
362     *                  AuthenticationSessionContext directive need to be
363     *                  handled, use "true" as parameter here since the
364     *                  SessionContext will always be included in the
365     *                  ResourceAccessStatement.
366     * @param recipientProviderID recipient's provider ID.
367     * @return the <code>SecurityAssertion</code> object.
368     * @throws SecurityTokenException if the assertion could not be obtained
369     * @supported.api
370     */
371    public SecurityAssertion getSAMLBearerToken(
372            NameIdentifier senderIdentity,
373            SessionContext invocatorSession,
374            EncryptedResourceID encResourceID,
375            boolean includeAuthN,
376            boolean includeResourceAccessStatement,
377            String recipientProviderID)
378            throws SecurityTokenException {
379        return provider.getSAMLBearerToken(senderIdentity,
380                invocatorSession,
381                encResourceID,
382                includeAuthN,
383                includeResourceAccessStatement,
384                recipientProviderID);
385    }   
386}