Skip to main content
Version: 4.32.x.x LTS

Plugin Deployment

In the Quickstart chapter, we already learned how to integrate a simple custom AuthState into our nevisAuth instance. This chapter provides more insight into how to deal with specific situations.

Plugin Packaging

A nevisAuth Plugin should bring all its required dependencies, except the nevisauth-authstate-api. By default the pom.xml generated by the Maven archetype uses the Apache Maven Assembly Plugin to create a ZIP archive file containing the Plugin jar file and all its transitive compile and runtime dependencies in the subfolder lib. Additionally, the files README, LICENSE, and NOTICE are included if they exist in the project base directory.

Plugin Classpaths

nevisAuth plugins are loaded when the nevisAuth instance starts. The AuthEngine checks specific paths on the filesystem to find the configured AuthStates and their dependencies.

The paths that are investigated by the AuthEngine are configured in the nevisAuth configuration:

<AuthEngine name="AuthEngine"
classPath="/opt/nevisauth/plugin:/var/opt/nevisauth/default/plugin"
classLoadStrategy="PARENT_FIRST"
useLiteralDictionary="true"
addAutheLevelToSecRoles="true"
compatLevel="none"
inputLanguageCookie="LANG"
>

The plugins that are delivered with the nevisAuth package are located in the /opt/nevisauth/plugin directory. We recommend putting instance-specific plugins into the instance directory: /var/opt/nevisauth/<instance-name>/plugin.

The classloading strategy defines how the classes are discovered by the classloader. With PARENT_FIRST, the AuthEngine classloader first checks whether the class has already been loaded by a parent classloader (which is the container's classloader). With PARENT_LAST, the AuthEngine classloader will try to discover and load the class, but delegate the class loading to the parent if it cannot be found.

Different strategies have different effects. With PARENT_FIRST, you reduce the amount of the MetaSpace memory of the Java virtual machine. However, if you are using libraries that also exist in the web application server classpath it is recommended using PARENT_LAST to avoid classloading conflicts.

Classpath Conflict Resolution

Similar to the problem of loading classes from the AuthEngine's classpath first vs. loading classes from the web application server's classpath first, different plugins may also produce library conflicts. Therefore, it is sometimes necessary to configure a classpath on the AuthState to avoid library dependency confusion. This will lead to a separate classloader being used for that AuthState (an AuthState classloader).

The problem can be illustrated as follows:

Imagine an AuthState A, which depends on library_v1 and an AuthState B, which depends on library_v2. If the libraries contain the same classes but implement different functionality or method signatures, nevisAuth may fail during runtime because AuthState A and B expect a different behavior of the library.

This can be solved by configuring a separate classloader per AuthState, as the following example shows:

<AuthState name="UseridPasswordState" class="ch.example.UseridPasswordFileAuthState"
classPath="/var/opt/nevisauth/default/plugin/auth-state-example-1.0-SNAPSHOT"
classLoadStrategy="PARENT_LAST">
<ResultCond name="ok" next="AuthDone"/>
<ResultCond name="failed" next="AuthError" />
<property name="passwordFileLocation" value="/var/opt/nevisauth/default/conf/passwords.txt"/>
</AuthState>

In this case, the ZIP archive auth-state-example-1.0-SNAPSHOT.zip containing the AuthState ch.example.UseridPasswordFileAuthState must be extracted into the directory /var/opt/default/plugin. Due to the PARENT_LAST class loading strategy, the directory /var/opt/nevisauth/default/plugin/auth-state-example-1.0-SNAPSHOT will be consulted first before checking the AuthEngine's classpath for loading classes.

Note that with some libraries you cannot have multiple jar entries on various classloading levels. (either the same or different version) Such example is the Slf4j API using log4j2 as implementation. Define such dependencies in your dependency list as provided.