Integrating Cortex with an alternate Identity Management System
Integrating Cortex with an alternate Identity Management System
This class explains how you could potentially swap a custom Identity Management System (IdM) with Cortex's out-of-the-box one.
An Identity Management System manages the authentication, authorization, roles and privilege of each customer across systems and enterprises. Out of the box, Cortex integrates with Commerce Engine's Identity Management System. This tutorial follows the implementation methodology described in Creating a Resource Integration to swap out the Commerce Engine's IdM and swap it with a custom IdM to communicate with Cortex.
- Cortex Architecture: Architecture Overview.
- Your Identity Management System (Our tutorial code does not talk to an Identity Management System. From the examples below, you need to infer how code a resource integration to communicate with your custom Identity Management System).
- DTOs and Interface Strategies (Don't worry, you don't need to know these inside out, just be aware of how they work).
- Cortex Web Application POMs
Creating the Identity Management Integration Project
Creating a new Resource Integration project is the first lesson in this class. Elastic Path provides a Maven Archetype to simplify the task to create a new resource integration. Archetypes are project templates that contain some of the standard components you'll need for your project.
- Open a command prompt and navigate to your Extensions Directory.
- Run the following command to create an Integration project:
mvn archetype:generate -DarchetypeArtifactId=ep-cortex-resource-integration-archetype -DarchetypeGroupId=com.elasticpath.cortex.dce -DarchetypeVersion=<your-artifact-version>
- Enter the variables for your project as prompted (i.e: groupId, version and artifactId).
- Change to the newly created project directory and execute the following command to build the resource integration JAR file.
mvn install
Import the New Resource Integration into Eclipse
Next, you need to import your Resource Integration project into Eclipse as a Maven project.
- In Eclipse, choose File -> Import -> Existing Maven Projects into Workspace, and click Next.
- Click Browse and select the resource integration directory.
- Make sure the project is selected in the list of projects and click Finish.
Add the Resource Integration's Dependency
Once our base project is set up, we need to add the appropriate rest resource dependency to the project's pom.xml.
Why do you need this dependency?
We need to implement the authentication resource's strategy interfaces in order for Cortex to communicate with your custom Identity Management System. Therefore, we need to add this as a dependency to our project so we can access these methods.
- In Eclipse, open your project's pom.xml.
- Add the following code beneath the <description> element:
... <dependencies> <dependency> <groupId>com.elasticpath.rest.relos.rs.authentication</groupId> <artifactId>ep-rs-authentication</artifactId> <version>${cortex.version}</version> </dependency> </dependencies>
- Save the pom.xml.
- Right-click the project and select Maven -> Update Project Configuration, to update your project's dependencies and rebuild.
Implementing the Interfaces
Now that we've created the project and added the appropriate dependency, we're going to implement the authentication strategy's interfaces
There are four interfaces we need to implement to make the appropriate service calls to the custom IdM.
Interface | Purpose |
---|---|
UserAuthenticationStrategy | Authenticates a user against the Identity Management system based on given user credentials. |
PostUserAuthenticationStrategy | Any operations to be performed after a user is authenticated. |
UserPrincipalLookupStrategy | Retrieves information about the user, such as whether the user account is still active. |
RealmValidator | Validates rather the given scope of a request URI is valid. |
UserAuthenticationStrategy
This interface lives under the package com.elasticpath.rest.relos.rs.authentication and provides the following method declaration:
ExecutionResult<AuthenticationResponseDto> authenticate(String scope, String username, String password, String role);
The parameters are the user credentials passed down from the OAuth2 endpoint. The custom Identity Management system uses these credentials to authenticate the user. The AuthenticationResponseDto object returned by the method is a DTO.
AuthenticationResponseDto Fields:
Field | Usage |
---|---|
Id | The Identity Management system's unique identifier for the user. |
Scope | The requested scope |
Role | The requested role |
An example implementation could look like the following:
public ExecutionResult<AuthenticationResponseDto> authenticate(final String scope, final String username, final String password, final String role) { User user = identityManagementService.authenticate(username, password, scope, role); AuthenticationResponseDto dto = ResourceTypeFactory.createResourceEntity(AuthenticationResponseDto.class) .setId(user.getUserId()) .setScope(user.getScope()) .setRole(role); }
This interface lives under the package com.elasticpath.rest.relos.rs.authentication, and provides the following method declaration:
ExecutionResult<Void> execute(AuthHeaderDto authHeaderDto, AuthenticationResponseDto authenticationResponseDto)
AuthHeaderDto is a DTO object containing the information of the current user making the authentication call. AuthenticationResponsetDto is the DTO object created from the authenticate() method call in UserAuthenticationStrategy, and holds information of the authenticated user. If you have any additional operations you wish to perform on the authenticated user, post authentication, then you can implement that logic here. The method should return an ExecutionResult object with a successful status, if all operations are successful.
This interface lives under com.elasticpath.rest.relos.rs.authentication, and provides the following method declaration:
ExecutionResult<UserPrincipalDto> getUserPrincipal(Collection<String> scopes, String userId, Collection<String> roles)
The parameters are the user's unique identifier for the Custom Identity Management system, along with the requested scopes and roles of the user.
This method should return a UserPrincipalDto object, that holds following information about the user:
Field | Usage |
---|---|
AccountEnabled | Is user account enabled? |
AccountLocked | Is user account locked? |
AccountExpired | Has user account expired? |
UserIdentifier | The unique identifier of the user on the Custom Identity Management system |
Username | The user's username |
CredentialsExpired | Has user's credentials expired? |
Scope | The scope accessible by the user. |
Roles | The roles of the user. |
An example implementation could look like the following:
public ExecutionResult<UserPrincipalDto> getUserPrincipal(Collection<String> scopes, String userId, Collection<String> roles) { UserPrincipalDto userPrincipalDto = ResourceTypeFactory.createResourceEntity(UserPrincipalDto.class); User user = identityManagementService.findUser(userId, scopes, roles); userPrincipalDto.setAccountEnabled(user.isEnabled()) .setAccountExpired(false) .setAccountLocked(false) .setUserIdentifier(userId) .setUsername(user.getUserName()) .setCredentialsExpired(false) .setScope(user.getScope()) .setRoles(user.getRoles()); return ExecutionResultFactory.createReadOK(userPrincipalDto); }
This interface contains two methods:
ExecutionResult<String> validate(String realm)
This method validates that the given realm is valid and exists in the integrated system.
Boolean isRealmActive(String realm)
This method validates that the requested realm is still active.
Export your Code for OSGI to Consume
Inside theCortex's Web App, the Cortex runs in an OSGi framework. We need to export our code in a way OSGi can be aware of it and consume it.
To export your code for OSGi:
Declare the following in your project's OSGI-INF/blueprint/example-integration-blueprint.xml:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> ... <service ref="userAuthenticationStrategy" interface="com.elasticpath.rest.relos.rs.authentication.UserAuthenticationStrategy" /> <service ref="userPrincipalLookup" interface="com.elasticpath.rest.relos.rs.authentication.UserPrincipalLookupStrategy" /> <service ref="postUserAuthenticationStrategy" interface="com.elasticpath.rest.relos.rs.authentication.PostUserAuthenticationStrategy" /> <service ref="realmValidator" interface="com.elasticpath.rest.relos.rs.authentication.RealmValidator" /> </blueprint>
Next, add the following declaration to your project's spring/applicationContext-example-integration.xml:
<beans ... <context:component-scan base-package{project.package} scope-resolver="org.springframework.context.annotation.Jsr330ScopeMetadataResolver"/commerce-legacy/> </beans>
mvn install
Override the Old Identity Management Integration with the Custom Identity Management Integration
This lesson teaches you how to override the old identify managment integration with a new one. To make this change, you need to shut down Cortex web application, modify the web application's POM file, and then restart the web application.
In this lesson, you are modifying the following XML elements in the Cortex web application's POM file.
- <dependency> - Tells Maven to include your integration project's jar as a dependency during build.
- <execution> - Execution groups configure the goals for the plugin. In this tutorial, we are going to configure the Cortex API Web App POM to override the out-of-the-box resource asset's <execution> group. For more information on POMs, see Cortex Web Application POMs.
- Shut down Cortex web application.
- With a text editor, open the Cortex web application's pom.xml.
- Add your com.customer.identity.management as a <dependency> and configure the :copy-oauth2-OSGi-bundles <execution> group following the example below:
... <dependencies> <!-- Add Extension resources or Integration modules as maven dependencies here. --> <dependency> <groupId>com.customer.identity.management</groupId> <artifactId>custom-identity-management-integfration</artifactId> <version>1.0-SNAPSHOT</version> <scope>provided</scope> </dependency> </dependencies> ... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <!-- Override Assets CE Integration and use an example integration instead. --> <execution> <id>copy-oauth2-OSGi-bundles</id> <phase>prepare-package</phase> <goals> <goal>copy</goal> </goals> <configuration> <outputDirectory>${war-bundle-directory}</outputDirectory> <artifactItems> <artifactItem> <groupId>com.elasticpath.rest.relos.rs.authentication</groupId> <artifactId>ep-rs-authentication-client</artifactId> </artifactItem> <artifactItem> <groupId>com.elasticpath.rest.relos.rs.authentication</groupId> <artifactId>ep-rs-authentication-spring-oauth2</artifactId> </artifactItem> <artifactItem> <groupId>com.customer.identity.management</groupId> <artifactId>custom-identity-management-integfration</artifactId> </artifactItem> </artifactItems> </configuration> </execution>
- On command line, change to your Cortex web application directory and run the following:
mvn clean install -DskipAllTests