How to use NetLicensing with Java and Spring Security
Recently we started a journey through user Authentication-Authorization and entitlements Validation process with the article What is Authentication-Authorization-Validation Framework.
Now that we have a basic understanding of AAV Framework and what it brings to us, I think it’s time to see how we can apply this to enhance user authorization flow.
We will use Spring Security demo project as a good starting point. This demo project offers implementation of sample authentication and authorization process as well as simple UI (Spring MVC Framework).
These steps needed to integrate NetLicensing customer entitlements validation in the Java Spring Security project:
- Setup Spring Security Project
- Configure NetLicensing Product
- Integrate NetLicensing RESTful API
Setup Spring Security Project
Prerequisites
- Installed Java (>= 8.x)
- Installed Maven (>= 3.5)
Spring Security demo project can be cloned or forked on GitHub.
> git clone https://github.com/Labs64/gs-securing-web
After clone, you can verify your setup and preconditions by executing:
> cd complete
> ./mvnw spring-boot:run
First execution might take a bit more time, as all needed Maven project dependencies need to be downloaded in your local Maven repository.
If everything works well, you should see the following message:
...
2020-11-13 10:04:43.948 INFO 5093 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
...
… and you can open the website in your browser at localhost:8080 (make sure you are using Tomcat port number from the log message).
To work with the java source code, you can use any available IDE; e.g. Eclipse, IntelliJ IDEA, VSCode, etc.
So, now your development environment is set up, and we can move on to the next step.
Configure NetLicensing Product
As next, we will create NetLicensing product configuration, which will be used to specify customers entitlements. You can create the product, module and packages configurations manually (you might find these video tutorials helpful) or simply open Demo Data view and create one of the demo configurations for the chosen Licensing Model.
After this step is finished, you should have the following entities created:
Product
NetLicensing Product corresponds to your specific product being offered to the end-customers.
For this demo, we recommend enabling “Auto-create customer” option, so every not-existing customer will be created automatically upon the first validation request.
Module
NetLicensing Module represents a specific product licensing schema and configured using one of the supported Licensing Models.
Did you know!
One product in the NetLicensing can be configured using more than one licensing models, which is allowing you the highest level of customization accordingly to your business needs.
Packages
NetLicensing Package is an individual product module configuration which is defining licensing packages offered to the end-customers.
Did you know!
Modules & Packages configuration can vary depending on the chosen licensing model.
You need to note the following configuration data for the NetLicensing API integration described in the next chapter:
- Product Number
- Module Number
Integrate NetLicensing RESTful API
NetLicensing offers a very flexible RESTful API, which can be implemented with almost every programming language and technology stack. To speed up integration, a set of predefined client libraries is provided. In this demo, we will be using NetLicensing Java Client library.
Maven dependency
NetLicensing Java Client library needs to be added as a project dependency in the pom.xml
file
<dependency>
<groupId>com.labs64.netlicensing</groupId>
<artifactId>netlicensing-client</artifactId>
<version>2.9.6</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
For this demo, we will slightly modify Spring Security configuration and allow every username with the same password as username (e.g. guidechimp
:guidechimp
)
complete/src/main/java/com/example/securingweb/WebSecurityConfig.java
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/home").permitAll().anyRequest().authenticated().and().formLogin()
.loginPage("/login").permitAll().and().logout().permitAll();
}
@Bean
@Override
public UserDetailsService userDetailsService() {
return new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Set password same as username
return User.withDefaultPasswordEncoder().username(username).password(username).roles("USER").build();
}
};
}
Every logged-in user will be forwarded to the /hello
page. We introduced a new controller class, which will receive username for the logged-in user and use this to validate users entitlements in the NetLicensing.
This class need to be changed with the specific configuration you made in the previous step:
NLIC_APIKEY
- NetLicensing API Key with the Role:Licensee
; API Key can be created in the Management Console / Settings view.NLC_PRODUCT
- use created Product NumberNLC_MODULE
- use created Module Number
After successful validation, the result will be added to the Spring MVC model object and shown on the /hello
page.
complete/src/main/java/com/example/securingweb/NetLicensingController.java
@GetMapping("/hello")
public String greeting(Model model) throws NetLicensingException {
// NetLicensing configuration
// API Key - min role needed: Licensee
final String NLIC_APIKEY = "ea624604-028e-458c-b5e5-85bc6620b890";
// Product number
final String NLC_PRODUCT = "P1S85TDRU-DEMO";
// Product module number
final String NLC_MODULE = "MTGTOW8EC-DEMO";
// Initiate NetLicensing context
final Context context = new Context();
context.setBaseUrl("https://go.netlicensing.io/core/v2/rest");
context.setSecurityMode(SecurityMode.APIKEY_IDENTIFICATION);
context.setApiKey(NLIC_APIKEY);
// Prepare validation request
final ValidationParameters validationParameters = new ValidationParameters();
validationParameters.setProductNumber(NLC_PRODUCT);
// Send validation request; where current login username will be used as unique customer identifier
ValidationResult validationResult = LicenseeService.validate(context, getUsername(), validationParameters);
// Prepare model to be rendered on the hello page
Composition moduleValidation = validationResult.getProductModuleValidation(NLC_MODULE);
model.addAttribute("name", getUsername());
model.addAttribute("moduleValidation", moduleValidation);
return "hello";
}
Hello page was extended in order to show NetLicensing validation status and other relevant information.
complete/src/main/resources/templates/hello.html
...
<hr>
<h2 th:inline="text">[[${moduleValidation.properties.get('productModuleName')}]]!</h2>
<p th:text="'- valid: ' + ${moduleValidation.properties['valid']}" />
<p th:text="'- expires: ' + ${moduleValidation.properties['expires']}" />
<p th:text="'RAW validation result: ' + ${moduleValidation}" />
...
Now you can start the project again and verify NetLicensing integration.
> ./mvnw spring-boot:run
Conclusion
With the above simple adjustments, we added the possibility to validate customers licenses maintained in the NetLicensing system.
This validation process extends standard authentication & authorization steps and allows you to drive application behaviour based on the customer’s entitlements and validation status.
We are always happy to receive your feedback as well as suggestions on how we can improve NetLicensing services. Get in touch with us here.
Source code: Labs64/gs-securing-web
Image Credits: NetLicensing