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: AuthContext.java,v 1.25 2009/11/21 01:12:59 qcheng Exp $ 026 * 027 * Portions Copyrighted 2010-2016 ForgeRock AS. 028 */ 029package com.sun.identity.authentication; 030 031import com.iplanet.am.util.SystemProperties; 032import com.iplanet.dpro.session.SessionID; 033import com.iplanet.dpro.session.service.SessionService; 034import com.iplanet.services.comm.client.PLLClient; 035import com.iplanet.services.comm.share.Request; 036import com.iplanet.services.comm.share.RequestSet; 037import com.iplanet.services.comm.share.Response; 038import com.iplanet.services.naming.WebtopNaming; 039import com.iplanet.sso.SSOException; 040import com.iplanet.sso.SSOToken; 041import com.iplanet.sso.SSOTokenManager; 042import com.sun.identity.authentication.client.AuthClientUtils; 043import com.sun.identity.authentication.server.AuthContextLocal; 044import com.sun.identity.authentication.service.AMAuthErrorCode; 045import com.sun.identity.authentication.service.AuthException; 046import com.sun.identity.authentication.service.LoginState; 047import com.sun.identity.authentication.share.AuthXMLTags; 048import com.sun.identity.authentication.share.AuthXMLUtils; 049import com.sun.identity.authentication.spi.AuthLoginException; 050import com.sun.identity.authentication.util.ISAuthConstants; 051import com.sun.identity.security.AMSecurityPropertiesException; 052import com.sun.identity.security.AdminTokenAction; 053import com.sun.identity.shared.Constants; 054import com.sun.identity.shared.debug.Debug; 055import com.sun.identity.shared.locale.L10NMessageImpl; 056import com.sun.identity.shared.xml.XMLUtils; 057import org.forgerock.guice.core.InjectorHolder; 058import org.forgerock.openam.authentication.service.protocol.RemoteHttpServletRequest; 059import org.forgerock.openam.authentication.service.protocol.RemoteHttpServletResponse; 060import org.forgerock.openam.session.SessionCache; 061import org.w3c.dom.Document; 062import org.w3c.dom.Node; 063import org.w3c.dom.NodeList; 064 065import javax.security.auth.Subject; 066import javax.security.auth.callback.Callback; 067import javax.servlet.http.HttpServletRequest; 068import javax.servlet.http.HttpServletResponse; 069import java.io.ByteArrayInputStream; 070import java.io.IOException; 071import java.lang.reflect.Constructor; 072import java.lang.reflect.Method; 073import java.net.URL; 074import java.net.URLStreamHandler; 075import java.security.AccessController; 076import java.security.KeyStore; 077import java.text.MessageFormat; 078import java.util.Collections; 079import java.util.Enumeration; 080import java.util.HashMap; 081import java.util.HashSet; 082import java.util.Hashtable; 083import java.util.Map; 084import java.util.ResourceBundle; 085import java.util.Set; 086import java.util.Vector; 087 088/** 089 * The <code>AuthContext</code> provides the implementation for 090 * authenticating users. 091 * <p> 092 * A typical caller instantiates this class and starts the login process. 093 * The caller then obtains an array of <code>Callback</code> objects, 094 * which contains the information required by the authentication plug-in 095 * module. The caller requests information from the user. On receiving 096 * the information from the user, the caller submits the same to this class. 097 * While more information is required, the above process continues until all 098 * the information required by the plug-ins/authentication modules, has 099 * been supplied. The caller then checks if the user has successfully 100 * been authenticated. If successfully authenticated, the caller can 101 * then get the <code>Subject</code> and <code>SSOToken</code> for the user; 102 * if not successfully authenticated, the caller obtains the 103 * <code>AuthLoginException</code>. 104 * <p> 105 * The implementation supports authenticating users either locally 106 * i.e., in process with all authentication modules configured or remotely 107 * to an authentication service/framework. (See documentation to configure 108 * in either of the modes). 109 * 110 * @supported.api 111 */ 112public class AuthContext extends Object implements java.io.Serializable { 113 114 private java.util.Locale clientLocale = null; 115 116 private String server_proto = 117 SystemProperties.get(Constants.AM_SERVER_PROTOCOL); 118 private String server_host = 119 SystemProperties.get(Constants.AM_SERVER_HOST); 120 private String server_port = 121 SystemProperties.get(Constants.AM_SERVER_PORT); 122 private String server_uri = 123 SystemProperties.get(Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR); 124 private boolean includeReqRes = 125 SystemProperties.getAsBoolean(Constants.REMOTEAUTH_INCLUDE_REQRES); 126 127 private static final String amAuthContext = "amAuthContext"; 128 129 private static final String JSS_PASSWORD_UTIL = 130 "com.sun.identity.authentication.util.JSSPasswordUtil"; 131 132 private static final String JSSE_PASSWORD_CALLBACK = 133 "com.sun.identity.security.keystore.AMCallbackHandler"; 134 135 static String protHandlerPkg = 136 System.getProperty(Constants.PROTOCOL_HANDLER, Constants.JSSE_HANDLER); 137 138 static boolean usingJSSEHandler = 139 protHandlerPkg.equals(Constants.JSSE_HANDLER); 140 141 // Debug & I18N class 142 protected static Debug authDebug = Debug.getInstance(amAuthContext); 143 protected static ResourceBundle bundle = 144 com.sun.identity.shared.locale.Locale.getInstallResourceBundle(amAuthContext); 145 146 Status loginStatus = Status.IN_PROGRESS; 147 String organizationName = ""; 148 Document receivedDocument; 149 AuthLoginException loginException = null; 150 151 String hostName = null; 152 private boolean forceAuth = false; 153 private boolean localSessionChecked = false; 154 String nickName = null; 155 private URL authURL = null; 156 private URL authServiceURL = null; 157 private SSOToken ssoToken = null; 158 private String ssoTokenID = null; 159 private static SSOToken appSSOToken = null; 160 com.sun.identity.authentication.server.AuthContextLocal acLocal = null; 161 private final static int DEFAULT_RETRY_COUNT = 1; 162 private int retryRunLogin = DEFAULT_RETRY_COUNT; 163 164 /** 165 * Variables for checking auth service is running local 166 */ 167 public boolean localFlag = false; 168 /** 169 * Variables for local AuthService identifier 170 */ 171 public static String localAuthServiceID; 172 173 // Variable to check if 6.3 style remote AuthN has to be performed 174 static boolean useOldStyleRemoteAuthentication; 175 static boolean useNewStyleRemoteAuthentication; 176 177 // this cookieTable is used to keep all the cookies retrieved from the 178 // the PLL layer and replay them in subsequent auth requests, mainly for 179 // persistence purpose. 180 private HashMap cookieTable = new HashMap(); 181 182 private HttpServletRequest remoteRequest = null; 183 private HttpServletResponse remoteResponse = null; 184 185 private final SessionCache sessionCache = SessionCache.getInstance(); 186 187 /** 188 * Constructs an instance of <code>AuthContext</code> for a given 189 * organization name or sub organization name. This organization or 190 * sub-organization name must be either "/" separated 191 * ( where it starts with "/" ) , DN , Domain name or DNS Alias Name. 192 * <p> 193 * Caller would then use <code>login</code> to start the 194 * authentication process and use <code>getRequirements()</code> and 195 * <code>submitRequirements()</code> to pass the credentials 196 * needed for authentication by the plugin authentication modules. 197 * The method <code>getStatus()</code> returns the 198 * authentication status. 199 * 200 * @param orgName Name of the user's organization. 201 * @throws AuthLoginException if <code>AuthContext</code> creation fails. 202 * This exception is kept for backward compatibility only. 203 * 204 * @supported.api 205 */ 206 public AuthContext(String orgName) throws AuthLoginException { 207 organizationName = orgName; 208 } 209 210 /** 211 * Constructs an instance of <code>AuthContext</code> for a given 212 * organization name, or sub organization name and the OpenAM server 213 * URL. 214 * This organization or sub-organization name must be either "/" separated 215 * ( where it starts with "/" ) , DN , Domain name or DNS Alias Name. 216 * And the <code>url</code> should specify the OpenAM server's protocol, 217 * host name, and port number, 218 * for example : <code>http://daye.red.iplanet.com:58080</code> 219 * 220 * Caller would then use <code>login</code> to start the 221 * authentication process and use <code>getRequirements()</code> and 222 * <code>submitRequirements()</code> to pass the credentials 223 * needed for authentication by the plugin authentication modules. 224 * The method <code>getStatus()</code> returns the 225 * authentication status. 226 * 227 * @param orgName name of the user's organization 228 * @param url URL of the OpenAm instance to talk to 229 * @throws AuthLoginException if <code>AuthContext</code> creation fails. 230 * This exception is kept for backward compatibility only. 231 * 232 * @supported.api 233 */ 234 public AuthContext(String orgName, URL url) throws AuthLoginException { 235 organizationName = orgName; 236 authURL = url; 237 } 238 239 /** 240 * Constructs an instance of <code>AuthContext</code> for a given 241 * organization name, or sub organization name and a nick name 242 * for the certificate to be used in SSL handshake if client authentication 243 * is turn on in the server side. 244 * This organization or sub-organization name must be either "/" separated 245 * ( where it starts with "/" ) , DN , Domain name or DNS Alias Name. 246 * 247 * This constructor would be mainly used for the Certificate based 248 * authentication. If the certificate database contains multiple matching 249 * certificates for SSL, this constructor must be called in order for the 250 * desired certificate to be used for the Certificate based authentication. 251 * 252 * Caller would then use <code>login</code> to start the 253 * authentication process and use <code>getRequirements()</code> and 254 * <code>submitRequirements()</code> to pass the credentials 255 * needed for authentication by the plugin authentication modules. 256 * The method <code>getStatus()</code> returns the 257 * authentication status. 258 * 259 * @param orgName name of the user's organization 260 * @param nickName nick name for the certificate to be used 261 * @throws AuthLoginException if <code>AuthContext</code> creation fails. 262 * This exception is kept for backward compatibility only. 263 * 264 * @supported.api 265 */ 266 public AuthContext(String orgName, String nickName) 267 throws AuthLoginException { 268 organizationName = orgName; 269 this.nickName = nickName; 270 } 271 272 /** 273 * Constructs an instance of <code>AuthContext</code> for a given 274 * organization name, or sub organization name, a nick name 275 * for the certificate to be used in SSL handshake if client authentication 276 * is enabled on the server side and the OpenAM URL. 277 * This organization or sub-organization name must be either "/" separated 278 * ( where it starts with "/" ) , DN , Domain name or a DNS Alias Name. 279 * And the <code>url</code> should specify the OpenAM server's protocol, 280 * host name, and port number, 281 * for example : <code>http://daye.red.iplanet.com:58080</code> 282 * This constructor would be mainly used for the Certificate based 283 * authentication. If the certificate database contains multiple matching 284 * certificates for SSL, this constructor must be called in order for the 285 * desired certificate to be used for the Certificate based authentication. 286 * 287 * Caller would then use <code>login</code> to start the 288 * authentication process and use <code>getRequirements()</code> and 289 * <code>submitRequirements()</code> to pass the credentials 290 * needed for authentication by the plugin authentication modules. 291 * The method <code>getStatus()</code> returns the 292 * authentication status. 293 * 294 * @param orgName name of the user's organization 295 * @param nickName nick name for the certificate to be used 296 * @param url URL of the OpenAM server to talk to 297 * @throws AuthLoginException if <code>AuthContext</code> creation fails. 298 * This exception is kept for backward compatibility only. 299 * 300 * @supported.api 301 */ 302 public AuthContext(String orgName, String nickName, URL url) 303 throws AuthLoginException { 304 organizationName = orgName; 305 this.nickName = nickName; 306 authURL = url; 307 } 308 309 /** 310 * Constructs an instance of <code>AuthContext</code> for a given 311 * organization name, or sub organization name contained in the 312 * single sign on token. 313 * 314 * This constructor should be called for re-authentication of an 315 * authenticated user. single sign on token is the authenticated resource's 316 * Single-Sign-On Token. If the session properties based on 317 * the login method used matches those in the user's new 318 * authenticated session then session upgrade will be done. 319 * A new session containing properties from both old single sign on token 320 * and new session shall be returned and old session will be 321 * destroyed if authentication passes. 322 * 323 * Caller would then use <code>login</code> to start the 324 * authentication process and use <code>getRequirements()</code> and 325 * <code>submitRequirements()</code> to pass the credentials 326 * needed for authentication by the plugin authentication modules. 327 * The method <code>getStatus()</code> returns the 328 * authentication status. 329 * 330 * @param ssoToken single sign on token representing the resource's previous 331 * authenticated session. 332 * @throws AuthLoginException if <code>AuthContext</code> creation fails. 333 * This exception is kept for backward compatibility only. 334 * 335 * @supported.api 336 */ 337 public AuthContext(SSOToken ssoToken) throws AuthLoginException { 338 this.ssoToken = ssoToken; 339 } 340 341 /** 342 * Constructs an instance of <code>AuthContext</code> for a given 343 * organization name, or sub organization name contained in the 344 * single sign on token. 345 * 346 * This constructor should be called for re-authentication of an 347 * authenticated user. single sign on token is the authenticated resource's 348 * Single-Sign-On Token. If the session properties based on 349 * the login method used matches those in the user's new 350 * authenticated session then session upgrade will be done. 351 * If forceAuth flag is <code>true</code> then the existing session 352 * is used and no new session is created otherwise this constructor 353 * behaves same as the constructor with no forceAuth flag. 354 * 355 * Caller would then use <code>login</code> to start the 356 * authentication process and use <code>getRequirements()</code> and 357 * <code>submitRequirements()</code> to pass the credentials 358 * needed for authentication by the plugin authentication modules. 359 * The method <code>getStatus()</code> returns the 360 * authentication status. 361 * 362 * @param ssoToken single sign on token representing the resource's 363 * previous authenticated session. 364 * @param forceAuth indicates that authentication preocess has to be 365 * restarted and given single sign on token will be used and new 366 * session will not be created. 367 * @throws AuthLoginException if <code>AuthContext</code> creation fails. 368 * This exception is kept for backward compatibility only. 369 * 370 * @supported.api 371 */ 372 public AuthContext(SSOToken ssoToken, boolean forceAuth) throws 373 AuthLoginException { 374 this.ssoToken = ssoToken; 375 this.forceAuth = forceAuth; 376 } 377 378 /** 379 * Starts the login process for the given <code>AuthContext</code> object. 380 * 381 * @exception AuthLoginException if an error occurred during login. 382 * 383 * @supported.api 384 */ 385 public void login() throws AuthLoginException { 386 login(null, null, null, null, null, null); 387 } 388 389 /** 390 * Starts the login process for the given <code>AuthContext</code> object. 391 * 392 * @param request The HttpServletRequest that was sent to start the authentication process. 393 * @param response The corresponding HttpServletResponse for the HttpServletRequest. 394 * @throws AuthLoginException If an error occurred during login. 395 * 396 * @supported.api 397 */ 398 public void login(HttpServletRequest request, HttpServletResponse response) throws AuthLoginException { 399 login(null, null, null, null, request, response); 400 } 401 402 /** 403 * Starts the login process for the given <code>AuthContext</code> object 404 * identified by the index type and index name. The <code>IndexType</code> 405 * defines the possible kinds of "objects" or "resources" for which an 406 * authentication can be performed. Currently supported index types are 407 * users, roles, services (or application), levels, resources and 408 * mechanism/authentication modules. 409 * 410 * @param type Authentication index type. 411 * @param indexName Authentication index name. 412 * @exception AuthLoginException if an error occurred during login. 413 * 414 * @supported.api 415 */ 416 public void login(IndexType type, String indexName) 417 throws AuthLoginException { 418 login(type, indexName, null, null, null, null); 419 } 420 421 /** 422 * Starts the login process for the given <code>AuthContext</code> object 423 * identified by the index type and index name. 424 * The <code>IndexType</code> defines the possible kinds of "objects" 425 * or "resources" for which an authentication can 426 * be performed. Currently supported index types are 427 * users, roles, services (or application), levels, resources and mechanism. 428 * It allows the caller to pass in the desired locale for this request. 429 * 430 * @param type authentication index type 431 * @param indexName authentication index name 432 * @param locale locale setting 433 * 434 * @exception AuthLoginException if an error occurred during login 435 */ 436 public void login(IndexType type, String indexName, String locale) 437 throws AuthLoginException { 438 login(type, indexName, null, null, locale); 439 } 440 441 /** 442 * Starts the login process for the given <code>AuthContext</code> object 443 * identified by the index type and index name and also completes 444 * the login process by submitting the given User credentials 445 * in the form of Callbacks. 446 * The <code>IndexType</code> defines the possible kinds of "objects" 447 * or "resources" for which an authentication can 448 * be performed. Currently supported index types are 449 * users, roles, services (or application), levels, resources and mechanism. 450 * <p> 451 * NOTE : This is a simplified wrapper method to eliminate multi-step calls 452 * to 'login' and submit credentials. This method is useful and will work 453 * only for those authentication modules which require only one set of 454 * callbacks or one page. This method can not be used to authenticate to 455 * authentication modules which require user interaction or multiple pages. 456 * 457 * @param type Authentication index type. 458 * @param indexName Authentication index name. 459 * @param userInfo User information/credentials in the form of array of 460 * <code>Callback</code> objects. The <code>Callback</code> objects 461 * array must be in the same order as defined in the authentication 462 * module properties file, otherwise authentication module code will 463 * not work. 464 * @return single-sign-on token for the valid user after successful 465 * authentication. 466 * @exception AuthLoginException if an error occurred during login. 467 */ 468 public SSOToken login(IndexType type, String indexName, Callback[] userInfo) 469 throws AuthLoginException { 470 login(type, indexName, null, null, null, null); 471 472 SSOToken ssoToken = null; 473 Callback[] callbacks = null; 474 475 while (hasMoreRequirements()) { 476 callbacks = getRequirements(); 477 478 if (callbacks != null) { 479 try { 480 submitRequirements(userInfo); 481 } catch (Exception e) { 482 if (authDebug.messageEnabled()) { 483 authDebug.message( 484 "Error: submitRequirements with userInfo : " 485 + e.getMessage()); 486 } 487 throw new AuthLoginException(e); 488 } 489 } 490 } 491 try { 492 if (getStatus() == AuthContext.Status.SUCCESS) { 493 ssoToken = getSSOToken(); 494 } 495 } catch (Exception e) { 496 if (authDebug.messageEnabled()) { 497 authDebug.message("Error: getSSOToken : " + e.getMessage()); 498 } 499 throw new AuthLoginException(e); 500 } 501 return ssoToken; 502 } 503 504 /** 505 * Starts the login process for the given <code>AuthContext</code> object 506 * identified by the index type and index name with default parameters. 507 * The <code>IndexType</code> defines the possible kinds of "objects" 508 * or "resources" for which an authentication can be performed. Currently 509 * supported index types are users, roles, services (or application), 510 * levels, resources and mechanism/authentication modules. 511 * 512 * @param indexType authentication index type. 513 * @param indexName authentication index name. 514 * @param params contains the default values for the callbacks. The order 515 * of this array matches the callbacks order for this login process. 516 * value for the <code>PasswordCallback</code> is also in String 517 * format, it will be converted to <code>char[]</code> when it is 518 * set to the callback. Internal processing for this string array 519 * uses <code>|</code> as separator. Hence <code>|</code> should not 520 * be used in these default values. Currently only 521 * <code>NameCallback</code> and <code>PasswordCallback</code> are 522 * supported. 523 * @exception AuthLoginException if an error occurred during login. 524 * 525 * @supported.api 526 */ 527 public void login(IndexType indexType, String indexName, String[] params) 528 throws AuthLoginException { 529 login(indexType, indexName, params, null, null, null); 530 } 531 532 public void login(IndexType indexType, 533 String indexName, 534 String[] params, 535 HttpServletRequest request, 536 HttpServletResponse response) 537 throws AuthLoginException { 538 login(indexType, indexName, params, null, request, response); 539 } 540 541 /** 542 * Starts the login process for the given <code>AuthContext</code> object 543 * identified by the index type and index name with certain parameters 544 * and environment map. 545 * The <code>IndexType</code> defines the possible kinds of "objects" 546 * or "resources" for which an authentication can be performed. Currently 547 * supported index types are users, roles, services (or application), 548 * levels, modules and resources. 549 * 550 * @param indexType authentication index type. 551 * @param indexName authentication index name. 552 * @param params contains the default values for the callbacks. The order 553 * of this array matches the callbacks order for this login process. 554 * value for the <code>PasswordCallback</code> is also in String 555 * format, it will be converted to <code>char[]</code> when it is 556 * set to the callback. Internal processing for this string array 557 * uses <code>|</code> as separator. Hence <code>|</code> should not 558 * be used in these default values. Currently only 559 * <code>NameCallback</code> and <code>PasswordCallback</code> are 560 * supported. 561 * @param envMap contains the environment key/value pairs. Key is a String 562 * object indicating the property name, value is a Set of String 563 * values for the property. Currenty this parameter only applicable 564 * when the indexTye is <code>AuthContext.IndexType.RESOURCE</code>. 565 * @exception AuthLoginException if an error occurred during login. 566 * 567 * @supported.api 568 */ 569 public void login(IndexType indexType, String indexName, 570 String[] params, Map envMap) 571 throws AuthLoginException { 572 login(indexType, indexName, params, envMap, null, null); 573 } 574 575 public void login( 576 IndexType indexType, 577 String indexName, 578 String[] params, 579 Map envMap, 580 HttpServletRequest request, 581 HttpServletResponse response 582 ) throws AuthLoginException { 583 if (clientLocale == null) { 584 login(indexType, indexName, params, envMap, null, request, response); 585 } else { 586 String localeStr = clientLocale.toString(); 587 login(indexType, indexName, params, envMap, localeStr, request, response); 588 } 589 } 590 591 private void login( 592 IndexType indexType, 593 String indexName, 594 String[] params, 595 Map envMap, 596 String locale 597 ) throws AuthLoginException { 598 login(indexType, indexName, params, envMap, locale, null, null); 599 } 600 601 private void login( 602 IndexType indexType, 603 String indexName, 604 String[] params, 605 Map envMap, 606 String locale, 607 HttpServletRequest request, 608 HttpServletResponse response 609 ) throws AuthLoginException { 610 if (ssoToken != null) { 611 try { 612 organizationName = ssoToken.getProperty( 613 ISAuthConstants.ORGANIZATION); 614 ssoTokenID = ssoToken.getTokenID().toString(); 615 authURL = sessionCache.getSession(new SessionID(ssoTokenID)).getSessionServiceURL(); 616 } catch (Exception e) { 617 throw new AuthLoginException(e); 618 } 619 } 620 621 if (authURL != null) { 622 authServiceURL = getAuthServiceURL(authURL.getProtocol(), 623 authURL.getHost(), Integer.toString(authURL.getPort()), 624 SystemProperties.get(Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR)); 625 } 626 627 AuthLoginException authException = null; 628 try { 629 if (authServiceURL == null) { 630 authServiceURL = getAuthServiceURL( server_proto, 631 server_host, server_port, server_uri); 632 } 633 if (authServiceURL != null) { 634 if (authDebug.messageEnabled()) { 635 authDebug.message("AuthContext.login : runLogin against " 636 + authServiceURL); 637 } 638 runLogin(indexType, indexName, params, envMap, locale, 639 request, response); 640 return; 641 } 642 } catch (AuthLoginException e) { 643 authException = e; 644 authDebug.error("Failed to login to " + authServiceURL); 645 } catch (Exception e) { 646 authDebug.error("Failed to login to " + authServiceURL 647 + ": " + e.getMessage(),e); 648 } 649 650 if (authURL == null) { 651 // failover when authURL is not specified 652 Vector serviceURLs = null; 653 try { 654 serviceURLs = WebtopNaming.getServiceAllURLs( 655 AuthXMLTags.AUTH_SERVICE); 656 } catch (Exception e) { 657 throw new AuthLoginException(amAuthContext, "loginError", 658 new Object[]{e.getMessage()}); 659 } 660 661 if (authDebug.messageEnabled()) { 662 authDebug.message("Org Name : " + organizationName); 663 authDebug.message("ssoTokenID: " + ssoTokenID); 664 authDebug.message("serviceURLs: " + serviceURLs); 665 } 666 667 if (serviceURLs != null) { 668 serviceURLs.remove(authServiceURL); 669 for (Enumeration e = serviceURLs.elements(); 670 e.hasMoreElements(); ) { 671 authServiceURL = (URL)e.nextElement(); 672 try { 673 runLogin(indexType, indexName, params, 674 envMap, locale, request, response); 675 return; 676 } catch (AuthLoginException ex) { 677 authException = ex; 678 authDebug.error("Failed to login in failover with " + 679 authServiceURL + ": " + ex.getMessage()); 680 } 681 } 682 } 683 } 684 authDebug.error("Authentication failed."); 685 if (authException != null) { 686 throw authException; 687 } else { 688 throw new AuthLoginException(amAuthContext, "loginError",null); 689 } 690 } 691 692 693 private void runLogin( 694 IndexType indexType, 695 String indexName, 696 String[] params, 697 Map envMap, 698 String locale, 699 HttpServletRequest request, 700 HttpServletResponse response 701 ) throws AuthLoginException { 702 if (!localFlag) { 703 setLocalFlag(authServiceURL); 704 } 705 706 if (appSSOToken == null) { 707 if (!((indexType == IndexType.MODULE_INSTANCE) && 708 (indexName.equals("Application")))){ 709 appSSOToken = getAppSSOToken(false); 710 } 711 } 712 713 if (localFlag) { 714 try { 715 if (ssoTokenID == null) { 716 acLocal = com.sun.identity.authentication.service.AuthUtils. 717 getAuthContext(organizationName); 718 } else { 719 if (authDebug.messageEnabled()) { 720 authDebug.message("AuthContext.runLogin: " 721 + "ForceAuth = "+forceAuth); 722 } 723 acLocal = com.sun.identity.authentication.service.AuthUtils. 724 getAuthContext(organizationName, ssoTokenID, false, 725 null, null, null, forceAuth); 726 } 727 LoginState loginState = acLocal.getLoginState(); 728 /* 729 * Set both the HttpRequest and HttpResponse on the login state so they are accessible by the Auth 730 * Modules. 731 */ 732 if (request != null) { 733 loginState.setHttpServletRequest(request); 734 Hashtable hashtable = AuthClientUtils.parseRequestParameters(request); 735 loginState.setParamHash(hashtable); 736 } 737 if (response != null) { 738 loginState.setHttpServletResponse(response); 739 } 740 if (hostName != null) { 741 acLocal.getLoginState().setClient(hostName); 742 } 743 acLocal.login(indexType, indexName, envMap, locale); 744 } catch (AuthException e) { 745 throw new AuthLoginException(e); 746 } 747 if (acLocal.getStatus().equals(Status.SUCCESS)) { 748 onSuccessLocal(); 749 } 750 return; 751 } 752 753 // Check if 7.0 RR stype protocol needs to be used 754 // This will setup NewAuthContext and authHandles 755 if (useOldStyleRemoteAuthentication) { 756 runRemoteOldAuthContext(); 757 if (loginException != null) { 758 throw loginException; 759 } 760 } 761 // Run Login 762 runRemoteLogin(indexType, indexName, params, envMap, locale, 763 request, response); 764 // reset the retry count 765 retryRunLogin = DEFAULT_RETRY_COUNT; 766 767 if (authDebug.messageEnabled()) { 768 authDebug.message("useNewStyleRemoteAuthentication : " 769 + useNewStyleRemoteAuthentication); 770 authDebug.message("useOldStyleRemoteAuthentication : " 771 + useOldStyleRemoteAuthentication); 772 authDebug.message("receivedDocument : " + receivedDocument); 773 authDebug.message("loginException : " + loginException); 774 } 775 776 // If "Login" fails and we have not set 6.3, 7.0 RR style protocol 777 // the server could be either 6.3 or 7.0 RR. Hence try "NewAuthContext" 778 // and then "Login" 779 if (!useNewStyleRemoteAuthentication && 780 !useOldStyleRemoteAuthentication && 781 (receivedDocument == null || 782 (getAuthenticationHandle(receivedDocument)).equals("null")) && 783 loginException != null) { 784 if (authDebug.messageEnabled()) { 785 authDebug.message("AuthContext: trying 6.3 style remote " + 786 "AuthN and setting the flag to use 6.3 style"); 787 } 788 useOldStyleRemoteAuthentication = true; 789 // Server could be either 6.3 or 7.0 RR, try old style 790 // Construct the Request XML with New AuthContext parameters 791 loginException = null; // Reset loginException 792 runRemoteOldAuthContext(); 793 if (loginException != null) { 794 throw loginException; 795 } 796 // Re-try login process with AuthIdentifier 797 runRemoteLogin(indexType, indexName, params, 798 envMap, locale, request, response); 799 // reset the retry count 800 retryRunLogin = DEFAULT_RETRY_COUNT; 801 } else if (!useNewStyleRemoteAuthentication) { 802 useNewStyleRemoteAuthentication = true; 803 } 804 if (loginException != null) { 805 throw loginException; 806 } 807 } 808 809 private void runRemoteLogin(IndexType indexType, String indexName, String[] params, Map envMap, 810 String locale, HttpServletRequest req, HttpServletResponse res) throws AuthLoginException { 811 try { 812 String xmlString; 813 // remote auth 814 StringBuilder request = new StringBuilder(100); 815 String authHandle = getAuthHandle(); 816 if (ssoTokenID != null && "0".equals(authHandle)) { 817 if (authDebug.messageEnabled()) { 818 authDebug.message("AuthContext.runRemoteLogin: Found SSOTokenID " + ssoTokenID); 819 } 820 authHandle = ssoTokenID; 821 } 822 823 request.append(MessageFormat.format(AuthXMLTags.XML_REQUEST_PREFIX, authHandle)); 824 if (appSSOToken != null) { 825 request.append(AuthXMLTags.APPSSOTOKEN_BEGIN); 826 request.append(appSSOToken.getTokenID().toString()); 827 request.append(AuthXMLTags.APPSSOTOKEN_END); 828 } 829 request.append(AuthXMLTags.LOGIN_BEGIN); 830 831 if (!useOldStyleRemoteAuthentication) { 832 request.append(AuthXMLTags.SPACE) 833 .append(AuthXMLTags.ORG_NAME_ATTR) 834 .append(AuthXMLTags.EQUAL) 835 .append(AuthXMLTags.QUOTE) 836 .append(XMLUtils.escapeSpecialCharacters(organizationName)) 837 .append(AuthXMLTags.QUOTE); 838 if (hostName != null) { 839 request.append(AuthXMLTags.SPACE) 840 .append(AuthXMLTags.HOST_NAME_ATTR) 841 .append(AuthXMLTags.EQUAL) 842 .append(AuthXMLTags.QUOTE) 843 .append(XMLUtils.escapeSpecialCharacters(hostName)) 844 .append(AuthXMLTags.QUOTE); 845 } 846 if (locale != null && !locale.isEmpty()) { 847 request.append(AuthXMLTags.SPACE) 848 .append(AuthXMLTags.LOCALE) 849 .append(AuthXMLTags.EQUAL) 850 .append(AuthXMLTags.QUOTE) 851 .append(XMLUtils.escapeSpecialCharacters(locale)) 852 .append(AuthXMLTags.QUOTE); 853 } 854 if (forceAuth) { 855 request.append(AuthXMLTags.SPACE) 856 .append(AuthXMLTags.FORCE_AUTH_ATTR) 857 .append(AuthXMLTags.EQUAL) 858 .append(AuthXMLTags.QUOTE) 859 .append("true") 860 .append(AuthXMLTags.QUOTE); 861 } 862 } 863 request.append(AuthXMLTags.ELEMENT_END); 864 865 if (indexType != null) { 866 request.append(AuthXMLTags.INDEX_TYPE_PAIR_BEGIN) 867 .append(AuthXMLTags.SPACE) 868 .append(AuthXMLTags.INDEX_TYPE) 869 .append(AuthXMLTags.EQUAL) 870 .append(AuthXMLTags.QUOTE); 871 872 if (indexType == IndexType.USER) { 873 request.append(AuthXMLTags.INDEX_TYPE_USER_ATTR); 874 } else if (indexType == IndexType.ROLE) { 875 request.append(AuthXMLTags.INDEX_TYPE_ROLE_ATTR); 876 } else if (indexType == IndexType.SERVICE) { 877 request.append(AuthXMLTags.INDEX_TYPE_SVC_ATTR); 878 } else if (indexType == IndexType.MODULE_INSTANCE) { 879 request.append(AuthXMLTags.INDEX_TYPE_MODULE_ATTR); 880 } else if (indexType == IndexType.LEVEL) { 881 request.append(AuthXMLTags.INDEX_TYPE_LEVEL_ATTR); 882 } else if (indexType == IndexType.COMPOSITE_ADVICE) { 883 request.append(AuthXMLTags.INDEX_TYPE_COMPOSITE_ADVICE_ATTR); 884 } else if (indexType == IndexType.RESOURCE) { 885 request.append(AuthXMLTags.INDEX_TYPE_RESOURCE); 886 } 887 request.append(AuthXMLTags.QUOTE) 888 .append(AuthXMLTags.ELEMENT_END) 889 .append(AuthXMLTags.INDEX_NAME_BEGIN) 890 .append(XMLUtils.escapeSpecialCharacters(indexName)) 891 .append(AuthXMLTags.INDEX_NAME_END) 892 .append(AuthXMLTags.INDEX_TYPE_PAIR_END); 893 } 894 895 if (locale != null && locale.length() > 0) { 896 request.append(AuthXMLTags.LOCALE_BEGIN); 897 request.append(XMLUtils.escapeSpecialCharacters(locale)); 898 request.append(AuthXMLTags.LOCALE_END); 899 } 900 901 if (params != null) { 902 StringBuilder paramString = new StringBuilder(); 903 for (int i = 0; i < params.length; i++) { 904 if (i != 0 ) { 905 paramString.append(ISAuthConstants.PIPE_SEPARATOR); 906 } 907 paramString.append(XMLUtils.escapeSpecialCharacters(params[i])); 908 } 909 request.append(AuthXMLTags.PARAMS_BEGIN) 910 .append(paramString.toString()) 911 .append(AuthXMLTags.PARAMS_END); 912 } 913 if (envMap != null && !envMap.isEmpty()) { 914 StringBuilder envString = new StringBuilder(); 915 for (Map.Entry<String, Set<String>> entry : ((Map<String, Set<String>>) envMap).entrySet()) { 916 // convert Map to XMLString as follows: 917 // <EnvValue>keyname|value1|value2|...</EnvValue> 918 String keyName = entry.getKey(); 919 Set<String> values = entry.getValue(); 920 if (values != null && !values.isEmpty()) { 921 envString.append(AuthXMLTags.ENV_AV_BEGIN) 922 .append(AuthClientUtils.escapePipe(XMLUtils.escapeSpecialCharacters(keyName))); 923 for (String value : values) { 924 envString.append(ISAuthConstants.PIPE_SEPARATOR) 925 .append(AuthClientUtils.escapePipe(XMLUtils.escapeSpecialCharacters(value))); 926 } 927 envString.append(AuthXMLTags.ENV_AV_END); 928 } 929 } 930 request.append(AuthXMLTags.ENV_BEGIN) 931 .append(envString.toString()) 932 .append(AuthXMLTags.ENV_END); 933 } 934 request.append(AuthXMLTags.LOGIN_END); 935 936 if (includeReqRes) { 937 request.append(AuthXMLTags.REMOTE_REQUEST_RESPONSE_START) 938 .append(AuthXMLTags.HTTP_SERVLET_REQUEST_START); 939 String encObj = ""; 940 941 if (req != null) { 942 try { 943 encObj = AuthXMLUtils.serializeToString(new RemoteHttpServletRequest(req)); 944 } catch (IOException ioe) { 945 authDebug.error("AuthXMLUtils::runRemoteLogin Unable to serailize http request", ioe); 946 } 947 948 if (authDebug.messageEnabled()) { 949 authDebug.message("req=" + new RemoteHttpServletRequest(req).toString()); 950 } 951 952 request.append(encObj); 953 } 954 955 request.append(AuthXMLTags.HTTP_SERVLET_REQUEST_END); 956 request.append(AuthXMLTags.HTTP_SERVLET_RESPONSE_START); 957 958 if (res != null) { 959 encObj = ""; 960 961 try { 962 encObj = AuthXMLUtils.serializeToString(new RemoteHttpServletResponse(res)); 963 } catch (IOException ioe) { 964 authDebug.error("AuthXMLUtils::runRemoteLogin Unable to serailize http response", ioe); 965 } 966 967 if (authDebug.messageEnabled()) { 968 authDebug.message("res=" + res); 969 } 970 971 request.append(encObj); 972 } 973 974 request.append(AuthXMLTags.HTTP_SERVLET_RESPONSE_END) 975 .append(AuthXMLTags.REMOTE_REQUEST_RESPONSE_END); 976 } else { 977 if (authDebug.messageEnabled()) { 978 authDebug.message("Not including req/res " + includeReqRes); 979 } 980 } 981 982 request.append(AuthXMLTags.XML_REQUEST_SUFFIX); 983 xmlString = request.toString(); 984 985 // process the request, which will check for exceptions 986 // and also get the authentication handle ID 987 receivedDocument = processRequest(xmlString); 988 989 // Check set the login status 990 checkAndSetLoginStatus(); 991 992 // if the app token was refreshed, retry remote login 993 if (loginException != null && 994 loginException.getErrorCode().equals(AMAuthErrorCode.REMOTE_AUTH_INVALID_SSO_TOKEN) && 995 retryRunLogin > 0) { 996 retryRunLogin--; 997 998 if (authDebug.messageEnabled()) { 999 authDebug.message("Run remote login failed due to expired app token, retying"); 1000 } 1001 1002 // reset as we are starting again 1003 loginStatus = Status.IN_PROGRESS; 1004 runRemoteLogin(indexType, indexName, params, envMap, locale, req, res); 1005 } 1006 } catch (AuthLoginException le) { 1007 // Login has failed 1008 loginStatus = Status.FAILED; 1009 loginException = le; 1010 } 1011 } 1012 1013 private void runRemoteOldAuthContext() throws AuthLoginException { 1014 try { 1015 StringBuilder request = new StringBuilder(100); 1016 String[] objs = { "0" }; 1017 if (ssoTokenID != null) { 1018 objs[0] = ssoTokenID; 1019 } 1020 request.append(MessageFormat.format( 1021 AuthXMLTags.XML_REQUEST_PREFIX, (Object[])objs)) 1022 .append(AuthXMLTags.NEW_AUTHCONTEXT_BEGIN) 1023 .append(AuthXMLTags.SPACE) 1024 .append(AuthXMLTags.ORG_NAME_ATTR) 1025 .append(AuthXMLTags.EQUAL) 1026 .append(AuthXMLTags.QUOTE) 1027 .append(XMLUtils.escapeSpecialCharacters(organizationName)) 1028 .append(AuthXMLTags.QUOTE) 1029 .append(AuthXMLTags.ELEMENT_END) 1030 .append(AuthXMLTags.NEW_AUTHCONTEXT_END) 1031 .append(AuthXMLTags.XML_REQUEST_SUFFIX); 1032 // process the request, which will check for exceptions 1033 // and also get the authentication handle ID 1034 receivedDocument = processRequest(request.toString()); 1035 1036 // Check set the login status 1037 checkAndSetLoginStatus(); 1038 } catch (AuthLoginException le) { 1039 // Login has failed 1040 loginStatus = Status.FAILED; 1041 loginException = le; 1042 } 1043 } 1044 1045 /** 1046 * Returns the set of Principals or Subject the user has been 1047 * authenticated as. 1048 * This should be invoked only after successful authentication. 1049 * 1050 * @return <code>Subject</code> for the authenticated User. 1051 * If the authentication fails or the authentication is in process, 1052 * this will return <code>null</code>. 1053 * 1054 * @supported.api 1055 */ 1056 public Subject getSubject() { 1057 if (localFlag) { 1058 if (!acLocal.getStatus().equals(Status.SUCCESS)) { 1059 return (null); 1060 } 1061 return (acLocal.getSubject()); 1062 } else { 1063 if (!loginStatus.equals(Status.SUCCESS)) { 1064 return (null); 1065 } 1066 return (getSubject(receivedDocument)); 1067 } 1068 } 1069 1070 /** 1071 * Returns a <code>Map</code> object that 1072 * that contains cookies set by AM server 1073 * 1074 * @return a <code>Map</code> of cookie name and 1075 * <code>Cookie</code> object. 1076 */ 1077 public Map getCookieTable() { 1078 return cookieTable; 1079 } 1080 1081 /** 1082 * Returns <code>true</code> if the login process requires more 1083 * information from the user to complete the authentication. 1084 * <p> 1085 * NOTE: This method has to be called as a condition of a 1086 * <code>while</code> loop in order to complete the authentication process 1087 * and get the correct <code>Status</code> after submitting the 1088 * requirements. 1089 * 1090 * @return <code>true</code> if more credentials are required from the user. 1091 * 1092 * @supported.api 1093 */ 1094 public boolean hasMoreRequirements() { 1095 if (localFlag) { 1096 return (acLocal.hasMoreRequirements(false)); 1097 } else { 1098 if ((!loginStatus.equals(Status.IN_PROGRESS)) || 1099 ((getCallbacks(receivedDocument, false)) == null)) { 1100 return (false); 1101 } 1102 return (true); 1103 } 1104 } 1105 1106 /** 1107 * Returns <code>true</code> if the login process requires more information 1108 * from the user to complete the authentication. 1109 * 1110 * NOTE: This method has to be called as a condition of a <ode>while</code> 1111 * loop in order to complete the authentication process and get the correct 1112 * <code>Status</code> after submitting the requirements. 1113 * 1114 * @param noFilter flag indicates whether to filter 1115 * <code>PagePropertiesCallback</code> or not. Value 1116 * <code>true</code> will not filter 1117 * <code>PagePropertiesCallback</code>. 1118 * @return <code>true</code> if more credentials are required from the user. 1119 * 1120 * @supported.api 1121 */ 1122 public boolean hasMoreRequirements(boolean noFilter) { 1123 if (localFlag) { 1124 return (acLocal.hasMoreRequirements(noFilter)); 1125 } else { 1126 if ((!loginStatus.equals(Status.IN_PROGRESS)) || 1127 ((getCallbacks(receivedDocument, noFilter)) == null)) { 1128 return (false); 1129 } 1130 return (true); 1131 } 1132 } 1133 1134 /** 1135 * Returns an array of <code>Callback</code> objects that must be populated 1136 * by the user and returned back. These objects are requested by the 1137 * authentication plug-ins, and these are usually displayed to the user. 1138 * The user then provides the requested information for it to be 1139 * authenticated. 1140 * 1141 * @return an array of <code>Callback</code> objects requesting credentials 1142 * from user 1143 * 1144 * @supported.api 1145 */ 1146 public Callback[] getRequirements() { 1147 if (localFlag) { 1148 if (!acLocal.getStatus().equals(Status.IN_PROGRESS)) { 1149 return (null); 1150 } 1151 return (acLocal.getRequirements(false)); 1152 } else { 1153 if (!loginStatus.equals(Status.IN_PROGRESS)) { 1154 return (null); 1155 } 1156 return (getCallbacks(receivedDocument, false)); 1157 } 1158 } 1159 1160 /** 1161 * Returns an array of <code>Callback</code> objects that 1162 * must be populated by the user and returned back. 1163 * These objects are requested by the authentication plug-ins, 1164 * and these are usually displayed to the user. The user then provides 1165 * the requested information for it to be authenticated. 1166 * 1167 * @param noFilter boolean flag indicating whether to filter 1168 * <code>PagePropertiesCallback</code> or not. Value <code>true</code> will 1169 * not filter <code>PagePropertiesCallback</code>. 1170 * 1171 * @return an array of <code>Callback</code> objects requesting credentials 1172 * from user 1173 * 1174 * @supported.api 1175 */ 1176 public Callback[] getRequirements(boolean noFilter) { 1177 if (localFlag) { 1178 if (!acLocal.getStatus().equals(Status.IN_PROGRESS)) { 1179 return (null); 1180 } 1181 return (acLocal.getRequirements(noFilter)); 1182 } else { 1183 if (!loginStatus.equals(Status.IN_PROGRESS)) { 1184 return (null); 1185 } 1186 return (getCallbacks(receivedDocument, noFilter)); 1187 } 1188 } 1189 1190 /** 1191 * Fetches the remote request from the context 1192 * 1193 * @return The Http Servlet Request 1194 */ 1195 public HttpServletRequest getRemoteRequest() { 1196 return remoteRequest; 1197 } 1198 1199 /** 1200 * Fetches the remote response from the context 1201 * 1202 * @return The Http Servlet Response 1203 */ 1204 public HttpServletResponse getRemoteResponse() { 1205 return remoteResponse; 1206 } 1207 1208 /** 1209 * Submits the populated <code>Callback</code> objects to the 1210 * authentication plug-in modules. Called after <code>getRequirements</code> 1211 * method and obtaining user's response to these requests. 1212 * 1213 * @param info Array of <code>Callback</code> objects. 1214 * 1215 * @supported.api 1216 */ 1217 public void submitRequirements(Callback[] info) { 1218 submitRequirements(info, null, null); 1219 } 1220 1221 public void submitRequirements(Callback[] info, HttpServletRequest request, 1222 HttpServletResponse response) { 1223 if (authDebug.messageEnabled()) { 1224 authDebug.message("submitRequirements with Callbacks : " + info); 1225 } 1226 1227 if (localFlag) { 1228 // Check if we are still in login session 1229 if (!acLocal.getStatus().equals(Status.IN_PROGRESS)) { 1230 return; 1231 } 1232 acLocal.submitRequirements(info); 1233 if (acLocal.getStatus().equals(Status.SUCCESS)) { 1234 onSuccessLocal(); 1235 } 1236 return; 1237 } else { 1238 // Check if we are still in login session 1239 if (!loginStatus.equals(Status.IN_PROGRESS)) { 1240 return; 1241 } 1242 1243 // Construct the XML 1244 try { 1245 StringBuilder xml = new StringBuilder(100); 1246 String[] authHandles = new String[1]; 1247 authHandles[0] = getAuthenticationHandle(receivedDocument); 1248 xml.append(MessageFormat.format( 1249 AuthXMLTags.XML_REQUEST_PREFIX,(Object[])authHandles)); 1250 if (appSSOToken != null) { 1251 xml.append(AuthXMLTags.APPSSOTOKEN_BEGIN); 1252 xml.append(appSSOToken.getTokenID().toString()). 1253 append(AuthXMLTags.APPSSOTOKEN_END); 1254 } 1255 xml.append(AuthXMLTags.SUBMIT_REQS_BEGIN) 1256 .append(AuthXMLUtils.getXMLForCallbacks(info)); 1257 1258 if (clientLocale != null) { 1259 String localeStr = clientLocale.toString(); 1260 if ((localeStr != null) && (localeStr.length() > 0)) { 1261 xml.append(AuthXMLTags.LOCALE_BEGIN) 1262 .append(XMLUtils.escapeSpecialCharacters(localeStr)) 1263 .append(AuthXMLTags.LOCALE_END); 1264 } 1265 } 1266 1267 xml.append(AuthXMLTags.SUBMIT_REQS_END); 1268 1269 if (includeReqRes) { 1270 // serialized request and response objects 1271 xml.append(AuthXMLTags.REMOTE_REQUEST_RESPONSE_START) 1272 .append(AuthXMLTags.HTTP_SERVLET_REQUEST_START); 1273 String encObj = ""; 1274 1275 if (request != null) { 1276 try { 1277 encObj = AuthXMLUtils.serializeToString(new RemoteHttpServletRequest(request)); 1278 } catch (IOException ioe) { 1279 authDebug.error("AuthXMLUtils::runRemoteLogin Unable to serailize http request", ioe); 1280 } 1281 1282 if (authDebug.messageEnabled()) { 1283 authDebug.message("req=" + request); 1284 } 1285 1286 xml.append(encObj); 1287 } 1288 1289 xml.append(AuthXMLTags.HTTP_SERVLET_REQUEST_END); 1290 xml.append(AuthXMLTags.HTTP_SERVLET_RESPONSE_START); 1291 1292 if (response != null) { 1293 encObj = ""; 1294 1295 try { 1296 encObj = AuthXMLUtils.serializeToString(new RemoteHttpServletResponse(response)); 1297 } catch (IOException ioe) { 1298 authDebug.error("AuthXMLUtils::runRemoteLogin Unable to serailize http response", ioe); 1299 } 1300 1301 if (authDebug.messageEnabled()) { 1302 authDebug.message("res=" + response); 1303 } 1304 1305 xml.append(encObj); 1306 } 1307 1308 xml.append(AuthXMLTags.HTTP_SERVLET_RESPONSE_END) 1309 .append(AuthXMLTags.REMOTE_REQUEST_RESPONSE_END); 1310 } 1311 xml.append(AuthXMLTags.XML_REQUEST_SUFFIX); 1312 1313 // Send the request to be processes 1314 receivedDocument = processRequest(xml.toString()); 1315 1316 // Check set the login status 1317 checkAndSetLoginStatus(); 1318 } catch (AuthLoginException le) { 1319 // Login has failed 1320 loginStatus = Status.FAILED; 1321 loginException = le; 1322 } 1323 } 1324 } 1325 1326 /** 1327 * Logs out the user and also invalidates the single sign on token 1328 * associated with this <code>AuthContext</code>. 1329 * 1330 * @throws AuthLoginException if an error occurred during logout. 1331 * 1332 * @supported.api 1333 */ 1334 public void logout() throws AuthLoginException { 1335 if (localFlag) { 1336 acLocal.logout(); 1337 return; 1338 } 1339 1340 // Construct the XML 1341 try { 1342 StringBuilder xml = new StringBuilder(100); 1343 String[] authHandles = new String[1]; 1344 authHandles[0] = getAuthenticationHandle(receivedDocument); 1345 xml.append(MessageFormat.format(AuthXMLTags.XML_REQUEST_PREFIX, 1346 (Object[])authHandles)); 1347 if (appSSOToken != null) { 1348 xml.append(AuthXMLTags.APPSSOTOKEN_BEGIN); 1349 xml.append(appSSOToken.getTokenID().toString()). 1350 append(AuthXMLTags.APPSSOTOKEN_END); 1351 } 1352 xml.append(AuthXMLTags.LOGOUT_BEGIN) 1353 .append(AuthXMLTags.LOGOUT_END) 1354 .append(AuthXMLTags.XML_REQUEST_SUFFIX); 1355 1356 // Send the request to be processes 1357 receivedDocument = processRequest(xml.toString()); 1358 1359 // Check set the login status 1360 checkAndSetLoginStatus(); 1361 } catch (AuthLoginException le) { 1362 // Login has failed 1363 loginStatus = Status.FAILED; 1364 loginException = le; 1365 } 1366 } 1367 1368 /** 1369 * Logs out the user and also invalidates the single sign on token 1370 * associated with this <code>AuthContext</code>. 1371 * 1372 * This method causes the logout to happen on the server and the 1373 * correct SPI hooks to be called. 1374 * 1375 * @throws AuthLoginException if an error occurred during logout. 1376 * 1377 * @supported.api 1378 */ 1379 public void logoutUsingTokenID() 1380 throws AuthLoginException { 1381 if (localFlag) { 1382 return; 1383 } 1384 1385 if (ssoToken != null) { 1386 try { 1387 organizationName = ssoToken.getProperty( 1388 ISAuthConstants.ORGANIZATION); 1389 ssoTokenID = ssoToken.getTokenID().toString(); 1390 authURL = sessionCache.getSession(new SessionID(ssoTokenID)).getSessionServiceURL(); 1391 } catch (Exception e) { 1392 throw new AuthLoginException(e); 1393 } 1394 } 1395 1396 if (authURL != null) { 1397 authServiceURL = getAuthServiceURL(authURL.getProtocol(), 1398 authURL.getHost(), Integer.toString(authURL.getPort()), 1399 authURL.getPath()); 1400 } 1401 1402 1403 // Construct the XML 1404 try { 1405 StringBuilder xml = new StringBuilder(100); 1406 String[] authHandles = new String[1]; 1407 authHandles[0] = ssoToken.getTokenID().toString(); 1408 xml.append(MessageFormat.format(AuthXMLTags.XML_REQUEST_PREFIX, 1409 (Object[]) authHandles)); 1410 if (appSSOToken != null) { 1411 xml.append(AuthXMLTags.APPSSOTOKEN_BEGIN); 1412 xml.append(appSSOToken.getTokenID().toString()). 1413 append(AuthXMLTags.APPSSOTOKEN_END); 1414 } 1415 xml.append(AuthXMLTags.LOGOUT_BEGIN) 1416 .append(AuthXMLTags.LOGOUT_END) 1417 .append(AuthXMLTags.XML_REQUEST_SUFFIX); 1418 1419 // Send the request to be processes 1420 receivedDocument = processRequest(xml.toString()); 1421 1422 // Check set the login status 1423 checkAndSetLoginStatus(); 1424 } catch (AuthLoginException le) { 1425 // Login has failed 1426 loginStatus = Status.FAILED; 1427 loginException = le; 1428 } 1429 } 1430 1431 /** 1432 * Returns login exception, if any, during the authentication process. 1433 * Typically set when the login fails. 1434 * 1435 * @return login exception. 1436 * @supported.api 1437 */ 1438 public AuthLoginException getLoginException() { 1439 if (localFlag) { 1440 return (acLocal.getLoginException()); 1441 } else { 1442 return (loginException); 1443 } 1444 } 1445 1446 /** 1447 * Returns the Single-Sign-On (SSO) Token for the authenticated 1448 * user. If the user has not successfully authenticated 1449 * <code>Exception</code> will be thrown. 1450 * <p> 1451 * Single sign token can be used as the authenticated token. 1452 * 1453 * @return Single-Sign-On token for the valid user after successful 1454 * authentication. 1455 * @throws L10NMessageImpl if the user is not authenticated or an error is 1456 * encountered in retrieving the user's single sign on token. 1457 * @supported.api 1458 */ 1459 public SSOToken getSSOToken() throws L10NMessageImpl { 1460 if (localFlag) { 1461 if (!acLocal.getStatus().equals(Status.SUCCESS)) { 1462 throw new L10NMessageImpl( 1463 amAuthContext, "statusNotSuccess", null); 1464 } 1465 return (acLocal.getSSOToken()); 1466 } else { 1467 // Get the loginStatus node 1468 if (!loginStatus.equals(Status.SUCCESS)) { 1469 throw new L10NMessageImpl( 1470 amAuthContext, "statusNotSuccess", null); 1471 } 1472 Node loginStatusNode = XMLUtils.getRootNode(receivedDocument, 1473 AuthXMLTags.LOGIN_STATUS); 1474 if (loginStatusNode == null) { 1475 throw new L10NMessageImpl(amAuthContext, "noStatusNode", null); 1476 } 1477 1478 String ssoTokenIDTmp = XMLUtils.getNodeAttributeValue(loginStatusNode, 1479 AuthXMLTags.SSOTOKEN); 1480 try { 1481 return new com.iplanet.sso.providers.dpro.SSOProviderImpl(). 1482 createSSOToken(ssoTokenIDTmp, true); 1483 } catch (SSOException ssoe) { 1484 throw new L10NMessageImpl( 1485 amAuthContext, "createSSOTokenError", null); 1486 } 1487 } 1488 } 1489 1490 /** 1491 * Returns the current status of the authentication process as 1492 * <code>AuthContext.Status</code>. 1493 * 1494 * @return <code>Status</code> of the authentication process. 1495 * 1496 * @supported.api 1497 */ 1498 public Status getStatus() { 1499 if (localFlag) { 1500 return (acLocal.getStatus()); 1501 } else { 1502 return (loginStatus); 1503 } 1504 } 1505 1506 /** 1507 * Returns the current Auth Identifier of the authentication 1508 * process as String Session ID. 1509 * 1510 * @return Auth Identifier of the authentication process. 1511 */ 1512 public String getAuthIdentifier() { 1513 if (localFlag) { 1514 return (acLocal.getAuthIdentifier()); 1515 } else { 1516 return (getAuthHandle()); 1517 } 1518 } 1519 1520 /** 1521 * Returns the Successful Login URL for the authenticated user. 1522 * 1523 * @return the Successful Login URL for the authenticated user. 1524 * @throws Exception if it fails to get url for auth success 1525 */ 1526 public String getSuccessURL() throws Exception { 1527 if (localFlag) { 1528 if (!acLocal.getStatus().equals(Status.SUCCESS)) { 1529 throw new 1530 L10NMessageImpl(amAuthContext, "statusNotSuccess", null); 1531 } 1532 return (acLocal.getSuccessURL()); 1533 } else { 1534 // Get the loginStatus node 1535 if (!loginStatus.equals(Status.SUCCESS)) { 1536 throw new 1537 L10NMessageImpl(amAuthContext, "statusNotSuccess", null); 1538 } 1539 Node loginStatusNode = XMLUtils.getRootNode(receivedDocument, 1540 AuthXMLTags.LOGIN_STATUS); 1541 if (loginStatusNode == null) { 1542 throw new L10NMessageImpl(amAuthContext, "noStatusNode", null); 1543 } 1544 return (XMLUtils.getNodeAttributeValue(loginStatusNode, 1545 AuthXMLTags.SUCCESS_URL)); 1546 } 1547 } 1548 1549 /** 1550 * Returns the Failure Login URL for the authenticating user. 1551 * 1552 * @return the Failure Login URL for the authenticating user 1553 * @throws Exception if it fails to get url for auth failure 1554 */ 1555 public String getFailureURL() throws Exception { 1556 if (localFlag) { 1557 return (acLocal.getFailureURL()); 1558 } else { 1559 // Get the loginStatus node 1560 Node loginStatusNode = XMLUtils.getRootNode(receivedDocument, 1561 AuthXMLTags.LOGIN_STATUS); 1562 if (loginStatusNode == null) { 1563 throw new L10NMessageImpl(amAuthContext, "noStatusNode", null); 1564 } 1565 return (XMLUtils.getNodeAttributeValue(loginStatusNode, 1566 AuthXMLTags.FAILURE_URL)); 1567 } 1568 } 1569 1570 /** 1571 * Resets this instance of <code>AuthContext</code> object, so that a new 1572 * login process can be initiated. A new authentication process can started 1573 * using any one of the <code>login</code> methods. 1574 */ 1575 public void reset() { 1576 loginStatus = Status.NOT_STARTED; 1577 //organizationName = null; 1578 //receivedDocument = null; 1579 //loginException = null; 1580 } 1581 1582 /** 1583 * Returns the the organization name that was set during the 1584 * <code>AuthContext</code> constructor. 1585 * 1586 * @return Organization name in the <code>AuthContext</code>. 1587 * 1588 * @supported.api 1589 */ 1590 public String getOrganizationName() { 1591 return (this.organizationName); 1592 } 1593 1594 /** 1595 * 1596 * Returns authentication module/s instances (or plugins) configured 1597 * for a organization, or sub-organization name that was set during the 1598 * <code>AuthContext</code> constructor. 1599 * 1600 * @return Set of Module instance names. 1601 * 1602 * @supported.api 1603 */ 1604 public Set getModuleInstanceNames() { 1605 if (authURL != null) { 1606 authServiceURL = getAuthServiceURL( 1607 authURL.getProtocol(), 1608 authURL.getHost(), 1609 Integer.toString(authURL.getPort()), 1610 authURL.getPath()); 1611 } 1612 if (!localFlag) { 1613 setLocalFlag(authServiceURL); 1614 } 1615 if (localFlag) { 1616 return (acLocal.getModuleInstanceNames()); 1617 } else { 1618 if (authServiceURL == null) { 1619 try { 1620 authServiceURL = getAuthServiceURL(server_proto, 1621 server_host, server_port, server_uri); 1622 } catch (Exception e) { 1623 return Collections.EMPTY_SET; 1624 } 1625 } 1626 sendQueryInformation(AuthXMLTags.MODULE_INSTANCE); 1627 1628 //Receive data 1629 Node queryResultNode = XMLUtils.getRootNode(receivedDocument, 1630 AuthXMLTags.QUERY_RESULT); 1631 if (queryResultNode == null) { 1632 return (null); 1633 } 1634 1635 // Iteratate through moduleInstanceNames 1636 HashSet moduleInstanceNames = new HashSet(); 1637 NodeList childNodes = queryResultNode.getChildNodes(); 1638 if ( childNodes != null ) { 1639 for (int i = 0; i < childNodes.getLength(); i++) { 1640 Node childNode = childNodes.item(i); 1641 String moduleName = XMLUtils.getValueOfValueNode(childNode); 1642 moduleInstanceNames.add(moduleName); 1643 } 1644 } 1645 return (moduleInstanceNames); 1646 } 1647 } 1648 1649 /** 1650 * Terminates an ongoing <code>login</code> call that has not yet completed. 1651 * 1652 * @exception AuthLoginException if an error occurred during abort. 1653 * 1654 * @supported.api 1655 */ 1656 public void abort() throws AuthLoginException { 1657 if (localFlag) { 1658 acLocal.abort(); 1659 return; 1660 } 1661 1662 // Construct the XML 1663 try { 1664 StringBuilder xml = new StringBuilder(100); 1665 String[] authHandles = new String[1]; 1666 authHandles[0] = getAuthenticationHandle(receivedDocument); 1667 xml.append(MessageFormat.format(AuthXMLTags.XML_REQUEST_PREFIX, 1668 (Object[])authHandles)); 1669 if (appSSOToken != null) { 1670 xml.append(AuthXMLTags.APPSSOTOKEN_BEGIN); 1671 xml.append(appSSOToken.getTokenID().toString()). 1672 append(AuthXMLTags.APPSSOTOKEN_END); 1673 } 1674 xml.append(AuthXMLTags.ABORT_BEGIN) 1675 .append(AuthXMLTags.ABORT_END) 1676 .append(AuthXMLTags.XML_REQUEST_SUFFIX); 1677 1678 // Send the request to be processes 1679 receivedDocument = processRequest(xml.toString()); 1680 1681 // Check set the login status 1682 checkAndSetLoginStatus(); 1683 } catch (AuthLoginException le) { 1684 // Login has failed 1685 loginStatus = Status.FAILED; 1686 loginException = le; 1687 } 1688 } 1689 1690 /** 1691 * Sets the password for the certificate database. 1692 * It is required to call only once to initialize certificate database if 1693 * the password is not set in the password file (specified as 1694 * the value for <code>com.iplanet.am.admin.cli.certdb.passfile</code> 1695 * in <code>AMConfig.properties</code>). If both are set, this method will 1696 * overwrite the value in certificate password file. 1697 * 1698 * @param password Password for the certificate database. 1699 * 1700 * @supported.api 1701 */ 1702 public static void setCertDBPassword(String password) { 1703 try { 1704 if (usingJSSEHandler) { 1705 Class pcbClass = (Class) Class.forName(JSSE_PASSWORD_CALLBACK); 1706 Object passwdCallback = (Object) pcbClass.newInstance(); 1707 Method method = 1708 pcbClass.getMethod("setPassword", new Class[] { String.class }); 1709 KeyStore keystore = (KeyStore)method.invoke( 1710 passwdCallback, new Object[] { password }); 1711 } else { 1712 Class initializer = Class.forName(JSS_PASSWORD_UTIL); 1713 Constructor initializerConstructor = initializer.getConstructor( 1714 new Class[] { String.class }); 1715 initializerConstructor.newInstance(new Object[] { password }); 1716 } 1717 } catch (Exception e) { 1718 e.printStackTrace(); 1719 authDebug.message("Error in setCertDBPassword : " + e.getMessage()); 1720 } 1721 } 1722 1723 1724 /** 1725 * Returns the error template. 1726 * 1727 * @return error template. 1728 */ 1729 public String getErrorTemplate() { 1730 if (localFlag) { 1731 return (acLocal.getErrorTemplate()); 1732 } else { 1733 if (receivedDocument == null) { 1734 //something went terribly wrong, let's return with internal error template 1735 return AuthClientUtils.getErrorTemplate(AMAuthErrorCode.AUTH_ERROR); 1736 } 1737 String errTemplate = ""; 1738 Node exceptionNode = XMLUtils.getRootNode(receivedDocument, 1739 AuthXMLTags.EXCEPTION); 1740 if (exceptionNode != null) { 1741 errTemplate = XMLUtils.getNodeAttributeValue(exceptionNode, 1742 AuthXMLTags.TEMPLATE_NAME); 1743 } 1744 return errTemplate; 1745 } 1746 } 1747 1748 /** 1749 * Returns the error message. 1750 * 1751 * @return error message. 1752 */ 1753 public String getErrorMessage() { 1754 if (localFlag) { 1755 return (acLocal.getErrorMessage()); 1756 } else { 1757 if (receivedDocument == null) { 1758 //something went terribly wrong, let's return with internal error message 1759 return AuthClientUtils.getErrorMessage(AMAuthErrorCode.AUTH_ERROR); 1760 } 1761 String errMessage = null; 1762 Node exceptionNode = XMLUtils.getRootNode(receivedDocument, 1763 AuthXMLTags.EXCEPTION); 1764 if (exceptionNode != null) { 1765 errMessage = XMLUtils.getNodeAttributeValue(exceptionNode, 1766 AuthXMLTags.MESSAGE); 1767 } 1768 return errMessage; 1769 } 1770 } 1771 1772 /** 1773 * Returns error code. 1774 * 1775 * @return error code with white space trimmed 1776 */ 1777 public String getErrorCode() { 1778 if (localFlag) { 1779 return (acLocal.getErrorCode()); 1780 } else { 1781 if (receivedDocument == null) { 1782 //something went terribly wrong 1783 return AMAuthErrorCode.AUTH_ERROR; 1784 } 1785 String errCode = ""; 1786 Node exceptionNode = XMLUtils.getRootNode(receivedDocument, 1787 AuthXMLTags.EXCEPTION); 1788 1789 if (exceptionNode != null) { 1790 errCode = XMLUtils.getNodeAttributeValue(exceptionNode, 1791 AuthXMLTags.ERROR_CODE); 1792 } 1793 1794 if (errCode != null) { 1795 return errCode.trim(); 1796 } else { 1797 return errCode; 1798 } 1799 } 1800 } 1801 1802 /** 1803 * Sets the client's hostname or IP address.This could be used 1804 * by the policy component to restrict access to resources. 1805 * This method is ineffective if the "Remote Auth Security" option under 1806 * the global configuration of Core Authentication Service is not enabled. 1807 * This method must be called before calling <code>login</code> method. 1808 * If it is called after calling <code>login</code> then 1809 * it is ineffective. 1810 * 1811 * @param hostname hostname or ip address 1812 * 1813 * @supported.api 1814 */ 1815 public void setClientHostName(String hostname) { 1816 this.hostName = hostname; 1817 } 1818 1819 /** 1820 * Returns the client's hostname or IP address as set by 1821 * setClientHostName 1822 * 1823 * @return hostname/IP address 1824 * 1825 * @supported.api 1826 */ 1827 public String getClientHostName() { 1828 return (hostName); 1829 } 1830 1831 /** 1832 * Sets locale based on user locale preferemce. 1833 * 1834 * @param loc locale preference of user 1835 */ 1836 public void setLocale (java.util.Locale loc) { 1837 clientLocale = loc; 1838 } 1839 1840 /** 1841 * Returns locale preference set in AuthConext 1842 * @return - user prefered locale. 1843 */ 1844 1845 public java.util.Locale getLocale () { 1846 return clientLocale; 1847 } 1848 1849 private AuthLoginException checkException(){ 1850 AuthLoginException exception = null; 1851 String error = getErrorCode(); 1852 1853 // if the app token is invalid, refresh the token 1854 if (error != null && error.equals(AMAuthErrorCode.REMOTE_AUTH_INVALID_SSO_TOKEN)) { 1855 appSSOToken = getAppSSOToken(true); 1856 } 1857 1858 if (error != null && error.length() != 0){ 1859 exception = new AuthLoginException("amAuth", error, null); 1860 } else { 1861 error = getErrorMessage(); 1862 if (error != null && error.length() != 0) { 1863 exception = new AuthLoginException(error); 1864 } 1865 } 1866 return exception; 1867 } 1868 1869 protected void checkAndSetLoginStatus(){ 1870 1871 Node loginStatusNode = XMLUtils.getRootNode( 1872 receivedDocument, AuthXMLTags.LOGIN_STATUS); 1873 if (loginStatusNode == null) { 1874 loginException = checkException(); 1875 1876 if (includeReqRes) { 1877 remoteRequest = AuthXMLUtils.getRemoteRequest( 1878 XMLUtils.getRootNode(receivedDocument, AuthXMLTags.REMOTE_REQUEST_RESPONSE)); 1879 remoteResponse = AuthXMLUtils.getRemoteResponse( 1880 XMLUtils.getRootNode(receivedDocument, AuthXMLTags.REMOTE_REQUEST_RESPONSE)); 1881 } 1882 } else { 1883 //since there was no error, we should reset the loginException, to handle the case when the first auth 1884 //server was not available. 1885 loginException = null; 1886 // Get the status attribute 1887 String status = XMLUtils.getNodeAttributeValue( 1888 loginStatusNode, AuthXMLTags.STATUS); 1889 if (status != null) { 1890 if (status.equals(Status.SUCCESS.toString())) { 1891 loginStatus = Status.SUCCESS; 1892 } else if (status.equals(Status.FAILED.toString())) { 1893 loginStatus = Status.FAILED; 1894 loginException = checkException(); 1895 } else if (status.equals(Status.COMPLETED.toString())) { 1896 loginStatus = Status.COMPLETED; 1897 } else if (status.equals(Status.IN_PROGRESS.toString())) { 1898 loginStatus = Status.IN_PROGRESS; 1899 } else if (status.equals(Status.RESET.toString())) { 1900 loginStatus = Status.RESET; 1901 } 1902 } 1903 1904 if (includeReqRes) { 1905 remoteRequest = AuthXMLUtils.getRemoteRequest( 1906 XMLUtils.getRootNode(receivedDocument, AuthXMLTags.REMOTE_REQUEST_RESPONSE)); 1907 remoteResponse = AuthXMLUtils.getRemoteResponse( 1908 XMLUtils.getRootNode(receivedDocument, AuthXMLTags.REMOTE_REQUEST_RESPONSE)); 1909 } 1910 1911 if (authDebug.messageEnabled()) { 1912 authDebug.message("LoginStatus : " + loginStatus); 1913 } 1914 } 1915 } 1916 1917 protected void sendQueryInformation(String reqInfo) { 1918 // Construct the XML 1919 try { 1920 StringBuilder xml = new StringBuilder(100); 1921 String[] authHandles = new String[1]; 1922 authHandles[0] = getAuthHandle(); 1923 1924 xml.append(MessageFormat.format(AuthXMLTags.XML_REQUEST_PREFIX, 1925 (Object[])authHandles)); 1926 if (appSSOToken != null) { 1927 xml.append(AuthXMLTags.APPSSOTOKEN_BEGIN); 1928 xml.append(appSSOToken.getTokenID().toString()). 1929 append(AuthXMLTags.APPSSOTOKEN_END); 1930 } 1931 xml.append(AuthXMLTags.QUERY_INFO_BEGIN) 1932 .append(AuthXMLTags.SPACE) 1933 .append(AuthXMLTags.REQUESTED_INFO) 1934 .append(AuthXMLTags.EQUAL) 1935 .append(AuthXMLTags.QUOTE) 1936 .append(reqInfo) 1937 .append(AuthXMLTags.QUOTE); 1938 1939 if (authHandles[0].equals("0")) { 1940 xml.append(AuthXMLTags.SPACE) 1941 .append(AuthXMLTags.ORG_NAME_ATTR) 1942 .append(AuthXMLTags.EQUAL) 1943 .append(AuthXMLTags.QUOTE) 1944 .append(XMLUtils.escapeSpecialCharacters(organizationName)) 1945 .append(AuthXMLTags.QUOTE); 1946 } 1947 1948 xml.append(AuthXMLTags.ELEMENT_END) 1949 .append(AuthXMLTags.QUERY_INFO_END) 1950 .append(AuthXMLTags.XML_REQUEST_SUFFIX); 1951 1952 // Send the request to be processes 1953 receivedDocument = processRequest(xml.toString()); 1954 1955 // Check set the login status 1956 checkAndSetLoginStatus(); 1957 } catch (AuthLoginException le) { 1958 // Login has failed 1959 loginStatus = Status.FAILED; 1960 loginException = le; 1961 } 1962 } 1963 1964 private void setLocalFlag(URL url) { 1965 try { 1966 String urlStr = url.getProtocol() + "://" + url.getHost() + ":" 1967 + Integer.toString(url.getPort()); 1968 1969 if (authDebug.messageEnabled()) { 1970 authDebug.message("in setLocalFlag(), url : " + urlStr); 1971 authDebug.message("AuthContext.localAuthServiceID : " + 1972 localAuthServiceID); 1973 } 1974 1975 if ((localAuthServiceID != null) && 1976 (urlStr.equalsIgnoreCase(localAuthServiceID)) 1977 ) { 1978 localFlag = true; 1979 } 1980 } catch (Exception e) { 1981 authDebug.error("AuthContext::setLocalFlag:: " + e); 1982 } 1983 } 1984 1985 protected Document processRequest(String xmlRequest) 1986 throws AuthLoginException { 1987 Document doc = null; 1988 1989 try { 1990 Request request = new Request(xmlRequest); 1991 RequestSet set = new RequestSet(AuthXMLTags.AUTH_SERVICE); 1992 set.addRequest(request); 1993 1994 URL url = authServiceURL; 1995 1996 if (url.getProtocol().equals("https") && (nickName != null)) { 1997 Class[] paramtype = {String.class}; 1998 Object[] param = {nickName}; 1999 String protHandler = protHandlerPkg + ".https.Handler"; 2000 Constructor construct = 2001 Class.forName(protHandler).getConstructor(paramtype); 2002 URLStreamHandler handler = 2003 (URLStreamHandler)construct.newInstance(param); 2004 url = new URL(url.getProtocol(), url.getHost(), url.getPort(), 2005 url.getFile(), handler); 2006 } 2007 2008 if (authDebug.messageEnabled()) { 2009 authDebug.message("Service URL : " + url.toString()); 2010 } 2011 2012 Vector responses = PLLClient.send(url, set, cookieTable); 2013 2014 if ((responses.isEmpty()) || (responses.size() != 1)) { 2015 throw new L10NMessageImpl(amAuthContext, "responseError", null); 2016 } 2017 2018 Response res = (Response) responses.elementAt(0); 2019 String responseStr = (String)res.getContent(); 2020 2021 doc = XMLUtils.getXMLDocument( 2022 new ByteArrayInputStream(responseStr.getBytes("UTF-8"))); 2023 } catch (Exception e) { 2024 authDebug.message("error in getting service url", e); 2025 throw new AuthLoginException(amAuthContext, "xmlProcessError", 2026 null, e); 2027 } 2028 return (doc); 2029 } 2030 2031 protected static void checkForException(Document document) 2032 throws AuthLoginException { 2033 Node exceptionNode = XMLUtils.getRootNode( 2034 document, AuthXMLTags.EXCEPTION); 2035 2036 if (exceptionNode != null) { 2037 throw (new AuthLoginException(XMLUtils.getNodeAttributeValue( 2038 exceptionNode, AuthXMLTags.MESSAGE))); 2039 } 2040 } 2041 2042 protected String getAuthenticationHandle(Document document) 2043 throws AuthLoginException { 2044 Node responseNode = XMLUtils.getRootNode( 2045 document, AuthXMLTags.RESPONSE); 2046 if (responseNode == null) { 2047 throw new AuthLoginException(amAuthContext, "responseError", null); 2048 } 2049 2050 String authID = XMLUtils.getNodeAttributeValue( 2051 responseNode, AuthXMLTags.AUTH_ID_HANDLE); 2052 return (authID); 2053 } 2054 2055 protected static Callback[] getCallbacks( 2056 Document document, 2057 boolean noFilter) { 2058 return (AuthXMLUtils.getCallbacks(XMLUtils.getRootNode(document, 2059 AuthXMLTags.CALLBACKS), noFilter)); 2060 } 2061 2062 protected static Subject getSubject(Document document) { 2063 Node loginStatusNode = XMLUtils.getRootNode(document, 2064 AuthXMLTags.LOGIN_STATUS); 2065 2066 if (loginStatusNode == null) { 2067 return (null); 2068 } 2069 2070 Node subjectNode = XMLUtils.getChildNode(loginStatusNode, 2071 AuthXMLTags.SUBJECT); 2072 2073 if (subjectNode == null) { 2074 return (null); 2075 } 2076 2077 String subject = XMLUtils.getValueOfValueNode(subjectNode); 2078 try { 2079 Subject sSubject = AuthXMLUtils.getDeSerializedSubject(subject); 2080 2081 if (authDebug.messageEnabled()) { 2082 authDebug.message("Deserialized subject : " 2083 + sSubject.toString()); 2084 } 2085 return sSubject; 2086 } catch (Exception e) { 2087 authDebug.message("get Deserialized subject error : " , e); 2088 return null; 2089 } 2090 2091 } 2092 2093 protected static String getXMLforSubject(Subject subject) { 2094 if (subject == null) { 2095 return (""); 2096 } 2097 StringBuilder request = new StringBuilder(100); 2098 request.append(AuthXMLTags.SUBJECT_BEGIN); 2099 String serializeSubject = AuthXMLUtils.getSerializedSubject(subject); 2100 request.append(serializeSubject); 2101 request.append(AuthXMLTags.SUBJECT_END); 2102 return (request.toString()); 2103 } 2104 2105 /** 2106 * Returns the account lockout message. This can be either a dynamic 2107 * message indicating the number of tries left or the the account 2108 * deactivated message. 2109 * 2110 * @return account lockout message. 2111 */ 2112 public String getLockoutMsg() { 2113 String lockoutMsg = null; 2114 if (localFlag) { 2115 lockoutMsg = acLocal.getLockoutMsg(); 2116 } else { 2117 // Account Lockout Warning Check by scanning the error 2118 // message in the exception thrown by the server 2119 lockoutMsg = getErrorMessage(); 2120 if((lockoutMsg == null) || 2121 (lockoutMsg.indexOf("Account lockout") == -1)){ 2122 lockoutMsg = ""; 2123 } 2124 } 2125 return lockoutMsg; 2126 } 2127 2128 /** 2129 * Returns <code>true</code> if account is lock out. 2130 * 2131 * @return <code>true</code> if account is lock out. 2132 */ 2133 public boolean isLockedOut() { 2134 boolean isLockedOut = false; 2135 if (localFlag) { 2136 isLockedOut = acLocal.isLockedOut(); 2137 } else { 2138 // TBD 2139 } 2140 2141 return isLockedOut; 2142 } 2143 2144 /** 2145 * The class <code>Status</code> defines the possible 2146 * authentication states during the login process. 2147 * 2148 * @supported.all.api 2149 */ 2150 public static class Status extends Object { 2151 2152 private String status; 2153 2154 /** 2155 * The <code>NOT_STARTED</code> status indicates that the login process 2156 * has not yet started. Basically, it means that the method 2157 * <code>login</code> has not been called. 2158 */ 2159 public static final Status NOT_STARTED = new Status("not_started"); 2160 2161 /** 2162 * The <code>IN_PROGRESS</code> status indicates that the login process 2163 * is in progress. Basically, it means that the <code>login</code> 2164 * method has been called and that this object is waiting for the user 2165 * to send authentication information. 2166 */ 2167 public static final Status IN_PROGRESS = new Status("in_progress"); 2168 2169 /** 2170 * 2171 * The <code>SUCCESS</code> indicates that the login process has 2172 * succeeded. 2173 */ 2174 public static final Status SUCCESS = new Status("success"); 2175 2176 /** 2177 * The <code>FAILED</code> indicates that the login process has failed. 2178 */ 2179 public static final Status FAILED = new Status("failed"); 2180 2181 /** 2182 * 2183 * The <code>COMPLETED</code> indicates that the user has been 2184 * successfully logged out. 2185 */ 2186 public static final Status COMPLETED = new Status("completed"); 2187 2188 /** 2189 * The <code>RESET</code> indicates that the login process has been 2190 * reset or re-initialized. 2191 */ 2192 public static final Status RESET = new Status("reset"); 2193 2194 /** 2195 * The <code>ORG_MISMATCH</code> indicates that the framework 2196 * <code>org</code> and the <code>org</code> required by the user do 2197 * not match. 2198 */ 2199 public static final Status ORG_MISMATCH = new Status("org_mismatch"); 2200 2201 2202 private Status() { 2203 // do nothing 2204 } 2205 2206 private Status(String s) { 2207 status = s; 2208 } 2209 2210 /** 2211 * Returns the string representation of the authentication status. 2212 * 2213 * @return String representation of authentication status. 2214 */ 2215 public String toString() { 2216 return (status); 2217 } 2218 2219 /** 2220 * Checks if two authentication status objects are equal. 2221 * 2222 * @param authStatus Reference object with which to compare. 2223 * @return <code>true</code> if the objects are same. 2224 */ 2225 public boolean equals(Object authStatus) { 2226 if (authStatus instanceof Status) { 2227 Status s = (Status) authStatus; 2228 return (s.status.equalsIgnoreCase(status)); 2229 } 2230 return (false); 2231 } 2232 } 2233 2234 /** 2235 * The class <code>IndexType</code> defines the possible kinds of "objects" 2236 * or "resources" for which an authentication can be performed. 2237 * 2238 * @supported.all.api 2239 */ 2240 public static class IndexType extends Object { 2241 2242 private String index; 2243 2244 /** 2245 * The <code>USER</code> index type indicates that the index name given 2246 * corresponds to a user. 2247 */ 2248 public static final IndexType USER = new IndexType("user"); 2249 2250 /** 2251 * The <code>ROLE</code> index type indicates that the index name given 2252 * corresponds to a role. 2253 */ 2254 public static final IndexType ROLE = new IndexType("role"); 2255 2256 /** 2257 * 2258 * The <code>SERVICE</code> index type indicates that the index name 2259 * given corresponds to a service (or application). 2260 */ 2261 public static final IndexType SERVICE = new IndexType("service"); 2262 2263 /** 2264 * The <code>LEVEL</code> index type indicates that the index name 2265 * given corresponds to a given authentication level. 2266 */ 2267 public static final IndexType LEVEL = new IndexType("level"); 2268 2269 /** 2270 * The <code>MODULE_INSTANCE</code> index type indicates that the index 2271 * name given corresponds to one of the authentication modules. 2272 */ 2273 public static final IndexType MODULE_INSTANCE = 2274 new IndexType("module_instance"); 2275 2276 /** 2277 * The <code>RESOURCE</code> index type indicates that the index 2278 * name given corresponds to a given policy protected resource URL. 2279 */ 2280 public static final IndexType RESOURCE = 2281 new IndexType("resource"); 2282 2283 /** 2284 * The <code>COMPOSITE_ADVICE</code> index type indicates that the 2285 * index name given corresponds to string in the form of XML 2286 * representing different Policy Authentication conditions, example 2287 * <code>AuthSchemeCondition</code>, <code>AuthLevelCondition</code>, 2288 * etc. 2289 */ 2290 public static final IndexType COMPOSITE_ADVICE = 2291 new IndexType("composite_advice"); 2292 2293 private IndexType() { 2294 // do nothing 2295 } 2296 2297 private IndexType(String s) { 2298 index = s; 2299 } 2300 2301 /** 2302 * Returns the string representation of the index type. 2303 * 2304 * @return String representation of index type. 2305 */ 2306 public String toString() { 2307 return (index); 2308 } 2309 2310 /** 2311 * Checks if two index type objects are equal. 2312 * 2313 * @param indexType Reference object with which to compare. 2314 * 2315 * @return <code>true</code> if the objects are same. 2316 */ 2317 public boolean equals(Object indexType) { 2318 if (indexType instanceof IndexType) { 2319 IndexType s = (IndexType) indexType; 2320 return (s.index.equalsIgnoreCase(index)); 2321 } 2322 return (false); 2323 } 2324 } 2325 2326 private String getAuthHandle() { 2327 String handle = null; 2328 2329 if (receivedDocument != null) { 2330 try { 2331 handle = getAuthenticationHandle(receivedDocument); 2332 } catch (Exception e) { 2333 // do nothing 2334 } 2335 } 2336 if ( handle == null ) { 2337 handle = "0"; 2338 } 2339 return handle; 2340 } 2341 2342 private static URL getAuthServiceURL( 2343 String protocol, 2344 String host, 2345 String port, 2346 String uri 2347 ) { 2348 URL authservice = null; 2349 try { 2350 authservice = WebtopNaming.getServiceURL(AuthXMLTags.AUTH_SERVICE, 2351 protocol, host, port, uri); 2352 } catch (Exception e) { 2353 authDebug.error("Failed to obtain auth service url from server: " + 2354 protocol + "://" + host + ":" + port); 2355 } 2356 return authservice; 2357 } 2358 2359 private void onSuccessLocal() { 2360 if (localSessionChecked) { 2361 return; 2362 } 2363 SSOToken currToken = acLocal.getSSOToken(); 2364 com.iplanet.dpro.session.service.InternalSession oldSess 2365 = acLocal.getLoginState().getOldSession(); 2366 if (oldSess != null) { 2367 if (forceAuth) { 2368 try { 2369 SSOTokenManager.getInstance(). 2370 destroyToken(currToken); 2371 } catch (SSOException ssoExp) { 2372 authDebug.error("AuthContext.onSuccessLocal: ", 2373 ssoExp); 2374 2375 } 2376 acLocal.getLoginState().setSession(oldSess); 2377 acLocal.getLoginState().setForceAuth(false); 2378 ssoToken = acLocal.getSSOToken(); 2379 ssoTokenID = ssoToken.getTokenID().toString(); 2380 2381 } else { 2382 InjectorHolder.getInstance(SessionService.class).destroyInternalSession(oldSess.getID()); 2383 } 2384 } 2385 localSessionChecked = true; 2386 } 2387 2388 /** 2389 * Returns the application sso token. Can perform a check to ensure that 2390 * the app token is still valid (requires a session refresh call to OpenAM) 2391 * 2392 * @param refresh true if we should check with OpenAM if the app token is valid 2393 * @return a valid application's sso token. 2394 */ 2395 private SSOToken getAppSSOToken(boolean refresh) { 2396 SSOToken appToken = null; 2397 2398 try { 2399 appToken = (SSOToken) AccessController.doPrivileged( 2400 AdminTokenAction.getInstance()); 2401 } catch (AMSecurityPropertiesException aspe) { 2402 if (authDebug.messageEnabled()) { 2403 authDebug.message("AuthContext::getAppSSOToken: " + 2404 "unable to get app ssotoken " + aspe.getMessage()); 2405 } 2406 } 2407 2408 if (refresh) { 2409 // ensure the token is valid 2410 try { 2411 SSOTokenManager ssoTokenManager = SSOTokenManager.getInstance(); 2412 ssoTokenManager.refreshSession(appToken); 2413 2414 if (!ssoTokenManager.isValidToken(appToken)) { 2415 if (authDebug.messageEnabled()) { 2416 authDebug.message("AuthContext.getAppSSOToken(): " + 2417 "App SSOToken is invalid, retrying"); 2418 } 2419 2420 try { 2421 appToken = (SSOToken) AccessController.doPrivileged( 2422 AdminTokenAction.getInstance()); 2423 } catch (AMSecurityPropertiesException aspe) { 2424 if (authDebug.messageEnabled()) { 2425 authDebug.message("AuthContext::getAppSSOToken: " + 2426 "unable to get app ssotoken " + aspe.getMessage()); 2427 } 2428 } 2429 } 2430 } catch (SSOException ssoe) { 2431 if (authDebug.messageEnabled()) { 2432 authDebug.message("AuthContext.getAppSSOToken(): " + 2433 "unable to refresh app token: " + ssoe.getL10NMessage()); 2434 } 2435 2436 try { 2437 appToken = (SSOToken) AccessController.doPrivileged( 2438 AdminTokenAction.getInstance()); 2439 } catch (AMSecurityPropertiesException aspe) { 2440 if (authDebug.errorEnabled()) { 2441 authDebug.error("AuthContext::getAppSSOToken: " + 2442 "unable to get app ssotoken " + aspe.getMessage()); 2443 } 2444 } 2445 } 2446 } 2447 2448 if (authDebug.messageEnabled()) { 2449 if (appToken == null) { 2450 authDebug.message("Null App SSO Token"); 2451 } else { 2452 authDebug.message("Obtained App Token= " + appToken.getTokenID().toString()); 2453 } 2454 } 2455 2456 return appToken; 2457 } 2458 2459 public AuthContextLocal getAuthContextLocal() { 2460 return acLocal; 2461 } 2462}