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.