/
AuthConfigFactory.java
440 lines (413 loc) · 23.6 KB
/
AuthConfigFactory.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
/*
* Copyright (c) 2020, 2023 Contributors to Eclipse Foundation. All rights reserved.
* Copyright (c) 1997, 2020 Oracle and/or its affiliates and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package jakarta.security.auth.message.config;
import jakarta.security.auth.message.module.ServerAuthModule;
import java.security.Security;
import java.util.Map;
import java.util.Properties;
/**
* This class is used to obtain <code>AuthConfigProvider</code> objects that can be used to obtain authentication
* context configuration objects, that is, <code>ClientAuthConfig</code> and <code>ServerAuthConfig</code> objects.
* <p>
* Authentication context configuration objects are used to obtain authentication context objects. Authentication
* context objects, that is, <code>ClientAuthContext</code> and <code>ServerAuthContex</code> objects, encapsulate
* authentication modules. Authentication modules are pluggable components that perform security-related processing of
* request and response messages.
*
* <p>
* Callers do not operate on modules directly. Instead they rely on an authentication context to manage the invocation
* of modules. A caller obtains an authentication context by calling the <code>getAuthContext</code> method on a
* <code>ClientAuthConfig</code> or <code>ServerAuthConfig</code> obtained from an AuthConfigProvider.
*
* <p>
* The following represents a typical sequence of calls for obtaining a client authentication context, and then using it
* to secure a request.
* <ol>
* <li>AuthConfigFactory factory = AuthConfigFactory.getFactory();
* <li>AuthConfigProvider provider = factory.getConfigProvider(layer,appID,listener);
* <li>ClientAuthConfig config = provider.getClientAuthConfig(layer,appID,cbh)
* <li>String authContextID = config.getAuthContextID(messageInfo);
* <li>ClientAuthContext context = config.getAuthContext(authContextID,subject,properties);
* <li>context.secureRequest(messageInfo,subject);
* </ol>
*
* <p>
* A system-wide AuthConfigFactory implementation can be set by invoking <code>setFactory</code>, and retrieved using
* <code>getFactory</code>.
*
* <p>
* Every implementation of this abstract class must offer a public, zero argument constructor. This constructor must
* support the construction and registration (including self-registration) of AuthConfigProviders from a persistent
* declarative representation. For example, a factory implementation class could interpret the contents of a file
* containing a sequence of configuration entries, with one entry per AuthConfigProvider, and with each entry
* representing:
* <ul>
* <li>The fully qualified name of the provider implementation class (or null)
* <li>The list of provider initialization properties (which could be empty)
* </ul>
*
* Any provider initialization properties must be specified in a form that can be passed to the provider constructor
* within a Map of key, value pairs, and where all keys and values within the Map are of type String.
*
* <p>
* The entry syntax must also provide for the optional inclusion of information sufficient to define a
* RegistrationContext. This information would only be present when the factory will register the provider. For example,
* each entry could provide for the inclusion of one or more RegistrationContext objects of the following form:
* <ul>
* <li>The message layer name (or null)
* <li>The application context identifier (or null)
* <li>The registration description (or null)
* </ul>
*
* When a RegistrationContext is not included, the factory must make it convenient for the provider to self-register
* with the factory during the provider construction (see
* <code>registerConfigProvider(AuthConfigProvider provider, ...)</code>).
*
* <p>
* An AuthConfigFactory implementation is free to choose is own persistent declarative syntax as long as it conforms to
* the requirements defined by this class.
*
* @see ClientAuthContext
* @see ServerAuthContext
* @see ClientAuthConfig
* @see ServerAuthConfig
* @see Properties
*/
public abstract class AuthConfigFactory {
private static AuthConfigFactory factory;
/**
* The name of the Security property used to define the default AuthConfigFactory implementation class.
*/
public static final String DEFAULT_FACTORY_SECURITY_PROPERTY = "authconfigprovider.factory";
/**
* Get the system-wide AuthConfigFactory implementation.
*
* <p>
* If a non-null system-wide factory instance is defined at the time of the call, for example, with
* <code>setFactory</code>, it will be returned. Otherwise, an attempt will be made to construct an instance of the
* default AuthConfigFactory implementation class. The fully qualified class name of the default factory implementation
* class is obtained from the value of the {@link #DEFAULT_FACTORY_SECURITY_PROPERTY} security property. When an
* instance of the default factory implementation class is successfully constructed by this method, this method will set
* it as the system-wide factory instance.
* @return The non-null system-wide AuthConfigFactory instance set at the time of the call, or if that value was null,
* the value of the system-wide factory instance established by this method. This method returns null when the
* system-wide factory was not defined when this method was called and no default factory name was defined via the
* security property.
*
* @exception SecurityException Thrown if an exception was thrown during the class loading, or construction of the default
* AuthConfigFactory implementation class; in which case the SecurityException will contain the root Exception as its
* cause.
*/
public static synchronized AuthConfigFactory getFactory() {
if (AuthConfigFactory.factory == null) {
final String className = Security.getProperty(DEFAULT_FACTORY_SECURITY_PROPERTY);
if (className != null) {
try {
AuthConfigFactory.factory = (AuthConfigFactory)
Class.forName(
className,
true,
Thread.currentThread().getContextClassLoader())
.getDeclaredConstructor()
.newInstance();
} catch (ReflectiveOperationException pae) {
throw new SecurityException(pae);
}
}
}
return AuthConfigFactory.factory;
}
/**
* Set the system-wide AuthConfigFactory implementation.
*
* <p>
* If an implementation was set previously, it will be replaced.
* <p>
* Listeners are not notified of a change to the registered factory.
*
* @param factory The AuthConfigFactory instance, which may be null.
*/
public static synchronized void setFactory(AuthConfigFactory factory) {
AuthConfigFactory.factory = factory;
}
/**
* Get a registered AuthConfigProvider from the factory.
*
* Get the provider of ServerAuthConfig and ClientAuthConfig objects registered for the identified message layer and
* application context.
*
* <p>
* All factories shall employ the following precedence rules to select the registered AuthConfigProvider that matches
* the layer and appContext arguments:
* <ul>
* <li>The provider specifically registered for the values passed as the layer and appContext arguments shall be
* selected.
* <li>If no provider is selected according to the preceding rule, the provider specifically registered for the value
* passed as the appContext argument and for all (that is, null) layers shall be selected.
* <li>If no provider is selected according to the preceding rules, the provider specifically registered for the value
* passed as the layer argument and for all (that is, null) appContexts shall be selected.
* <li>If no provider is selected according to the preceding rules, the provider registered for all (that is, null)
* layers and for all (that is, null) appContexts shall be selected.
* <li>If no provider is selected according to the preceding rules, the factory shall terminate its search for a
* registered provider.
* </ul>
* <p>
* The above precedence rules apply equivalently to registrations created with a null or non-null <code>className</code>
* argument.
*
* @param layer A String identifying the message layer for which the registered AuthConfigProvider is to be returned.
* The value of this argument may be null.
*
* @param appContext A String that identifies the application messaging context for which the registered
* AuthConfigProvider is to be returned. The value of this argument may be null.
*
* @param listener The RegistrationListener whose <code>notify</code> method is to be invoked if the corresponding
* registration is unregistered or replaced. The value of this argument may be null.
*
* @return The implementation of the AuthConfigProvider interface registered at the factory for the layer and
* appContext, or null if no AuthConfigProvider is selected. An argument listener is attached even if the return value
* is null.
*/
public abstract AuthConfigProvider getConfigProvider(String layer, String appContext, RegistrationListener listener);
/**
* Registers within the factory and records within the factory's persistent declarative representation of provider
* registrations a provider of ServerAuthConfig and/or ClientAuthConfig objects for a message layer and application
* context identifier.
*
* This method typically constructs an instance of the provider before registering it with the factory. Factories may
* extend or modify the persisted registrations of existing provider instances, if those instances were registered with
* ClassName and properties arguments equivalent to those passed in the current call.
* <P>
* This method employs the two argument constructor required to be supported by every implementation of the
* AuthConfigProvider interface, and this method must pass a null value for the factory argument of the constructor.
* <code>AuthConfigProviderImpl AuthConfigProviderImpl(Map properties,
* AuthConfigFactory factory)</code>.
*
* <P>
* At most one registration may exist within the factory for a given combination of message layer and appContext. Any
* pre-existing registration with identical values for layer and appContext is replaced by a subsequent registration.
* When replacement occurs, the registration identifier, layer, and appContext identifier remain unchanged, and the
* AuthConfigProvider (with initialization properties) and description are replaced.
*
* <p>
* Within the lifetime of its Java process, a factory must assign unique registration identifiers to registrations, and
* must never assign a previously used registration identifier to a registration whose message layer and or appContext
* identifier differ from the previous use.
*
* <p>
* Programmatic registrations performed by using this method must update (according to the replacement rules described
* above) the persistent declarative representation of provider registrations employed by the factory constructor.
*
* @param className The fully qualified name of an AuthConfigProvider implementation class (or null). Calling this
* method with a null value for this parameter shall cause <code>getConfigProvider</code> to return null when it is
* called with layer and appContext values for which the resulting registration is the best match.
*
* @param properties A Map object containing the initialization properties to be passed to the properties argument of
* the provider constructor. This argument may be null.
*
* @param layer A String identifying the message layer for which the provider will be registered at the factory. A null
* value may be passed as an argument for this parameter, in which case the provider is registered at all layers.
*
* @param appContext A String value that may be used by a runtime to request a configuration object from this provider.
* A null value may be passed as an argument for this parameter, in which case the provider is registered for all
* configuration ids (at the indicated layers).
*
* @param description A text String describing the provider. This value may be null.
*
* @return A String identifier assigned by the factory to the provider registration, and that may be used to remove the
* registration from the factory.
*
* @exception SecurityException If the the provider construction (given a non-null <code>className</code>) or registration
* fails.
*
*/
public abstract String registerConfigProvider(String className, Map<String, String> properties, String layer, String appContext, String description);
/**
* Registers within the (in-memory) factory, a provider of ServerAuthConfig and/or ClientAuthConfig objects for a
* message layer and application context identifier. This method does NOT effect the factory's persistent declarative
* representation of provider registrations, and is intended to be used by providers to perform self-Registration.
*
* <P>
* At most one registration may exist within the factory for a given combination of message layer and appContext. Any
* pre-existing registration with identical values for layer and appContext is replaced by a subsequent registration.
* When replacement occurs, the registration identifier, layer, and appContext identifier remain unchanged, and the
* AuthConfigProvider (with initialization properties) and description are replaced.
*
* <p>
* Within the lifetime of its Java process, a factory must assign unique registration identifiers to registrations, and
* must never assign a previously used registration identifier to a registration whose message layer and or appContext
* identifier differ from the previous use.
*
* @param provider The AuthConfigProvider to be registered at the factory (or null). Calling this method with a null
* value for this parameter shall cause <code>getConfigProvider</code> to return null when it is called with layer and
* appContext values for which the resulting registration is the best match.
*
* @param layer A String identifying the message layer for which the provider will be registered at the factory. A null
* value may be passed as an argument for this parameter, in which case the provider is registered at all layers.
*
* @param appContext A String value that may be used by a runtime to request a configuration object from this provider.
* A null value may be passed as an argument for this parameter, in which case the provider is registered for all
* configuration ids (at the indicated layers).
*
* @param description A text String describing the provider. This value may be null.
*
* @return A String identifier assigned by the factory to the provider registration, and that may be used to remove the
* registration from the factory.
*
* @exception SecurityException If the provider registration fails.
*/
public abstract String registerConfigProvider(AuthConfigProvider provider, String layer, String appContext, String description);
/**
* Registers within the (in-memory) factory, an instance of a <code>ServerAuthModule</code> for a
* message layer and application context identifier as identified by a profile specific context object.
*
* <p>
* This will override any other modules that have already been registered, either via proprietary
* means or using the standard API. The <code>ServerAuthModule</code> is removed, via a call to
* <code>removeServerAuthModule</code> when the context associated with the profile specific context object ends.
*
* <p>
* Note that this method is a convenience method that can be used instead of <code>registerConfigProvider</code>,
* but should ultimately have the same effect. That is, the <code>layer</code> and <code>appContext</code> parameters
* are generated from the context object, and the <code>ServerAuthModule</code> is wrapped by an implementation
* specific <code>AuthConfigProvider</code>, which are then used to call <code>registerConfigProvider</code> or an
* internal method with the same effect. The returned registration ID is then associated with the profile specific
* context object, and also returned from this method.
*
* <p>
* A "profile specific context object" is for example the <code>ServletContext</code> in the
* Servlet Container Profile. The context associated with this <code>ServletContext</code> ends
* when for example the application corresponding to it is undeployed. Association of the
* registration ID with the <code>ServletContext</code> simply means calling the <code>setAttribute</code>
* method on the <code>ServletContext</code>, with the registration ID as value. (The name attribute has not been
* standardised in this version of the specification)
*
* @param serverAuthModule the <code>ServerAuthModule</code> instance to be registered
* @param context the profile specific context of the application for which the module is registered
* @return A String identifier assigned by the factory to the provider registration, and that may be used to remove the
* registration from the factory.
*/
public abstract String registerServerAuthModule(ServerAuthModule serverAuthModule, Object context);
/**
* Remove the <code>ServerAuthModule</code> (and potentially encompassing wrappers/factories) that was previously registered via a call
* to <code>registerServerAuthModule</code>.
*
* <p>
* Note that this method is a convenience method that can be used instead of <code>removeRegistration</code>, but should ultimately
* have the same effect. That is calling <code>removeRegistration</code> with the return value from <code>registerServerAuthModule</code>
* must have the same effect in that the <code>ServerAuthModule</code> is removed.
*
* @param context the profile specific context of the application for which the module is removed.
*/
public abstract void removeServerAuthModule(Object context);
/**
* Remove the identified provider registration from the factory (and from the persistent declarative representation of
* provider registrations, if appropriate) and invoke any listeners associated with the removed registration.
*
* @param registrationID A String that identifies a provider registration at the factory
*
* @return True if there was a registration with the specified identifier and it was removed. Return false if the
* registrationID was invalid.
*
*/
public abstract boolean removeRegistration(String registrationID);
/**
* Disassociate the listener from all the provider registrations whose layer and appContext values are matched by the
* corresponding arguments to this method.
* <p>
* Factories should periodically notify Listeners to effectively detach listeners that are no longer in use.
*
* @param listener The RegistrationListener to be detached.
*
* @param layer A String identifying the message layer or null.
*
* @param appContext A String value identifying the application context or null.
*
* @return An array of String values where each value identifies a provider registration from which the listener was
* removed. This method never returns null; it returns an empty array if the listener was not removed from any
* registrations.
*
*/
public abstract String[] detachListener(RegistrationListener listener, String layer, String appContext);
/**
* Get the registration identifiers for all registrations of the provider instance at the factory.
*
* @param provider The AuthConfigurationProvider whose registration identifiers are to be returned. This argument may be
* null, in which case it indicates that the IDs of all active registrations within the factory are to be returned.
*
* @return An array of String values where each value identifies a provider registration at the factory. This method
* never returns null; it returns an empty array when there are no registrations at the factory for the identified
* provider.
*/
public abstract String[] getRegistrationIDs(AuthConfigProvider provider);
/**
* Get the registration context for the identified registration.
*
* @param registrationID A String that identifies a provider registration at the factory
*
* @return A RegistrationContext or null. When a Non-null value is returned, it is a copy of the registration context
* corresponding to the registration. Null is returned when the registration identifier does not correspond to an active
* registration
*/
public abstract RegistrationContext getRegistrationContext(String registrationID);
/**
* Cause the factory to reprocess its persistent declarative representation of provider registrations.
*
* <p>
* A factory should only replace an existing registration when a change of provider implementation class or
* initialization properties has occurred.
*
* @exception SecurityException If an error occurred during the reinitialization.
*/
public abstract void refresh();
/**
* Represents the layer identifier, application context identifier, and description components of an AuthConfigProvider
* registration at the factory.
*/
public interface RegistrationContext {
/**
* Get the layer name from the registration context
*
* @return A String identifying the message layer for which the AuthConfigProvider was registered. The returned value
* may be null.
*/
String getMessageLayer();
/**
* Get the application context identifier from the registration context
*
* @return A String identifying the application context for which the AuthConfigProvider was registered. The returned
* value may be null.
*/
String getAppContext();
/**
* Get the description from the registration context
*
* @return The description String from the registration, or null if no description string was included in the
* registration.
*/
String getDescription();
/**
* Get the persisted status from the registration context.
*
* @return A boolean indicating whether the registration is the result of a className based registration, or an
* instance-based (for example, self-) registration. Only registrations performed using the five argument
* <code>registerConfigProvider</code> method are persistent.
*/
boolean isPersistent();
}
}