You can create a Certificate Identity Resolver (CIR) Provider
for User Management that is used while performing certificate-based
authentication. Using a CIR provider, you can map a custom certificate
attribute to the user instead of the default ones supported by User
Management. By default, User Management supports mapping from e-mail,
DN, common name (CN) and name. For example, consider the following
attribute map.
CN = TONY BLUE
G = Tony
SN = Blue
Serial Number = 33532809M
C = ES
Assume that you want to use the serial number attribute of Subject
to perform the mapping. You can use its value to map to the user's
canonical name. To perform this task, create a CIR provider that
performs the custom mapping. A CIR provider is used in addition
the User Management authentication logic that validates the certificate.
To create a CIR provider, you use the User Management
IdentityResolver
SPI
to create a LiveCycle custom component. An IdentityResolver
resolves a set of data and returns a user.
Summary of steps
To develop a CIR provider, perform the following
steps:
-
Set up your development environment.
-
Define your application logic.
-
Define the component XML file.
-
Register the CIR provider with User Management. (This step
is only required for the CIR provider and not required for other
component types.)
-
Package the CIR provider.
-
Deploy and test your CIR provider.
Setting up your development environment
To
create a CIR Provider, create an Eclipse Java project. The version
of Eclipse that is supported is 3.2.1 or later. The User Management
SPI requires the um-spi.jar file to exist in your project’s class
path. If you do not reference this JAR file, you cannot use the
User Management SPI in your Java project. This JAR file is installed
with the LiveCycle SDK in the <install directory>/Adobe/Adobe
LiveCycle ES4/sdk
/spi
folder.
The following JAR files must be added to your project’s classpath:
Defining your application logic
To define a CIR Provider, create a Java class that implements
com.adobe.idp.um.spi.authentication.IdentityResolver
.
The Java class that implements
IdentityResolver
contains
a method named
resolve
, which resolves passed in
data and returns a user. In the following example, notice that the
resolve
method
accepts a
Map
instance as a parameter. The Map instance
contains a user's certificate list that is stored against the key
UMConstants.AuthenticationOptions.USER_CERTIFICATE
.
The
Map
object’s
get
method returns
a
java.util.List
instance that contains an element
that stores the certificate. The data type of the certificate element
is
java.security.cert.X509Certificate
.
To obtain a certificate, invoke the
java.util.List
instance’s
get
method
and pass a numeric value that corresponds to the index value. The
first entry in the certificate list contains the user's certificate.
From the certificate, you can obtain the serial number. In the following
example, the
java.security.cert.X509Certificate
instance is
passed to a user-defined method named
getSerialNumber
.
This method accepts a
java.security.cert.X509Certificate
instance as
a parameter and returns a string value that represents the user’s
serial number.
The following application logic represents the
CertIdentityResolver
class
that implements
com.adobe.idp.um.spi.authentication.IdentityResolver
.
package com.adobe.livecycle.sample;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.security.auth.x500.X500Principal;
import com.adobe.idp.dsc.clientsdk.ServiceClientFactory;
import com.adobe.idp.um.api.DirectoryManager;
import com.adobe.idp.um.api.UMAuthenticationUtil;
import com.adobe.idp.um.api.UMConstants;
import com.adobe.idp.um.api.UMException;
import com.adobe.idp.um.api.infomodel.PrincipalSearchFilter;
import com.adobe.idp.um.api.infomodel.User;
import com.adobe.idp.um.spi.authentication.IdentityResolver;
import com.adobe.livecycle.usermanager.client.DirectoryManagerServiceClient;
import com.adobe.logging.AdobeLogger;
public class CertIdentityResolver implements IdentityResolver {
private static final AdobeLogger logger = AdobeLogger.getAdobeLogger(CertIdentityResolver.class);
private static final String SERIAL_NUMBER = "serialnumber";
public User resolve(Map<String, Object> credential) {
List<X509Certificate> javaCerts =
(List<X509Certificate>) credential.get(UMConstants.AuthenticationOptions.USER_CERTIFICATE);
if(javaCerts == null || javaCerts.isEmpty()){
throw new IllegalArgumentException("No certificate list passed");
}
//The first certificate in the list contains the user certificate. Others are the part of Trust Chain
X509Certificate userCert = javaCerts.get(0);
String serialNumber = getSerialNumber(userCert);
if(serialNumber == null){
logger.warning("Serial number not found with the certificate");
return null;
}
DirectoryManager dm = new DirectoryManagerServiceClient(ServiceClientFactory.createInstance());
User u = findPrincipal(serialNumber,dm);
//Due to a bug in UM need to set User against this key. It should be required by the Resolvers to set it
//But setting it let it work for now
if(u != null){
credential.put(UMAuthenticationUtil.authenticatedUserKey, u);
}
return u;
}
private String getSerialNumber(X509Certificate userCert){
X500Principal xp = userCert.getSubjectX500Principal();
Map<String,String> oidMap = new HashMap<String,String>();
//This is the OID for serialnumber as per std
oidMap.put("2.5.4.5", SERIAL_NUMBER);
String subjectName = xp.getName(X500Principal.RFC2253,oidMap);
LdapName name = null;
try {
name = new LdapName(subjectName);
} catch (InvalidNameException e) {
throw new RuntimeException(e);
}
for(Rdn rdn : name.getRdns()){
String attr = rdn.getType();
if(SERIAL_NUMBER.equals(attr)){
return rdn.getValue().toString();
}
}
return null;
}
private User findPrincipal(String serialNumber, DirectoryManager dm) {
PrincipalSearchFilter psf = new PrincipalSearchFilter();
psf.setSpecificDomainName(UMConstants.DEFACL_DEF_DOMAIN);
psf.setCanonicalName(serialNumber);
psf.setRetrieveOnlyActive();
try {
//If its canonical based search only prefer using dm.findPrincipal(canonical,domain)
//Using filter approach for more genric approach
List p = dm.findPrincipals(psf);
return (User) (p.isEmpty() ? null : p.get(0));
} catch (UMException e) {
throw new RuntimeException("Error invoking UM",e);
}
}
}
Defining the component XML file for the directory service provider
Create
a component XML file to deploy the CIR provider. A component XML
file exists for each component and provides metadata about the component.
For more information about the component XML file, see the
Component XML Reference
.
The following component.xml file is used for the CIR provider.
Notice that the service name is
CertIdentityResolver
and
the implementation class is
com.adobe.livecycle.sample.CertIdentityResolver
.
Defining the component XML file for the CIR provider
<component xmlns="http://adobe.com/idp/dsc/component/document">
<component-id>com.adobe.livecycle.samples.authentication.CertIdentityResolverService</component-id>
<version>1.0</version>
<supports-export>false</supports-export>
<services>
<service name="CertIdentityResolver">
<implementation-class>com.adobe.livecycle.sample.CertIdentityResolver</implementation-class>
<auto-deploy major-version="1" />
</service>
</services>
</component>
Register the CIR provider with User Management
Register the CIR provider with User Management by modifying
an XML configuration file by using administration console. For information
about modifying the configuration XML file, see the
Importing and exporting the configuration file
topic
in administration help.
Once you export the XML configuration file, search for a node
named
AdobeDefaultCertificate
. Under this node,
add a node named
DefaultConfig
. Under the
DefaultConfig
node,
add an entry for the
identityResolver
key. Specify
the name of the service specified in the component XML file. In
this example, the value
CertIdentityResolver
is
specified.
The following example shows the modified XML configuration file.
<node name="AdobeDefaultCertificate">
<map>
<entry key="enabled" value="true"/>
<entry key="visibleInUI" value="false"/>
<entry key="order" value="5"/>
<entry key="configured" value="true"/>
<entry key="allowMultipleConfigs" value="false"/>
<entry key="className" value="com.adobe.idp.um.provider.authentication.CertificateAuthProviderImpl"/>
</map>
<node name="DefaultConfig">
<map>
<entry key="identityResolver" value="CertIdentityResolver"/>
</map>
</node>
</node>
Note:
After you modify the XML configuration file,
ensure that you import it into LiveCycle.
Packaging the certificate identity resolver provider
Before deploying the CIR provider to LiveCycle,
package your Eclipse project into a JAR file. Also, the component
XML file and external JAR files must be located at the root of the
JAR file.
The following illustration shows the Eclipse project’s content
that is packaged into the CIR provider’s JAR file.
Package the CIR provider into a JAR file named CIRProviderSample-dsc.jar.
In the previous diagram, notice that the .JAVA file is listed. Once
packaged into a JAR file, the corresponding .CLASS file must also
be specified. Without the .CLASS file, the CIR provider does not
work.
Note:
After you package the CIR provider into a JAR
file, you can deploy the component to LiveCycle. (See
Deploying your component
.)
Deploying and testing the certificate identity resolver provider
After you package the certificate identity resolver provider,
deploy and test it.
To deploy the CIR provider:
-
Start Workbench.
-
Log in to Workbench.
-
Select
Window
>
Show Views
>
Components
.
This action adds the Components view to Workbench.
-
Right-click the
Components
icon and select
Install Component
.
-
Select the CIRProviderSample-dsc.jar file through the file
browser and click
Open
.
Notice that there is a red
square next to
com.adobe.livecycle.samples.authentication.CertIdentityResolverService
.
Expand
com.adobe.livecycle.samples.authentication.CertIdentityResolverService
.
-
Select
Service Descriptors
, and then right-click
CertIdentityResolver
and
select
Activate Service
.
-
Right-click
com.adobe.livecycle.samples.authentication.CertIdentityResolverService
and
select
Start Component
. A green arrow appears next to the
name if it succeeds. Notice that CertIdentityResolver is automatically
deployed and has a green arrow next to it if it succeeds.
Now
you can use a certificate that contains a user’s serial number to
authenticate with LiveCycle. For example, assume that you
have a .P12 certificate file that contains a serial number value
of 123. You can create a local user and sets its canonical name
to 123. Using the certificate, you can authenticate as that user.
Note:
Ensure that you place the certificate that contains
the users’s serial number in Trust Store. For information, see the
Managing certificates and credentials topic in
administration help
.
|
|
|