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.
Note: The IdentityResolver SPI was
added in LiveCycle ES2.5.
Summary of stepsTo 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 environmentTo
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 logicTo 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
ajava.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 providerCreate
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 ManagementRegister 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 LiveCycle 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 providerBefore 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 providerAfter 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 LiveCycle Administration Help.
|
|
|