Example: Customizing a server-side Java Authentication and Authorization Service authentication and login configuration

WebSphere Application Server supports plugging in a custom Java Authentication and Authorization Service (JAAS) login module before or after the WAS system login module. However, WebSphere Application Server does not support the replacement of the WebSphere Application Server system login modules, which are used to create WSCredential and WSPrincipal in the Subject. By using a custom login module, one can either make additional authentication decisions or add information to the Subject to make additional, potentially finer-grained, authorization decisions inside a Java 2 Platform, Enterprise Edition (J2EE) application.

WebSphere Application Server enables you to propagate information downstream that is added to the Subject by a custom login module. For more information, see Security attribute propagation. To determine which login configuration to use for plugging in your custom login modules, see the descriptions of the login configurations located in the System login configuration entry settings for Java Authentication and Authorization Service article.

WebSphere Application Server supports the modification of the system login configuration through the administrative console and by using the wsadmin scripting utility. To configure the system login configuration using the administrative console, click Security > Global security. Under Authentication, click JAAS Configuration > System logins.

Refer to the following code sample to configure a system login configuration using the wsadmin tool. The following sample JACL script adds a custom login module into the Lightweight Third-party Authentication (LTPA) Web system login configuration:

Attention: Lines 32, 33, and 34 in the following code sample were split onto two lines because of the width of the printed page.

1. #########################################
2. #
3. # Open security.xml
4. #
5. #########################################
6.
7.
8. set sec [$AdminConfig getid /Cell:hillside/Security:/]
9.
10.
11. #########################################
12. #
13. # Locate systemLoginConfig
14. #
15. #########################################
16.
17.
18. set slc [$AdminConfig showAttribute $sec systemLoginConfig]
19.
20. set entries [lindex [$AdminConfig showAttribute $slc entries] 0]
21.
22.
23. #########################################
24. #
25. # Append a new LoginModule to LTPA_WEB
26. #
27. #########################################
28.
29. foreach entry $entries {
30. set alias [$AdminConfig showAttribute $entry alias]
31. if {$alias == "LTPA_WEB"} {
32. set newJAASLoginModuleId [$AdminConfig create JAASLoginModule
$entry {{moduleClassName
"com.ibm.ws.security.common.auth.module.proxy.WSLoginModuleProxy"}}]
33. set newPropertyId [$AdminConfig create Property
$newJAASLoginModuleId {{name delegate}{value
"com.ABC.security.auth.CustomLoginModule"}}]
34. $AdminConfig modify $newJAASLoginModuleId
{{authenticationStrategy REQUIRED}}
35. break
36. }
37. }
38.
39.
40. #########################################
41. #
42. # save the change
43. #
44. #########################################
45.
46. $AdminConfig save
47.

Attention: The wsadmin scripting utility inserts a new object to the end of the list. To insert the custom LoginModule before the AuthenLoginModule, delete the AuthenLoginModule and then recreate it after inserting the custom LoginModule. Save the sample script into a file, sample.jacl, executing the sample script using the following command:

Wsadmin -f sample.jacl

You can use the following sample JACL script to remove the current LTPA_WEB login configuration and all the LoginModules:

48. #########################################
49. #
50. # Open security.xml
51. #
52. #########################################
53.
54.
55. set sec [$AdminConfig getid /Cell:hillside/Security:/]
56.
57.
58. #########################################
59. #
60. # Locate systemLoginConfig
61. #
62. #########################################
63.
64.
65. set slc [$AdminConfig showAttribute $sec systemLoginConfig]
66.
67. set entries [lindex [$AdminConfig showAttribute $slc entries] 0]
68.
69.
70. #########################################
71. #
72. # Remove the LTPA_WEB login configuration
73. #
74. #########################################
75.
76. foreach entry $entries {
77. set alias [$AdminConfig showAttribute $entry alias]
78. if {$alias == "LTPA_WEB"} {
79. $AdminConfig remove $entry
80. break
81. }
82. }
83.
84.
85. #########################################
86. #
87. # save the change
88. #
89. #########################################
90.
91. $AdminConfig save

Use the following sample JACL script to recover the original LTPA_WEB configuration:Attention: Lines 122, 124, and 126 in the following code sample were split onto two or more lines because of the width of the printed page. The two lines of code for line 122 are normally one continuous line. The three lines of code for line 124 are normally one continuous line. Also, the three lines of code for line 126 are normally one continuous line.

92. #########################################
93. #
94. # Open security.xml
95. #
96. #########################################
97.
98.
99. set sec [$AdminConfig getid /Cell:hillside/Security:/]
100.
101.
102. #########################################
103. #
104. # Locate systemLoginConfig
105. #
106. #########################################
107.
108.
109. set slc [$AdminConfig showAttribute $sec systemLoginConfig]
110.
111. set entries [lindex [$AdminConfig showAttribute $slc entries] 0]
112.
113.
114.
115. #########################################
116. #
117. # Recreate the LTPA_WEB login configuration
118. #
119. #########################################
120.
121.
122. set newJAASConfigurationEntryId [$AdminConfig create JAASConfigurationEntry
$slc {{alias LTPA_WEB}}]
123.
124. set newJAASLoginModuleId [$AdminConfig create JAASLoginModule
$newJAASConfigurationEntryId
{{moduleClassName
"com.ibm.ws.security.common.auth.module.proxy.WSLoginModuleProxy"}}]
125.
126. set newPropertyId [$AdminConfig create Property
$newJAASLoginModuleId {{name delegate}
{value "com.ibm.ws.security.web.AuthenLoginModule"}}]
127.
128. $AdminConfig modify $newJAASLoginModuleId {{authenticationStrategy REQUIRED}}
129.
130.
131. #########################################
132. #
133. # save the change
134. #
135. #########################################
136.
137. $AdminConfig save

