Oracle® Containers for J2EE Security Guide 10g (10.1.3.1.0) Part Number B28957-01 |
|
|
View PDF |
In addition to support for specific security providers documented earlier in this manual, OC4J includes a framework to more generally support heterogeneous third-party identity management systems for use by Web-based applications.
This chapter documents this identity management framework, covering the following topics:
This section introduces the OC4J identity management framework, for use by Web-based applications, with the following discussion:
Overview of Identity Management Framework Programmatic Implementation
Use of the Identity Management Framework by OC4J Java Single Sign-On
Notes:
|
As discussed earlier in this document, Oracle Application Server provides security infrastructure such as Oracle Identity Management and Oracle Access Manager, which both include identity repositories. There is also support, as noted previously, for certain external LDAP providers (Active Directory and Sun Java System Directory Server).
However, in earlier releases there was no general framework to support other third-party identity management and security systems. The OC4J 10.1.3.1 implementation adds such a framework, allowing integration of heterogeneous third-party systems into OC4J, and hence allowing any J2EE application to interoperate with these third-party systems.
This section introduces the components of the identity management framework, and summarizes how they work together. (Integration of third-party identity management systems into OC4J is based on standard JAAS login modules.)
In the general model of the identity management framework, the components work together as follows (as shown in Figure 13-1 below):
A token collector takes appropriate action to collect user credentials from the HTTP request. The token collector interface enables you to plug in a mechanism to collect the credentials. For form-based authentication, for example, a token collector would redirect to the login page for input of the user name and password. A token collector can be used to collect various types of credentials—including user name and password, or HTTP cookie—using basic, form-based, or custom authentication methods. An X.509 or SAML token can also be used, as long as it is received as part of the HTTP request object.
The token collector creates an appropriate identity token (depending on a specified token type) that corresponds to the user credentials, and passes it to OC4J. In the identity management framework, the type of token is typically an HTTP cookie or HTTP header that contains the user identity. If you do not want to use a cookie or header, then the HTTP request object itself can be used, and you are responsible for an implementation that would know how to parse a request object to retrieve the identity. (For example, the identity could be obtained by parsing and interpreting query parameters.)
A token asserter receives the identity token from OC4J and validates the identity, either by authenticating it against the third-party identity management system, or by validating the token in some other way. The token asserter interface enables you to plug in an assertion mechanism for the identity token. (For example: With OC4J Java SSO, which uses the identity management framework, the identity token is encoded into a cookie, and a symmetric key is used to validate the information in the cookie.)
With respect to the identity management framework, assertion refers to the ability to interpret the identity token, validate its contents, and establish the identity corresponding to the token. This does not necessarily require a password or other credentials, as the token typically comes from a trusted source or is submitted with a key.
Note that a token asserter can accept an identity authenticated by any single sign-on system, allowing the single sign-on system to collect credentials from a custom security provider and pass the identity to OC4J. The token asserter then verifies the identity and establishes the identity within the OC4J container.
Once the identity has been validated, the token asserter returns user information to OC4J through an identity callback handler, which it constructs. At this point, the identity passed in the callback handler is a trusted identity. The callback handler may be constructed simply by passing in an identity string, or an identity string and request object, for example.
OC4J passes the identity callback handler with user information to the login module configured for the application. The login module constructs appropriate callback types to handle user information, and passes them to the identity callback handler through the callback handler handle(Callback[])
method (standard login module functionality). The login module collects principals for the user, such as for roles the user belongs to, by retrieving information from the third-party identity management system as necessary. The login module then sends a populated subject to OC4J.
Note that because the identity has already been validated by the token asserter, there is no need for the login module to perform authentication again. Also note that a custom login module for the identity management framework must be able to handle an identity callback handler.
Alternative: Instead of implementing and configuring a login module for the application, you can provide a token asserter that creates the subject and implements the getSubject()
method to return the subject (populated with user roles) directly to OC4J, without a login module. If you choose this option, there is an identity management framework property (idm.subject.loginmodule.disabled
) that you must set accordingly.
A subject asserter can optionally validate the subject propagated by the login module. For example, you may want to sign and verify subject principals to protect the authenticity of the principals.
Oracle supplies Java interfaces for these components, which you can implement as appropriate to integrate a third-party identity management system with OC4J.
An administrator must configure OC4J to reference the implementation classes to use, and configure the login module.
Figure 13-1 Identity Management Framework Data Flow
Use the following programmatic steps to use a third-party identity management system through the Oracle framework:
Provide a token collector class that implements the token collector interface. One option is to extend the Oracle implementation.
Choose the appropriate identity token class that Oracle supplies, for an HTTP cookie identity token, HTTP header identity token, or HTTP request identity token.
Provide a token asserter class that implements the token asserter interface.
Provide an identity callback handler class that implements the identity callback handler interface, or use the Oracle implementation.
Implement a login module (unless you choose the alternative of having your token asserter populate the subject and implement the getSubject()
method). A login module must be able to appropriately process an identity callback handler instance.
Optionally provide a subject asserter class that implements the subject asserter interface.
The Oracle identity management framework requires the following configuration, discussed in detail later in this chapter:
An administrator configures jazn.xml
to set identity management properties, such as to indicate the token collector implementation class, token asserter implementation class, and token type (such as HTTP header or cookie). Each property is set in a <property>
subelement of the <jazn>
element.
An administrator configures the appropriate login module (or optionally uses the default login module, RealmLoginModule
). Configuration is stored under the <jazn-loginconfig>
element in system-jazn-data.xml
.
For any application to use the framework, the application assembler specifies the authentication method CUSTOM_AUTH
in the orion-application.xml
file packaged with the application.
The OC4J 10.1.3.1 implementation packages an alternative Java single sign-on implementation, Java SSO, that uses the identity management framework. Java SSO, discussed fully in Chapter 14, "OC4J Java Single Sign-On", is an SSO implementation that decouples OC4J from whatever identity system you want to use. It does not have particular infrastructure requirements such as Oracle Identity Management (required for Oracle Single Sign-On) or Oracle Access Manager (required for Oracle Access Manager SSO).
Java SSO includes a token collector implementation to collect cookie credentials and return an identity token to OC4J, and a token asserter implementation to verify the identity in the token and pass the identity back to OC4J in a callback handler.
This section discusses interfaces, APIs, and Oracle implementations to integrate a third-party identity management system with OC4J.
Methods discussed here are typically called by the identity management framework in OC4J.
Notes:
|
See Also:
|
Oracle defines the following identity token interface:
oracle.security.jazn.token.IdentityToken
An identity token object contains user credentials. It is returned by the token collector and passed to the token asserter.
The IdentityToken
interface specifies the following methods:
void setTokenType(String tokenType)
This method specifies the token type: HTTP_COOKIE
, HTTP_HEADER
, or HTTP_REQUEST
.
String getTokenType()
This method returns the token type.
OC4J supplies the following IdentityToken
implementations:
oracle.security.jazn.token.HttpCookieIdentityToken
Instances of this class can be constructed by the token collector by providing a Map
instance that contains the name of the cookie as a key to the cookie value:
HttpCookieIdentityToken(java.util.Map Cookies)
It includes the following method to retrieve identity information:
Map getCookies()
oracle.security.jazn.token.HttpHeaderIdentityToken
Instances of this class can be constructed by the token collector by providing a Map
instance that contains the name of the header as a key to the header value:
HttpHeaderIdentityToken(java.util.Map headerValues)
It includes the following method to retrieve identity information:
Map getHeaderValues()
oracle.security.jazn.token.HttpRequestIdentityToken
This class has the following constructor:
HttpRequestIdentityToken(HttpServletRequest request)
It includes the following method to retrieve identity information:
HttpServletRequest getRequest()
Oracle supplies the following token collector interface:
oracle.security.jazn.collector.TokenCollector
Use an implementation of this interface to receive HTTP-based authentication credentials and create an identity token. The implementation class should include the following functionality:
Collect the credentials from the user request.
Create an identity token for the user.
Pass the token to OC4J.
A token collector takes the following input:
Desired token type (so it knows what type to create)
HTTP request object
List of cookie or header names (as applicable, if the token type is cookie or header)
Any user-defined properties, as applicable
If the token supplied by the user is not valid, the token is missing, or the user cannot be properly asserted (among other possible scenarios), then OC4J calls the token collector fail()
method and passes it the reason for failure. The token collector can then take action as appropriate. The fail()
method must be implemented to perform appropriate failure actions, such as redirecting the user back to a login page, for example.
The TokenCollector
interface specifies the following methods:
IdentityToken getToken(String tokenType, HttpServletRequest request, List names, Properties props)
This method returns an identity token as an Oracle IdentityToken
instance (discussed in the preceding section, "Identity Token Interface and Oracle Implementations"). It takes as input the token type (HTTP_COOKIE
, HTTP_HEADER
, or HTTP_REQUEST
); the current request object; a list of names of cookies or headers, from the HTTP request, that will constitute the token; and any custom properties that may be configured.
The list of names is not applicable when using HTTP_REQUEST
, so would be null in that case. When using HTTP_COOKIE
or HTTP_HEADER
, the list corresponds to cookie names or header names configured through the properties idm.token.collector.cookie.
#
or idm.token.collector.header.
#
, respectively. The #
is replaced by numbers (1, 2, ..., n), as discussed in "Configuring Identity Management Framework Properties".
The list of properties would be specific to the particular token collector implementation and would be used by the token collector as applicable. By convention, any such property names must start with "custom.
" (including the period). For example, Java SSO properties include custom.sso.url.login
and custom.sso.key.alias
.
void fail(HttpServletRequest request, HttpServletResponse response, int reason)
throws CollectorException
This method would be called in a variety of failure modes, including:
The required token is not found in the HTTP request object during execution of the getToken()
method.
The identity is not asserted successfully (such as if the supplied token is not valid).
The identity is successfully established but the user attempts to access resources without proper permission (authorization failure).
The integer reason
is a code specified by OC4J that indicates why the failure occurred, and is one of the following values (defined in the class oracle.security.jazn.collector.IdmErrorConstants
):
REASON_CHALLENGE_USER
: The user is not authenticated, but can be prompted for authentication (401 error in the browser). This is typically for basic authentication, where the browser will bring up the authentication window again. The value of this constant is 1.
REASON_INVALID_USER
: The user is not authenticated, for example due to invalid credentials (401 error). The value of this constant is 1.
REASON_UNAUTHORIZED
: The user is authenticated, but not authorized to access the protected resource (403 error). The value of this constant is 2.
REASON_PRECLUDED_ACCESS
: The resource is protected by a security constraint that contains no roles (403 error). The value of this constant is 3.
Oracle supplies the following TokenCollector
implementation:
oracle.security.jazn.collector.oc4j.TokenCollectorImpl
This implementation is an abstract class that supports the use of an HTTP cookie or HTTP header for the identity token. If either of these is what you want to use, then you can extend TokenCollectorImpl
and add appropriate error handling in the fail()
method (such as redirecting the user to the login page, for example).
The getToken()
method of TokenCollectorImpl
returns the appropriate token type according to your configuration—either HttpCookieIdentityToken
or HttpHeaderIdentityToken
.
To use the HTTP request object itself instead of a cookie or header, you must implement a custom token collector.
A token collector uses the constructor of the appropriate identity token class to create the token. The HttpCookieIdentityToken
, HttpHeaderIdentityToken
, and HttpRequestIdentityToken
constructors are documented in "Identity Token Interface and Oracle Implementations".
Important: You must provide your own implementation of thefail() method, which is an abstract method in TokenCollectorImpl . |
Oracle supplies the following token asserter interface:
oracle.security.jazn.asserter.TokenAsserter
Implement this interface to accept an identity token passed by OC4J and return an identity callback handler to OC4J.
Once OC4J successfully receives an identity token from the token collector, it passes the token to the token asserter, which must validate the identity for that token.
If the identity is validated successfully, then the user is considered authenticated and the identity is returned to OC4J as an identity callback handler.
A token asserter can also optionally get all the roles or groups for the identity and populate a subject for it, or this can be left to a login module.
The TokenAsserter
interface specifies the following method:
IdentityCallbackHandler assertIdentity(String tokenType, IdentityToken token, Properties props) throws AsserterException
Upon successful validation, this method returns the asserted identity in an instance of IdentityCallbackHandler
(discussed in the next section, "Identity Callback Handler Interface"). The token type is HTTP_COOKIE
, HTTP_HEADER
, or HTTP_REQUEST
. The token is an instance of IdentityToken
(discussed earlier). The properties would be the same as described for the getToken()
method in "Token Collector Interface and Oracle Implementation".
If you extend TokenCollectorImpl
for the token collector, your token asserter must use the applicable identity token method to get identity information from the token. These methods in HttpCookieIdentityToken
, HttpHeaderIdentityToken
, and HttpRequestIdentityToken
were noted earlier.
Note: You can avoid using a login module by implementing a token asserter that accesses the identity management system, populates the subject, and implements agetSubject() method. If you choose this alternative, the identity management property idm.subject.loginmodule.disabled must be set accordingly. |
See Also:
|
Use an identity callback handler in conjunction with a token asserter. Oracle supplies the following identity callback handler interface:
oracle.security.jazn.callback.IdentityCallbackHandler
An identity callback handler is constructed by the token asserter and used to pass the asserted identity to OC4J. This is the user identity that will also be passed, typically to a login module, so that a subject corresponding to the identity can be populated with principals as appropriate.
The IdentityCallbackHandler
interface specifies the following methods:
void setIdentity(String identity) throws AsserterException
This method takes a string to specify the user identity.
String getIdentity()
This method returns a string with the user identity.
Subject getSubject()
If a subject was populated by the token asserter, then the identity management framework uses this method to retrieve it. Otherwise (if it is the login module that populates the subject), this method returns null
.
There is also the following standard callback handler method:
void handle(Callback[] callbacks)
This method takes an array of one or more javax.security.auth.callback.Callback
instances in order to handle (such as retrieve or display) information in the provided callbacks.
Oracle supplies the following identity callback handler implementation:
oracle.security.jazn.callback.IdentityCallbackHandlerImpl
Oracle provides the following callback implementations in package oracle.security.jazn.callback
, for use with the identity management framework:
IdentityCallback
HttpRequestCallback
Oracle supplies an identity callback class for use with the identity management framework:
oracle.security.jazn.callback.IdentityCallback
You can use an IdentityCallback
instance to obtain the identity itself, as well as the authentication state of the identity (whether it has been authenticated) and the authentication method used to authenticate it.
The constructor takes no parameters:
IdentityCallback()
You can then use the identity callback handler handle()
method to set an identity callback into the callback handler.
// In token asserter: IdentityCallbackHandler ich = new IdentityCallbackHandlerImpl("identity"); ... // In login module: IdentityCallback icb = new IdentityCallback(); Callback[] callback = {icb}; ich.handle(callback);
The IdentityCallback
class has the following methods:
String getIdentity()
Retrieves the identity from the identity callback, as a string.
boolean isIdentityAsserted()
Returns true
if the identity has been asserted, or false
if it has not.
String getAuthenticationType()
Indicates the authentication method (such as form-based or basic) used to authenticate the identity.
Oracle provides an HTTP request callback class for identity management framework implementations that do not use HTTP cookies or HTTP headers as the token type:
oracle.security.jazn.callback.HttpRequestCallback
Using an HTTP request callback instance, the login module can obtain the credentials from the request object, authenticate the user, and populate a subject for the user.
The constructor takes no parameters:
HttpRequestCallback()
You can then use the identity callback handler handle()
method to set an HTTP request callback into the callback handler.
// In token asserter: IdentityCallbackHandler ich = new IdentityCallbackHandlerImpl("identity"); ... // In login module: HttpRequestCallback httpreqcb = new HttpRequestCallback(); Callback[] callback = {httpreqcb}; ich.handle(callback);
The HttpRequestCallback
class has the following methods:
void setHttpRequest(HttpServletRequest request)
Use this method to set the HTTP request object, presumably containing the user credentials.
HttpServletRequest getHttpRequest()
This method returns the HTTP request object.
A typical implementation of the identity management framework includes a custom login module. After an identity is successfully asserted by the token asserter, the token asserter passes the identity to OC4J as an identity callback handler, which OC4J then passes to the login module.
In typical JAAS usage, a login module executes two key functions: authenticating the user, and populating a subject for the user. Within the identity management framework, however, the login module need not handle authentication. Its key function is to access the identity management system as necessary in order to get information about roles for the user and to populate the subject.
A login module used with the identity management framework must be able to handle an IdentityCallbackHandler
instance that is used to pass the user name. The login module must accomplish the following:
Receive an IdentityCallbackHandler
instance from OC4J.
Construct appropriate callbacks for handling user information. If you use cookie or header tokens, this can include the Oracle callback oracle.security.jazn.callback.IdentityCallback
as well as standard callbacks such as javax.security.auth.callback.NameCallback
and PasswordCallback
. If you use HTTP request tokens, you would use an Oracle callback oracle.security.jazn.callback.HttpRequestCallback
.
Pass callbacks to the IdentityCallbackHandler
instance through its handle(Callback[])
method.
Get the identity through the appropriate callback.
Go to the identity system to find out the roles (or groups) for the identity.
Populate a subject to send to OC4J.
Notes:
|
You can optionally implement a subject asserter to validate the subject that was populated and returned by the token asserter or login module. OC4J will invoke a subject asserter if one is configured. In a typical use case, the subject has been signed, the signature has been added to the subject as a principal, and the subject asserter examines and validates the signature.
Oracle supplies the following subject asserter interface:
oracle.security.jazn.asserter.SubjectAsserter
The SubjectAsserter
interface specifies the following method:
boolean assertSubject(Subject subject) throws AsserterException
Use this method to validate the subject; it returns true if successful.
Implementation classes you create for the identity management framework are not part of your application and are not packaged and deployed with your application. Package them into a single JAR file, and add the JAR file to the OC4J class path. You can do this as a shared library that can be imported by any application that needs to use it, as documented in "Tasks to Share a Library".
If you implement a login module as part of your identity management framework implementation, you can include that in the same library or as a separate library.
Note: The shared library feature is the preferred way to make a JAR file available to OC4J applications, but alternatively you can put the JAR file into the following directory:ORACLE_HOME/j2ee/home/lib/ext
(Note that this makes it globally available.) |
This section documents configuration for the identity management framework, covering the following topics:
An administrator configures the framework properties and login module, while an application assembler sets the authentication method to configure the application to use the framework.
Note: By default in any single-instance OC4J installation, Java SSO, which is an implementation of the identity management framework, is preconfigured as shown in "Default Java SSO Property Settings for Single-Instance OC4J Installations". |
An administrator configures jazn.xml
to set properties for the identity management framework, as appropriate for the class implementations being used. Table 13-1 describes the identity management framework properties.
Table 13-1 Identity Management Framework Properties
Property | Description |
---|---|
idm.authentication.name |
This can be anything that specifies or qualifies how the identity management framework is being used. It is merely for reference and is not used by the framework. (For example, for OC4J Java SSO this is set to " |
idm.token.type |
Type of identity token to use: |
idm.token.collector.class |
Fully qualified name of the class that implements the token collector interface. |
idm.token.asserter.class |
Fully qualified name of the class that implements the token asserter interface. |
idm.subject.asserter.class |
Fully qualified name of the class that implements the subject asserter interface (if applicable). |
idm.subject.loginmodule.disabled |
A boolean that specifies whether to invoke the login module ( |
idm.token.collector.cookie.# |
Name(s) of cookie(s) containing identity information. You can specify one or more, replacing " |
idm.token.collector.header.# |
Name(s) of HTTP header(s) containing identity information. As with cookies, you can specify one or more, replacing " |
Set these properties in <property>
subelements of the <jazn>
element, as in the following example:
<jazn provider="XML" location="./system-jazn-data.xml" default-realm="jazn.com"> ... <!-- properties to configure the 3rd party IDM framework --> <property name="idm.authentication.name" value="JavaSSO" /> <property name="idm.token.asserter.class" value="oracle.security.jazn.sso.SSOCookieTokenAsserter" /> <property name="idm.token.collector.class" value="oracle.security.jazn.sso.SSOCookieTokenCollector" /> <property name="idm.token.type" value="HTTP_COOKIE" /> <property name="idm.token.collector.cookie.1" value="ORA_OC4J_SSO"/> ... </jazn>
Important:
|
Assuming you will use a custom login module (as is typical), it must be configured. You can configure a custom login module either during or after application deployment through Application Server Control, as discussed in "Configuring the Custom Security Provider in Application Server Control". (The OracleAS JAAS Provider Admintool also has options for login module configuration, as noted in "Using Admintool to Configure Login Modules and Grant RMI Permission".)
The configuration is stored in the system-jazn-data.xml
file. The following example is for a custom login module CustomLM
used with an application myapp
:
<jazn-loginconfig> <application> <name>myapp</name> <login-modules> <login-module> <class>mypackage.CustomLM</class> <control-flag>required</control-flag> <options> <option> <name>addAllRoles</name> <value>true</value> </option> </options> </login-module> </login-modules> </application> </jazn-loginconfig>
For any application that will use the identity management framework, the application assembler must specify the authentication method CUSTOM_AUTH
in the <jazn-web-app>
element of the orion-application.xml
file. Here is an example:
<jazn provider="XML" ... > ... <jazn-web-app auth-method="CUSTOM_AUTH" /> ... </jazn>
This triggers usage of the identity management framework according to configuration of the framework properties in jazn.xml
, and of the login module in system-jazn-data.xml
(as applicable).
Important: If you switch from the file-based provider to Oracle Identity Management at any time for any application through Application Server Control, the<jazn> element in orion-application.xml for the application is replaced with the following. A CUSTOM_AUTH setting for the identity management framework would be lost and would have to be redone.
<jazn provider="LDAP" /> |
Notes:
|
For an installation type with multiple OC4J instances, any configuration for the identity management framework must be duplicated across instances. This includes identity management framework property settings in jazn.xml
, and the login module configuration (as applicable) in system-jazn-data.xml
. Take the following steps, as appropriate:
Repeat the same security provider configuration in each OC4J instance.
Use OC4J group functionality to coordinate system-jazn-data.xml
updates. This updates each system-jazn-data.xml
file across a group of OC4J instances. This would include user settings if you are using the file-based security provider. "Cluster MBean Browser Features and the J2EEServerGroup MBean" discusses how to coordinate settings in each system-jazn-data.xml
file across OC4J instances. There are also operations for maintaining login module configuration across instances (for example, setLoginModule
).
As necessary, go to each OC4J instance and repeat configuration, through Application Server Control or manually as applicable. Generally speaking, for property settings in the jazn.xml
file, such as for identity management framework settings, the only option is to manually configure jazn.xml
in each OC4J instance.
See Also:
|
This section summarizes previous discussion of the key duties involved in using the identity management framework.
The integrator (the developer who is integrating some third-party identity management system into OC4J) implements classes as appropriate for identity management framework components: token collector, identity token, token asserter, identity callback handler, and subject asserter.
The integrator develops a custom login module as desired.
The integrator packages the implementation classes into a JAR file, and packages the login module into the same JAR file or a separate JAR file.
The integrator or administrator deploys each JAR file to the target system as a shared library.
The application is enabled to use the identity management framework. This can be accomplished by the assembler in setting auth-method="CUSTOM_AUTH"
before deployment, in the <jazn-web-app>
element of the orion-application.xml
file packaged with the application.
The application deployer deploys the application, using Application Server Control. This includes configuring any custom login module (or it can be configured later by an administrator) and importing the shared library comprising the implementation classes.
On the target system, the administrator configures identity management framework properties in the jazn.xml
file.
This sample assumes that the user is being authenticated against some custom identity store. Subsequently, a custom HTTP header ("Acme-Custom-Auth
") containing the identity of the logged-in user is added to the request. Sample components function as follows:
The token collector implementation extracts the header value.
The token asserter implementation verifies the identity from the header, then asserts this identity through identity callback handler functionality using the IdentityCallbackHandlerImpl
class that Oracle supplies.
The corresponding configuration is in jazn.xml
, as shown.
This section shows the code for the sample token collector implementation.
package com.acme.idm; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Properties; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import oracle.security.jazn.collector.CollectorException; import oracle.security.jazn.collector.oc4j.TokenCollectorImpl; import oracle.security.jazn.token.HttpHeaderIdentityToken; import oracle.security.jazn.token.IdentityToken; import oracle.security.jazn.token.TokenNotFoundException; import oracle.security.jazn.collector.IdmErrorConstants; public class CollectorImpl extends TokenCollectorImpl { public CollectorImpl() { } public IdentityToken getToken(String tokenType, HttpServletRequest request, List tokenNames, Properties properties) throws CollectorException, TokenNotFoundException { if (null == tokenType || 0 == tokenType.length() || !IdentityToken.HTTP_HEADER.equalsIgnoreCase(tokenType)) { throw new CollectorException("invalid token type" + tokenType); } HttpHeaderIdentityToken identityToken = (HttpHeaderIdentityToken)super.getToken(tokenType, request, tokenNames, properties); Map m = identityToken.getHeaderValues(); if (m == null || m.size() == 0) { throw new TokenNotFoundException("no HTTP Header token was found"); } return identityToken; } public void fail(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, int reason) { try { switch (reason) { case IdmErrorConstants.REASON_INVALID_USER: httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); case IdmErrorConstants.REASON_UNAUTHORIZED: httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN); } } catch (Exception e) { System.err.println("failed to send response " + e); e.printStackTrace(System.err); } } }
This section shows the code for the sample token asserter implementation.
The assumption is that for all unauthenticated users, the Oracle HTTP Server or other Web server in front of OC4J will send "Acme-Custom-Auth
" set to "ANONYMOUS
". The Acme implementation requires that the user be authenticated. (A more production-quality implementation would very likely not pass a clear user name in the header, because there would be no way to validate where the header was generated.)
package com.acme.idm; import java.util.Map; import java.util.Properties; import oracle.security.jazn.asserter.AsserterException; import oracle.security.jazn.asserter.TokenAsserter; import oracle.security.jazn.callback.IdentityCallbackHandler; import oracle.security.jazn.callback.IdentityCallbackHandlerImpl; import oracle.security.jazn.token.IdentityToken; import oracle.security.jazn.token.HttpHeaderIdentityToken; public class TokenAsserterImpl implements TokenAsserter { private static final String HEADER_NAME = "Acme-Custom-Auth"; private static final String AUTH_TYPE = "CUSTOM_HTTP_HEADER"; public TokenAsserterImpl() { } public IdentityCallbackHandler assertIdentity(String tokenType, IdentityToken identityToken, Properties properties) throws AsserterException { if (tokenType != null && tokenType.length() > 0 && IdentityToken.HTTP_HEADER.equalsIgnoreCase(tokenType)) { HttpHeaderIdentityToken token = (HttpHeaderIdentityToken) identityToken; Map m = token.getHeaderValues(); if (m != null && m.size() > 0) { String user = (String) m.get(HEADER_NAME); if ("ANONYMOUS".equalsIgnoreCase(user)) { throw new AsserterException ("anon user - expected authenticated user"); } IdentityCallbackHandler idcb = new IdentityCallbackHandlerImpl(user); idcb.setIdentityAsserted(true); idcb.setAuthenticationType(AUTH_TYPE); return idcb; } else { throw new AsserterException ("not a valid token - no identity to assert"); } } } }
This section shows the configuration in the jazn.xml
file for this sample.
<?xml version="1.0" encoding="UTF-8" standalone='yes'?> <jazn xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation= "http://xmlns.oracle.com/oracleas/schema/jazn-10_0.xsd" schema-major-version="10" schema-minor-version="0" provider="XML" location="./system-jazn-data.xml" default-realm="jazn.com" > <property name="idm.token.asserter.class" value="com.acme.idm.TokenAsserterImpl" /> <property name="idm.token.collector.class" value="com.acme.idm.CollectorImpl" /> <property name="idm.token.type" value="HTTP_HEADER" /> <property name="idm.token.collector.header.1" value="Acme-Custom-Auth" /> <property name="idm.authentication.name" value="Acme-IDM" /> </jazn>