Programmatic login is a type of form login that supports application presentation site-specific login forms for the purpose of authentication.
When enterprise bean client applications require the user to provide identifying information, the writer of the application must collect that information and authenticate the user. The work of the programmer can be broadly classified in terms of where the actual user authentication is performed:
Users of Web applications can receive prompts for authentication data in many ways. The <login-config> element in the Web application deployment descriptor file defines the mechanism that is used to collect this information. Programmers who want to customize login procedures, rather than relying on general purpose devices like a 401 dialog window in a browser, can use a form-based login to provide an application-specific HTML form for collecting login information.
No authentication occurs unless administrative security is enabled. If you want to use form-based login for Web applications, you must specify FORM in the auth-method tag of the <login-config> element in the deployment descriptor of each Web application.
Applications can present site-specific login forms by using the WebSphere® Application Server form-login type. The Java™ Platform, Enterprise Edition (Java EE) specification defines form login as one of the authentication methods for Web applications. WebSphere Application Server provides a form-logout mechanism.
Java Authentication and Authorization Service (JAAS) is a new feature in WebSphere Application Server. It is also mandated by the Java EE 1.4 Specification. JAAS is a collection of strategic authentication application programming interfaces (API) that replace the Common Object Request Broker Architecture (CORBA) programmatic login APIs. WebSphere Application Server provides some extensions to JAAS:
... import java.util.Hashtable; import javax.naming.Context; import javax.naming.InitialContext; ... // Perform an InitialContext and default lookup prior to logging // in to initialize ORB security and for the bootstrap host/port // to be determined for SecurityServer lookup. If you do not want // to validate the userid/password during the JAAS login, disable // the com.ibm.CORBA.validateBasicAuth property in the // sas.client.props file. Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"); env.put(Context.PROVIDER_URL, "corbaloc:iiop:myhost.mycompany.com:2809"); Context initialContext = new InitialContext(env); Object obj = initialContext.lookup("");For more information, see xsec_jaas.html.
If you get a LoginException exception after issuing the LoginContext.login API, you can find the root cause exception from the configured user registry. In the login modules, the registry exceptions are wrapped by a com.ibm.websphere.security.auth.WSLoginFailedException class. This exception has a getCause method with which you can pull out the exception that was wrapped after issuing the previous command.
You are not always guaranteed to get a WSLoginFailedException exception, but most of the exceptions that are generated from the user registry display here. The following example illustrates a LoginContext.login API with the associated catch block. Cast the WSLoginFailedException exception to com.ibm.websphere.security.auth.WSLoginFailedException class if you want to issue the getCause API.
try { lc.login(); } catch (LoginException le) { // drill down through the exceptions as they might cascade through the runtime Throwable root_exception = determineCause(le); // now you can use "root_exception" to compare to a particular exception type // for example, if you have implemented a CustomUserRegistry type, you would // know what to look for here. } /* Method used to drill down into the WSLoginFailedException to find the "root cause" exception */ public Throwable determineCause(Throwable e) { Throwable root_exception = e, temp_exception = null; // keep looping until there are no more embedded WSLoginFailedException or // WSSecurityException exceptions while (true) { if (e instanceof com.ibm.websphere.security.auth.WSLoginFailedException) { temp_exception = ((com.ibm.websphere.security.auth.WSLoginFailedException) e).getCause(); } else if (e instanceof com.ibm.websphere.security.WSSecurityException) { temp_exception = ((com.ibm.websphere.security.WSSecurityException) e).getCause(); } else if (e instanceof javax.naming.NamingException) // check for Ldap embedded exception { temp_exception = ((javax.naming.NamingException)e).getRootCause(); } else if (e instanceof your_custom_exception_here) { // your custom processing here, if necessary } else { // this exception is not one of the types we are looking for, // lets return now, this is the root from the WebSphere // Application Server perspective return root_exception; } if (temp_exception != null) { // we have an exception; go back and see if this has another // one embedded within it. root_exception = temp_exception; e = temp_exception; continue; } else { // we finally have the root exception from this call path, this // has to occur at some point return root_exception; } } }
Throwable t = com.ibm.websphere.security.auth.WSSubject.getRootLoginException(); if (t != null) t = determineCause(t);
When you have the exception, you can run it through the previous determineCause example to get the native registry root cause.
Currently, the root cause does not get propagated to a pure client for security reasons. However, you might want to propagate the root cause to a pure client in a trusted environment. If you want to enable root cause login exception propagation to a pure client, click Security > Global security > Custom Properties on the WebSphere Application Server Administrative Console and set the following property:
com.ibm.websphere.security.registry.propagateExceptionsToClient=true
javax.security.auth.login.LoginContext lc = null; try { lc = new javax.security.auth.login.LoginContext("WSLogin", new com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl("user", "securityrealm", "securedpassword")); // create a LoginContext and specify a CallbackHandler implementation // CallbackHandler implementation determine how authentication data is collected // in this case, the authentication data is "push" to the authentication mechanism // implemented by the LoginModule. } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " + e.getMessage()); e.printStackTrace(); // maybe javax.security.auth.AuthPermission "createLoginContext" is not granted // to the application, or the JAAS login configuration is not defined. } if (lc != null) try { lc.login(); // perform login javax.security.auth.Subject s = lc.getSubject(); // get the authenticated subject // Invoke a Java EE resource using the authenticated subject com.ibm.websphere.security.auth.WSSubject.doAs(s, new java.security.PrivilegedAction() { public Object run() { try { bankAccount.deposit(100.00); // where bankAccount is a protected EJB } catch (Exception e) { System.out.println("ERROR: error while accessing EJB resource, exception: " + e.getMessage()); e.printStackTrace(); } return null; } } ); } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: login failed with exception: " + e.getMessage()); e.printStackTrace(); // login failed, might want to provide relogin logic }
You can use the com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl callback handler with a pure Java client, a client application container, enterprise bean, JavaServer Pages (JSP) files, servlet, or other Java 2 Platform, Enterprise Edition (Java EE) resources. See xsec_jaas.html for more information about Object Request Broker (ORB) security initialization requirements in a pure Java client.
javax.security.auth.login.LoginContext lc = null; try { lc = new javax.security.auth.login.LoginContext("WSLogin", new com.ibm.websphere.security.auth.callback.WSGUICallbackHandlerImpl()); // create a LoginContext and specify a CallbackHandler implementation // CallbackHandler implementation determine how authentication data is collected // in this case, the authentication date is collected by GUI login prompt // and pass to the authentication mechanism implemented by the LoginModule. } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " + e.getMessage()); e.printStackTrace(); // maybe javax.security.auth.AuthPermission "createLoginContext" is not granted // to the application, or the JAAS login configuration is not defined. } if (lc != null) try { lc.login(); // perform login javax.security.auth.Subject s = lc.getSubject(); // get the authenticated subject // Invoke a Java EE resources using the authenticated subject com.ibm.websphere.security.auth.WSSubject.doAs(s, new java.security.PrivilegedAction() { public Object run() { try { bankAccount.deposit(100.00); // where bankAccount is a protected enterprise bean } catch (Exception e) { System.out.println("ERROR: error while accessing EJB resource, exception: " + e.getMessage()); e.printStackTrace(); } return null; } } ); } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: login failed with exception: " + e.getMessage()); e.printStackTrace(); // login failed, might want to provide relogin logic }
WebSphere Application Server also provides a Kerberos credential cache implementation of the javax.security.auth.callback.CallbackHandler interface. The callback handler, com.ibm.websphere.security.auth.callback.WSCcacheCallBackHandlerImpl. Using this interface, an application can push authentication data to the WebSphere LoginModule instance to perform authentication.
This capability is only for the client side application code to authenticate to WebSphere Application Server with the Kerberos credential cache.
useDefaultKeytab=false
useDefaultCcache=false
tryFirstPass=false
useFirstPass=false
forwardable=false
renewable=false
renewable=false
noaddress=false
javax.security.auth.login.LoginContext lc = null; String krb5Ccache = /etc/krb5/krb5cc_utle; try { lc = new javax.security.auth.login.LoginContext("WSKRB5Login", new com.ibm.websphere.security.auth.callback.WSCcacheCallBackHandlerImpl(user, krb5Realm, krb5Ccache, false)); // create a LoginContext and specify a CallbackHandler implementation // CallbackHandler implementation determines how authentication data is collected // in this case, the authentication date is collected by stdin prompt // and passed to the authentication mechanism implemented by the LoginModule. } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " + e.getMessage()); e.printStackTrace(); // maybe javax.security.auth.AuthPermission "createLoginContext" is not granted // to the application, or the JAAS login configuration is not defined. } if (lc != null) try { lc.login(); // perform login javax.security.auth.Subject s = lc.getSubject(); // get the authenticated subject // Invoke a Java EE resource using the authenticated subject com.ibm.websphere.security.auth.WSSubject.doAs(s, new java.security.PrivilegedAction() { public Object run() { try { bankAccount.deposit(100.00); // where bankAccount is a protected enterprise bean } catch (Exception e) { System.out.println("ERROR: error while accessing EJB resource, exception: " + e.getMessage()); e.printStackTrace(); } return null; } } ); } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: login failed with exception: " + e.getMessage()); e.printStackTrace(); // login failed, might want to provide relogin logic } Application Server with the default Kerberos credential cache. javax.security.auth.login.LoginContext lc = null; try { lc = new javax.security.auth.login.LoginContext("WSKRB5Login", new com.ibm.websphere.security.auth.callback.WSCcacheCallBackHandlerImpl(user, krb5Realm, null, true)); // create a LoginContext and specify a CallbackHandler implementation // CallbackHandler implementation determines how authentication data is collected // in this case, the authentication date is collected by stdin prompt // and passed to the authentication mechanism implemented by the LoginModule. } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " + e.getMessage()); e.printStackTrace(); // maybe javax.security.auth.AuthPermission "createLoginContext" is not granted // to the application, or the JAAS login configuration is not defined. } if (lc != null) try { lc.login(); // perform login javax.security.auth.Subject s = lc.getSubject(); // get the authenticated subject // Invoke a Java EE resource using the authenticated subject com.ibm.websphere.security.auth.WSSubject.doAs(s, new java.security.PrivilegedAction() { public Object run() { try { bankAccount.deposit(100.00); // where bankAccount is a protected enterprise bean } catch (Exception e) { System.out.println("ERROR: error while accessing EJB resource, exception: " + e.getMessage()); e.printStackTrace(); } return null; } } ); } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: login failed with exception: " + e.getMessage()); e.printStackTrace(); // login failed, might want to provide relogin logic } Application Server with the Microsoft native Kerberos credential cache. The client must login to the Microsoft Domain Controller. javax.security.auth.login.LoginContext lc = null; try { lc = new javax.security.auth.login.LoginContext("WSKRB5Login", new com.ibm.websphere.security.auth.callback.WSCcacheCallBackHandlerImpl(null, null, null, true)); // create a LoginContext and specify a CallbackHandler implementation // CallbackHandler implementation determines how authentication data is collected // in this case, the authentication date is collected by stdin prompt // and passed to the authentication mechanism implemented by the LoginModule. } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " + e.getMessage()); e.printStackTrace(); // maybe javax.security.auth.AuthPermission "createLoginContext" is not granted // to the application, or the JAAS login configuration is not defined. } if (lc != null) try { lc.login(); // perform login javax.security.auth.Subject s = lc.getSubject(); // get the authenticated subject // Invoke a Java EE resource using the authenticated subject com.ibm.websphere.security.auth.WSSubject.doAs(s, new java.security.PrivilegedAction() { public Object run() { try { bankAccount.deposit(100.00); // where bankAccount is a protected enterprise bean } catch (Exception e) { System.out.println("ERROR: error while accessing EJB resource, exception: " + e.getMessage()); e.printStackTrace(); } return null; } } ); } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: login failed with exception: " + e.getMessage()); e.printStackTrace(); // login failed, might want to provide relogin logic }
The WSKRB5Login JAAS login configuration: is a generic JAAS login configuration that a Java client, client container application, servlet, JSP file, or enterprise bean can use to perform authentication that is based on a Kerberos principal name password or a Kerberos credential cache to the WebSphere Application Server security runtime. However, this configuration does not support the CallbackHandler handler that is specified in the client container deployment descriptor.
Place either the krb5.ini or krb5.conf files you have created in a default location. If either file is not located in the default location you must set the java.security.krb5.conf JVM system property with the correct path and Kerberos configuration file name.
On a Windows® platform, the default location is c:\winnt\krb5.ini.
On a Linux® platform, the default location is /etc/krb5.conf.
On other Unix platforms, the default location is /etc/krb5/krb5.conf.
On a z/OS platform, the default location is /etc/krb5/krb5.conf.
Kerberos configuration settings, the Kerberos key distribution center (KDC) name, and realm settings are provided in the Kerberos configuration file or through java.security.krb5.kdc and java.security.krb5.realm system property files.
javax.security.auth.login.LoginContext lc = null; try { lc = new javax.security.auth.login.LoginContext("WSLogin", new com.ibm.websphere.security.auth.callback.WSStdinCallbackHandlerImpl()); // create a LoginContext and specify a CallbackHandler implementation // CallbackHandler implementation determines how authentication data is collected // in this case, the authentication date is collected by stdin prompt // and passed to the authentication mechanism implemented by the LoginModule. } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " + e.getMessage()); e.printStackTrace(); // maybe javax.security.auth.AuthPermission "createLoginContext" is not granted // to the application, or the JAAS login configuration is not defined. } if (lc != null) try { lc.login(); // perform login javax.security.auth.Subject s = lc.getSubject(); // get the authenticated subject // Invoke a Java EE resource using the authenticated subject com.ibm.websphere.security.auth.WSSubject.doAs(s, new java.security.PrivilegedAction() { public Object run() { try { bankAccount.deposit(100.00); // where bankAccount is a protected enterprise bean } catch (Exception e) { System.out.println("ERROR: error while accessing EJB resource, exception: " + e.getMessage()); e.printStackTrace(); } return null; } } ); } catch (javax.security.auth.login.LoginException e) { System.err.println("ERROR: login failed with exception: " + e.getMessage()); e.printStackTrace(); // login failed, might want to provide relogin logic }