The WAS VltpaLoginModule and AuthenLoginModule use the shared state to save state information so that custom LoginModules can modify the information. The ltpaLoginModule initializes the callback array in the login() method using the following code. The callback array is created by ltpaLoginModule only if an array is not defined in the shared state area. In the following code sample, the error handling code was removed to make the sample concise. If you insert a custom LoginModule before the ltpaLoginModule, custom LoginModule might follow the same style to save the callback into the shared state.Attention: In the following code sample, several lines of code have been split onto two lines because of the width of the printed page. Each of these split lines are one continuous line.

138. Callback callbacks[] = null;
139. if (!sharedState.containsKey(
com.ibm.wsspi.security.auth.callback.Constants.
CALLBACK_KEY)) {
140. callbacks = new Callback[3];
141. callbacks[0] = new NameCallback("Username: ");
142. callbacks[1] = new PasswordCallback("Password: ", false);
143. callbacks[2] = new com.ibm.websphere.security.auth.callback.
WSCredTokenCallbackImpl( "Credential Token: ");
144. try {
145. callbackHandler.handle(callbacks);
146. } catch (java.io.IOException e) {
147. . . .
148. } catch (UnsupportedCallbackException uce) {
149. . . .
150. }
151. sharedState.put(
com.ibm.wsspi.security.auth.callback.Constants.CALLBACK_KEY,
callbacks);
152. } else {
153. callbacks = (Callback [])
sharedState.get( com.ibm.wsspi.security.auth.callback.
Constants.CALLBACK_KEY);
154. }

ltpaLoginModule and AuthenLoginModule generate both a WSPrincipal and a WSCredential object to represent the authenticated user identity and security credentials. The WSPrincipal and WSCredential objects also are saved in the shared state. A JAAS login uses a two-phase commit protocol. First, the login methods in login modules, which are configured in the login configuration, are called. Then, their commit methods are called. A custom LoginModule, which is inserted after the ltpaLoginModule and the AuthenLoginModule, can modify the WSPrincipal and WSCredential objects before they are committed. The WSCredential and WSPrincipal objects must exist in the Subject after the login is completed. Without these objects in the Subject, WebSphere Application Server run-time code rejects the Subject when it is used to make any security decisions.

AuthenLoginModule uses the following code to initialize the callback array:Attention: In the following code sample, several lines of code have been split onto two lines because of the width of the printed page. Each of these split lines are one continuous line.

155. Callback callbacks[] = null;
156. if (!sharedState.containsKey(
com.ibm.wsspi.security.auth.callback.Constants.
CALLBACK_KEY)) {
157. callbacks = new Callback[6];
158. callbacks[0] = new NameCallback("Username: ");
159. callbacks[1] = new PasswordCallback("Password: ", false);
160. callbacks[2] =
new com.ibm.websphere.security.auth.callback.WSCredTokenCallbackImpl(
"Credential Token: ");
161. callbacks[3] =
new com.ibm.wsspi.security.auth.callback.WSServletRequestCallback(
"HttpServletRequest: ");
162. callbacks[4] =
new com.ibm.wsspi.security.auth.callback.WSServletResponseCallback(
"HttpServletResponse: ");
163. callbacks[5] =
new com.ibm.wsspi.security.auth.callback.WSAppContextCallback(
"ApplicationContextCallback: ");
164. try {
165. callbackHandler.handle(callbacks);
166. } catch (java.io.IOException e) {
167. . . .
168. } catch (UnsupportedCallbackException uce {
169. . . .
170. }
171. sharedState.put( com.ibm.wsspi.security.auth.callback.
Constants.CALLBACK_KEY, callbacks);
172. } else {
173. callbacks = (Callback []) sharedState.get(
com.ibm.wsspi.security.auth.callback.
Constants.CALLBACK_KEY);
174. }

Three more objects, which contain callback information for the login, are passed from the Web container to the AuthenLoginModule: a java.util.Map, a HttpServletRequest, and a HttpServletResponse object. These objects represent the Web application context. The WebSphere Application Server V5.1 application context, java.util.Map object, contains the application name and the error page URL. We can obtain the application context, java.util.Map object, by calling the getContext() method on the WSAppContextCallback object. The java.util.Map object is created with the following deployment descriptor information.Attention: In the following code sample, several lines of code have been split onto two lines because of the width of the printed page. Each of these split lines are one continuous line.

175. HashMap appContext = new HashMap(2);
176. appContext.put(
com.ibm.wsspi.security.auth.callback.Constants.WEB_APP_NAME,
web_appname);
177. appContext.put(
com.ibm.wsspi.security.auth.callback.Constants.REDIRECT_URL,
errorPage);

The application name and the HttpServletRequest object might be read by the custom LoginModule to perform mapping functions. The error page of the form-based login might be modified by a custom LoginModule. In addition to the JAAS framework, WAS supports the Trust Association Interface (TAI).

Other credential types and information can be added to the caller Subject during the authentication process using a custom LoginModule. The third-party credentials in the caller Subject are managed by WAS as part of the security context. The caller Subject is bound to the thread of execution during the request processing. When a Web or EJB module is configured to use the caller identity, the user identity is propagated to the downstream service in an EJB request. WSCredential and any third-party credentials in the caller Subject are not propagated downstream. Instead, some of the information can be regenerated at the target server based on the propagated identity. Add third-party credentials to the caller Subject at the authentication stage. The caller Subject, which is returned from the WSSubject.getCallerSubject() method, is read-only and thus cannot be modified. For more information on the WSSubject, see Example: Getting the Caller Subject from the Thread.


 

See Also


Security attribute propagation

 

See Also


Example: Getting the Caller Subject from the Thread
System login configuration entry settings for Java Authentication and Authorization Service