One of the major features of Syncope 3.0 Maggiore is the new component Web Access (WA): let's understand how it works.
Syncope WA is based on Apereo CAS which allows WA to act as an identity provider and single sign-on manager using a variety of standard authentication protocols such as SAML2, OpenID Connect, etc. The general architecture of Syncope WA is as follows:
Syncope WA is tightly integrated with Syncope Core. Authentication modules, client application policies, and registration records are all managed by Syncope Core and stored in the underlying Syncope database. The configuration schema and authentication module structure follow a design language that Syncope itself can manage and present via REST APIs that allow CRUD operations on the data entities.
Syncope WA is also integrated with Syncope Console. Using the console, an administrator is given the ability to register or edit authentication modules, policies, register client applications and defined appropriate policies for each. The results are always stored and managed by Syncope Core, and can then be pushed onto the Syncope WA runtime.
In this post, we will explore these two key aspects of the Syncope WA architecture with a particular focus on authentication configuration.
Syncope WA presents the concept of an authentication module that generally represents a database, LDAP server or any other resource that maintains user accounts for authentication and login. For example, if we were to represent Syncope itself as an authentication module, a place where user account data can be found for authentication, this module is internally built using the following construct:
<AuthModule description="Syncope auth module" id="DefaultSyncopeAuthModule"
items="[...]"
jsonConf="{"_class":"org.apache.syncope.common.lib.auth.SyncopeAuthModuleConf","domain":"Master"}"
authModuleState="ACTIVE" />
The above XML snippet demonstrates the general strategy using which Apache Syncope boostraps its initial database content. This snippet when processed by Syncope eventually translates into a database row inside the Syncope database and ultimately translates into the following entry in the Syncope Console:
Each authentication module presents its own configuration schema that might describe specific authentication behavior. As another example, this is an authentication module that allows for multifactor authentication with Duo Security, and allows one to specify the details of the integration:
Just as before, this is internally translated to the following XML construct that Syncope can use during its own bootstrapping phase:
<AuthModule description="Duo Mfa auth module" id="DefaultDuoMfaAuthModule"
jsonConf="{"_class":"org.apache.syncope.common.lib.auth.DuoMfaAuthModuleConf","integrationKey":"DIOX...","secretKey":"Q2IU2i8BFNd6VYf...", "applicationKey":"u1IHBaREM...", "apiHost":"theapi.duosecurity.com"}"
authModuleState="ACTIVE"/>
Authentication modules are basic building blocks and by themselves are not applicable or useful yet. They need to be assigned to an application, and this is where we introduce the concept of Authentication Policy:
An authentication policy is a container of one or more authentication modules and just as before, may be interally represented using:
<AuthPolicy name="MyDefaultAuthPolicyConf" id="659b9906-4b6e-4bc0-aca0-6809dff346d4"
jsonConf="{"_class":"org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf","authModules":["DefaultSyncopeAuthModule"]}"/>
Once the authentication policy is ready, it can be assigned to a client application:
Just as before, our client application is registered with Syncope and may be internally represented using the following snippet for initial bootstrapping purposes:
<CASSPClientApp name="MyApplication" description="This is my client application"
id="01865ec4-c13e-7063-90f7-d46261f58ad8"
authPolicy_id="659b9906-4b6e-4bc0-aca0-6809dff346d4"
clientAppId="123456"
serviceId="https://app.example.org"
realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" properties="[]"/>
The key setting to note here is authPolicy_id
, which ties the client application and the authentication policy together.
So far, all authentication policies, modules and client application registration records are managed by Syncope Core. In this step, we are going to share and translate the configuration from the constructs that Syncope understands into a model that Syncope WA can understand. To do so, we need to take a step back first and understand the configuration strategy of Syncope WA or Apereo CAS itself.
Syncope WA, which is based on Apereo CAS, ultimately is a Spring Boot and Spring Cloud application. It packages a web application on top of several Apereo CAS modules that present features related to authentication MFA, application management, etc. In practice, this means that the configuration schema used by Syncope to manage applications and authentication policies needs to be translated into a language that Apereo CAS (Syncope WA) can understand and activate.
Rather than rewriting and redesigning the functionality of an identity provider from scratch, Syncope WA acts as a configuration management layer on top of CAS with a custom UI and bridges the component gap where necessary. For specific features of Apereo CAS that should prove useful to Syncope WA, it builds and injects its own implementation, logic and abstraction layers into the CAS runtime that provide a direct and native integration with Apache Syncope. To do so, Syncope WA during its configuration bootstrapping phase reaches out to Syncope Core via dedicated APIs to get the current state of the application, authentication modules, etc. This bootstrapping process then translates the current configuration state into a set of components and configuration properties that Syncope WA (Apereo CAS) can understand.
The bootstrapping process is somewhat tricky; as the name suggests, it's a process that kickstarts the application and executes at the very early stages of the WA initialization. After all, it must or otherwise, no component would be able to correctly initialize and continue. The bootstrapping process is ultimately modeled as a Spring Cloud PropertySourceLocator
, which then implies that once configuration is fetched and Syncope WA is bootstrapped and running, follow-up and all other subsequent changes need to be pushed again back to Syncope WA from Syncope Core.
The Push operation is a Syncope WA-specific feature that can be activated from the Syncope Console. You can see it here:
In practice, the push operation sends a Spring Cloud Refresh event to the running Syncope WA instance. The refresh operation allows for reloading the property sources in the WA runtime Environment
which ultimately might lead to the re-creation of certain WA components. One thing to note here is that the push and refresh operations do not immediately activate a feature or change; all they do at the time of execution is invalidate the current state of Spring-managed components and configuration. Components and configuration state is always re-created on demand, as a given feature or behavior is exercised.
Let's take an actual example to demonstrate the translation process. If you remember, our authentication module is taught to Syncope using the following XML snippet:
<AuthModule description="Syncope auth module" id="DefaultSyncopeAuthModule"
items="[...]"
jsonConf="{"_class":"org.apache.syncope.common.lib.auth.SyncopeAuthModuleConf","domain":"Master"}"
authModuleState="ACTIVE" />
When Syncope WA receives this word of this configuration entry from Syncope Core, (Note that of course, the XML above is only used for demonstration purposes and is not the real payload in transfer), it translates it to the following configuration settings that are understood by Apereo CAS:
cas.authn.attribute-repository.syncope.url=...
cas.authn.attribute-repository.syncope.domain=Master
# More to come...
In other words, Syncope Core is hydrating the CAS configuration properties and schema initially which then allows CAS-owned components to kickstart and continue.
One important note to include here is that the feature module/dependency itself must already be present and included in the Syncope WA bundle. The translation process can only have an impact, if there is some CAS component underneath that is tasked to read and react to those configuration settings, which means the Syncope WA packaging must surely include the relevant module that houses those components. Back to our example, this is handled using the following module that ships with Syncope WA:
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-syncope-authentication</artifactId>
</dependency>
The design choices that combine Syncope Core, Syncope Console and Syncope WA allow for a type of system architecture that is optimized for maximum reusability and decoupling of sub-systems. Each component is tasked to handle dedicated tasks and the overall integration strategy is one that attempts to bridge the gaps where necessary. The Syncope Core and Syncope Console allow WA to bootstrap correctly and present authentication and authorization features to the Apache Syncope portfolio.