001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2005 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: SSOTokenManager.java,v 1.7 2009/02/18 23:59:36 qcheng Exp $
026 *
027 * Portions copyright 2014 ForgeRock AS.
028 */
029
030package com.iplanet.sso;
031
032import com.iplanet.services.util.I18n;
033import com.iplanet.sso.providers.dpro.SSOProviderBundle;
034import com.iplanet.ums.IUMSConstants;
035import com.sun.identity.shared.debug.Debug;
036import java.security.Principal;
037import java.util.Set;
038
039/**
040 * SSOTokenManager is the final class that is the mediator between the SSO APIs
041 * and SSO providers. When an SSO client makes an API invocation,
042 * SSOTokenManager will delegate that call to the SSO provider/plug-in. The SSO
043 * provider will execute the call and return the results to SSOTokenManager,
044 * which in turn returns the results to the SSO client. This decouples the SSO
045 * clients from the actual SSO providers. You should be able to replace the SSO
046 * provider without having to modify the SSO client. However, the clients can
047 * invoke the class methods on the objects returned by the SSOTokenManager.
048 * <p>
049 * SSOTokenManager is a singleton class; there can be, at most, only one
050 * instance of SSOTokenManager in any given JVM. <p> SSOTokenManager currently
051 * supports only two kinds of provider, one for Grappa and another for Sun
052 * OpenSSO. In the future, this will be extended to support
053 * <p> It is assumed that the provider classes or the JAR file is in the
054 * CLASSPATH so that they can be found automatically. Providers can be
055 * configured using <code>providerimplclass</code> property.
056 * This property must be set to the complete (absolute) package name of the
057 * main class of the provider. For example, if the provider class is
058 * com.iplanet.sso.providers.dpro.SSOProviderImpl, that entire class name
059 * including package prefixes MUST be specified. The main class MUST implement
060 * the com.iplanet.sso.SSOProvider interface and MUST have a public no-arg
061 * default constructor.
062 * <p>
063 * The class <code>SSOTokenManager</code> is a <code>final</code> class that
064 * provides interfaces to create and validate <code>SSOToken</code>s.
065 * <p>
066 * It is a singleton class; an instance of this class can be obtained by calling
067 * <code>SSOTokenManager.getInstance()</code>.
068 * <p>
069 * Having obtained an instance of <code>SSOTokenManager</code>, its methods
070 * can be called to create <code>SSOToken</code>, get <code>SSOToken</code>
071 * given the <code>SSOTokenID</code> in string format, and to validate
072 * <code>SSOToken</code>s.
073 *
074 * @supported.api
075 */
076public class SSOTokenManager {
077
078    /*
079     * SSOTokenManager is not a real provider but implements SSOProvider for
080     * consistency in the methods.
081     */
082
083    /**
084     * Grappa SSOProvider class that will be used by default if
085     * providerimplclass property is not present.
086     */
087    static final String GRAPPA_PROVIDER_PACKAGE =
088        "com.sun.identity.authentication.internal";
089
090    static SSOProvider grappaProvider = null;
091
092    /**
093     * DPRO SSOProvider class
094     */
095    static SSOProvider dProProvider = null;
096
097    /** Debug class that can be used by SSOProvider implementations */
098    public static Debug debug = Debug.getInstance(IUMSConstants.UMS_DEBUG);
099
100    // Singleton instance of SSOTokenManager
101    private static SSOTokenManager instance = null;
102
103    /**
104     * Returns the singleton instance of
105     * <code>SSOTokenManager</code>.
106     *
107     * @return The singleton <code>SSOTokenManager</code> instance
108     * @throws SSOException
109     *             if unable to get the singleton <code>SSOTokenManager</code>
110     *             instance.
111     * @supported.api
112     */
113    public static SSOTokenManager getInstance() throws SSOException {
114
115        /*
116         * We will use the double-checked locking pattern. Rarely entered block.
117         * Push synchronization inside it. This is the first check.
118         */
119
120        if (instance == null) {
121            /*
122             * Only 1 thread at a time gets past the next point. Rarely executed
123             * synchronization statement and hence synchronization penalty is
124             * not paid every time this method is called.
125             */
126
127            synchronized (SSOTokenManager.class) {
128                /*
129                 * If a second thread was waiting to get here, it will now find
130                 * that the instance has already been initialized, and it will
131                 * not re-initialize the instance variable. This is the
132                 * double-check.
133                 */
134
135                if (instance == null) {
136                    /*
137                     * Here is the critical section that lazy initializes the
138                     * singleton variable.
139                     */
140                    debug.message(
141                            "Constructing a new instance of SSOTokenManager");
142                    instance = new SSOTokenManager();
143                }
144            }
145        }
146        return (instance);
147    }
148
149    /**
150     * Since this class is a singleton, the constructor is suppressed. This
151     * constructor will try to find the provider jar files, load them, then find
152     * the provider mainclass, instantiate it and store it in provider.
153     * Providers can be configured using <code>providerimplclass</code> Java
154     * property. This property must be set to the complete (absolute) package
155     * name of the main class of the provider. The main class MUST implement the
156     * com.iplanet.sso.SSOProvider interface and MUST have a public no-arg
157     * default constructor.
158     */
159    private SSOTokenManager() throws SSOException {
160        Throwable dProException = null;
161        // Obtain the Grappa provider class
162        try {
163            grappaProvider = new
164                com.sun.identity.authentication.internal.AuthSSOProvider();
165            if (debug.messageEnabled()) {
166                debug.message("Obtained Grappa SSO Provider");
167            }
168        } catch (Throwable e) {
169            debug.error("Unable to obtain Grappa SSO provider", e);
170            dProException = e;
171        }
172
173        // Obtain the DPRO provide class
174        try {
175            dProProvider = new com.iplanet.sso.providers.dpro.SSOProviderImpl();
176            if (debug.messageEnabled()) {
177                debug.message("Obtained DPRO SSO Provider");
178            }
179        } catch (Throwable e) {
180            debug.error("DPRO SSO Provider Exception", e);
181            dProException = e;
182        }
183
184        if (dProProvider == null && grappaProvider == null) {
185            debug.error("Unable to obtain either GRAPPA or DPRO SSO providers");
186            I18n i18n = I18n.getInstance(IUMSConstants.UMS_PKG);
187            String rbName = i18n.getResBundleName();
188            if (dProException instanceof ClassNotFoundException)
189                throw new SSOException(rbName,
190                        IUMSConstants.SSO_NOPROVIDERCLASS, null);
191            else if (dProException instanceof InstantiationException)
192                throw new SSOException(rbName,
193                        IUMSConstants.SSO_NOPROVIDERINSTANCE, null);
194            else if (dProException instanceof IllegalAccessException)
195                throw new SSOException(rbName, IUMSConstants.SSO_ILLEGALACCESS,
196                        null);
197            else
198                throw new SSOException(dProException);
199        }
200    }
201
202    /**
203     * Get provider based on SSOToken provided
204     * @param token Single signon SSOToken
205     * @exception SSOException in case of erros when getting the provider
206     */
207    private SSOProvider getProvider(SSOToken token) throws SSOException {
208        if (token == null) {
209            throw new SSOException(SSOProviderBundle.rbName, "ssotokennull", null);
210        }
211        String packageName = token.getClass().getName();
212        if (packageName.startsWith(GRAPPA_PROVIDER_PACKAGE)) {
213            if (grappaProvider == null) {
214                I18n i18n = I18n.getInstance(IUMSConstants.UMS_PKG);
215                throw new SSOException(i18n.getResBundleName(),
216                        IUMSConstants.SSO_NOPROVIDERCLASS, null);
217            }
218            return (grappaProvider);
219        }
220        return (dProProvider);
221    }
222
223    /**
224     * Creates a single sign on token from <code>HttpServletRequest</code>
225     *
226     * @param request
227     *            The <code>HttpServletRequest</code> object which contains
228     *            the session string.
229     * @return single sign on <code>SSOToken</code>
230     * @exception SSOException
231     *                if the single sign on token cannot be created.
232     * @exception UnsupportedOperationException
233     *                if this is an unsupported operation.
234     * @supported.api
235     */
236    public SSOToken createSSOToken(
237            javax.servlet.http.HttpServletRequest request)
238            throws UnsupportedOperationException, SSOException {
239        if (dProProvider != null)
240            return (dProProvider.createSSOToken(request));
241        else
242            return (grappaProvider.createSSOToken(request));
243    }
244
245    /**
246     * Creates a single sign on token after authenticating
247     * the principal with the given password. This method of creating a single
248     * sign on token should only be used for command line applications and it is
249     * forbidden to use this single sign on token in any other context (e.g.
250     * policy, federation, etc.). A token created with this method is only valid
251     * within the context of the calling application. Once the process exits the
252     * token will be destroyed. If token is created using this constructor then
253     * ONLY these methods of single sign on token is supported -
254     *
255     * <pre>
256     *  getAuthType(),
257     *  getHostName(),
258     *  getIPAddress(),
259     *  setProperty(String name, String value),
260     *  getProperty(String name),
261     *  isValid(),
262     *  validate().
263     * </pre>
264     *
265     * @param user
266     *            Principal representing a user or service
267     * @param password
268     *            The password supplied for the principal
269     * @return single sign on token
270     * @exception SSOException
271     *                if the single sign on token cannot be created.
272     * @exception UnsupportedOperationException
273     *                if this is an unsupported operation.
274     * @deprecated This method has been deprecated. Please use the regular LDAP
275     *             authentication mechanism instead. More information on how to
276     *             use the authentication programming interfaces as well as the
277     *             code samples can be obtained from the "Authentication
278     *             Service" chapter of the OpenSSO Developer's Guide.
279     */
280    public SSOToken createSSOToken(Principal user, String password)
281            throws UnsupportedOperationException, SSOException {
282        if (dProProvider != null)
283            return (dProProvider.createSSOToken(user, password));
284        else
285            return (grappaProvider.createSSOToken(user, password));
286    }
287
288    /**
289     * Creates a single sign on token from the single sign
290     * on token ID. Note:-If you want to do Client's IP address validation for
291     * the single sign on token then use
292     * <code>creatSSOToken(String, String)</code> OR
293     * <code>createSSOToken(HttpServletRequest)</code>.
294     *
295     * @param tokenId
296     *            Token ID of the single sign on token
297     * @return single sign on token
298     * @exception SSOException
299     *                if the single sign on token cannot be created.
300     * @exception UnsupportedOperationException
301     * @supported.api
302     */
303    public SSOToken createSSOToken(String tokenId)
304            throws UnsupportedOperationException, SSOException {
305        if (dProProvider != null)
306            return (dProProvider.createSSOToken(tokenId));
307        else
308            return (grappaProvider.createSSOToken(tokenId));
309    }
310
311    /**
312     * Creates a single sign on token from the single sign
313     * on token ID.
314     *
315     * @param tokenId
316     *            Token ID of the single sign on token
317     * @param clientIP
318     *            Client IP address. This must be the IP address of the
319     *            client/user who is accessing the application.
320     * @return single sign on token
321     * @exception SSOException
322     *                if the single sign on token cannot be created.
323     * @exception UnsupportedOperationException
324     * @supported.api
325     */
326    public SSOToken createSSOToken(String tokenId, String clientIP)
327            throws UnsupportedOperationException, SSOException {
328        if (dProProvider != null)
329            return (dProProvider.createSSOToken(tokenId, clientIP));
330        else
331            return (grappaProvider.createSSOToken(tokenId, clientIP));
332    }
333
334    /**
335     * Call this function if you want to retrieve a token whose id you know, you expect to be valid
336     * (this function will not create a new token for you) and you don't want its idle time accidentally
337     * reset.
338     *
339     * @param tokenId The token id of the token you suspect is valid.
340     * @return The valid token, or null if the token id turned out to be rubbish.
341     */
342    public SSOToken retrieveValidTokenWithoutResettingIdleTime(String tokenId)
343            throws UnsupportedOperationException, SSOException {
344        if (dProProvider != null)
345            return (dProProvider.createSSOToken(tokenId, false, false));
346        else
347            return (grappaProvider.createSSOToken(tokenId, false, false));
348    }
349
350    /**
351     * Returns true if a single sign on token is valid.  Your token may have its idle time reset.
352     * You have been warned.
353     *
354     * @param token
355     *            The single sign on token object to be validated.
356     * @return true if the single sign on token is valid.
357     * @supported.api
358     */
359    public boolean isValidToken(SSOToken token) {
360        return isValidToken(token, true);
361    }
362
363    /**
364     * Returns true if a single sign on token is valid, resetting the token's idle time
365     * if and only if the flag allows us to.
366     *
367     * @param token The single sign on token object to be validated.
368     *
369     * @return true if the single sign on token is valid.
370     * @supported.api
371     * @since 12.0.0
372     */
373    public boolean isValidToken(SSOToken token, boolean resetIdleTime) {
374        try {
375            return (getProvider(token).isValidToken(token, resetIdleTime));
376        } catch (SSOException ignored) {
377            return (false);
378        }
379    }
380
381
382    /**
383     * Returns true if the single sign on token is valid.
384     *
385     * @param token
386     *            The single sign on token object to be validated.
387     * @exception SSOException
388     *                if the single sign on token is not valid.
389     * @supported.api
390     */
391    public void validateToken(SSOToken token) throws SSOException {
392        getProvider(token).validateToken(token);
393    }
394
395    /**
396     * Destroys a single sign on token.
397     *
398     * @param token
399     *            The single sign on token object to be destroyed.
400     * @exception SSOException
401     *                if there was an error while destroying the token, or the
402     *                corresponding session reached its maximum session/idle
403     *                time, or the session was destroyed.
404     * @supported.api
405     */
406    public void destroyToken(SSOToken token) throws SSOException {
407        getProvider(token).destroyToken(token);
408    }
409
410    /**
411     * Refresh the Session corresponding to the single
412     * sign on token from the Session Server. This method should only be used
413     * when the client cannot wait the "session cache interval" for updates on
414     * any changes made to the session properties in the session server. If the
415     * client is remote, calling this method results in an over the wire request
416     * to the session server.
417     *
418     * @param token
419     *            single sign on token
420     * @exception SSOException
421     *                if the session reached its maximum session time, or the
422     *                session was destroyed, or there was an error while
423     *                refreshing the session.
424     * @supported.api
425     */
426    public void refreshSession(SSOToken token) throws SSOException {
427        try {
428            getProvider(token).refreshSession(token);
429        } catch (Exception e) {
430            debug.error("Error in refreshing the session from session server");
431            throw new SSOException(e);
432        }
433    }
434
435    /**
436     * This function will never reset the idle time of the refreshed token.  Otherwise, see
437     * {@link com.iplanet.sso.SSOTokenManager#refreshSession(SSOToken)}
438     *
439     * @param token single sign on token
440     * @exception SSOException
441     *                if the session reached its maximum session time, or the
442     *                session was destroyed, or there was an error while
443     *                refreshing the session.
444     * @since 12.0.0
445     */
446    public void refreshSessionWithoutIdleReset(SSOToken token) throws SSOException {
447        try {
448            getProvider(token).refreshSession(token, false);
449        } catch (Exception e) {
450            debug.error("Error in refreshing the session from session server");
451            throw new SSOException(e);
452        }
453    }
454
455    /**
456     * Destroys a single sign on token.
457     *
458     * @param destroyer
459     *            The single sign on token object used to authorize the
460     *            operation
461     * @param destroyed
462     *            The single sign on token object to be destroyed.
463     * @throws SSOException
464     *             if the there was an error during communication with session
465     *             service.
466     * @supported.api
467     */
468    public void destroyToken(SSOToken destroyer, SSOToken destroyed)
469            throws SSOException {
470        getProvider(destroyer).destroyToken(destroyer, destroyed);
471    }
472
473    /**
474     * Returns a list of single sign on token objects
475     * which correspond to valid Sessions accessible to requester. Single sign
476     * on tokens returned are restricted: they can only be used to retrieve
477     * properties and destroy sessions they represent.
478     *
479     * @param requester
480     *            The single sign on token object used to authorize the
481     *            operation
482     * @param server
483     *            The server for which the valid sessions are to be retrieved
484     * @return Set The set of single sign on tokens representing valid Sessions.
485     * @throws SSOException
486     *             if the there was an error during communication with session
487     *             service.
488     * @supported.api
489     */
490    public Set getValidSessions(SSOToken requester, String server)
491            throws SSOException {
492        return getProvider(requester).getValidSessions(requester, server);
493    }
494}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.