WebSphere Application Server supports plugging in a custom Java
Authentication and Authorization Service (JAAS) login module before or after
the WebSphere Application Server 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 the WSCredential credential
and WSPrincipal principal in the Subject. By using a custom login module,
you 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.
About this task
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
that are located in the System login configuration entry settings for Java Authentication and Authorization Service.
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.
- Configure a system login configuration.
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 are split
into two lines.
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
login module before the AuthenLoginModule login module, delete the AuthenLoginModule
login module and recreate it after inserting the custom login module. Save
the sample script into a
sample.jacl file, and run the sample script
using the following command:
wsadmin -f sample.jacl
- Remove the current LTPA_WEB login configuration and
all of the login modules.
You can use the following sample
Jacl script to remove the current LTPA_WEB login configuration and all the
login modules:
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
- Recover the original LTPA_WEB configuration.
You
can use the following sample Jacl script to recover the original LTPA_WEB
configuration:
Attention: Lines 122, 124, and 126 in the following
code sample are split into two or more lines for illustrative purposes only.
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
- Have the ltpaLoginModule initialize the callback array
in the login method.
The WebSphere Application Server Version
ltpaLoginModule and AuthenLoginModule login modules use the shared state to
save state information so that custom login modules can modify the information.
The ltpaLoginModule login module initializes the callback array in the login
method using the following code. The callback array is created by the ltpaLoginModule
login module only if an array is not defined in the shared state area. In
the following code sample, the error handling code is removed to make the
sample concise. If you insert a custom login module before the ltpaLoginModule
login module, the custom login module might follow the same style to save
the callback into the shared state.
Attention: In the following
code sample, several lines of code are split into two lines for illustrative
purposes only.
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. }
- Have the AuthenLoginModule initialize the callback array.
The ltpaLoginModule and AuthenLoginModule login modules generate
both a WSPrincipal object 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 login module,
which is inserted after the ltpaLoginModule and the AuthenLoginModule login
modules, can modify the WSPrincipal and WSCredential objects before these
objects 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 to
make security decisions.
AuthenLoginModule uses the
following code to initialize the callback array:
Attention: In
the following code sample, several lines of code are split into two lines
for illustrative purposes only.
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. }
- Obtain the application context.
Three more objects,
which contain callback information for the login, are passed from the Web
container to the AuthenLoginModule login module: a java.util.Map, an HttpServletRequest,
and an HttpServletResponse object. These objects represent the Web application
context. The WebSphere Application Server Version 5.1 application context,
java.util.Map object, contains the application name and the error page web
address. You 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 are split
into two lines for illustrative purposes only.
175. HashMap appContext = new HashMap(2);
176. appContext.put(
com.ibm.wsspi.security.auth.callback.Constants.WEB_APP_NAME,
web_application_name);
177. appContext.put(
com.ibm.wsspi.security.auth.callback.Constants.REDIRECT_URL,
errorPage);
What to do next
The application name and the HttpServletRequest object might be
read by the custom login module to perform mapping functions. The error page
of the form-based login might be modified by a custom login module. In addition
to the JAAS framework, WebSphere Application Server 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 login
module. The third-party credentials in the caller Subject are managed by WebSphere
Application Server as part of the security context. The caller Subject is
bound to the running thread during the request processing. When a Web or an
Enterprise JavaBeans (EJB) module is configured to use the caller
identity, the user identity is propagated to the downstream service in an
EJB request. The WSCredential credential 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 cannot be modified. For more information on the WSSubject
subject, see the example of getting the caller subject from the thread.