Table of Contents
As you may have gleaned from the getting started guide, the Curity Identity Server is comprised of three separate parts:
The first two are controlled through the idsvr command while the third is a separate process that is started automatically and supervised by the first. When the admin node is not also a run-time node, all it does is monitor and manage the configuration service; it does not expose any endpoints or listening ports. The configuration service that it spawns, however, exposes a number of northbound endpoints that are used to configure all nodes:
When a run-time node (or an admin node that also services request, as described in the getting started guide) starts, it immediately subscribes for configuration changes that relate to it (which is why it must identify itself in the startup.properties or on the command line). Whenever one of these northbound APIs is used to change configuration related to a run-time node, the new configuration will be pushed (not pulled using a polling process) to the appropriate run-time node. Without any downtime, the node is reconfigured and all new requests will use the new configuration while old requests finish using the previous configuration. This dynamic configurability of run-time nodes allows administrators to mange the entire deployment as a whole and from a single point. From this central position, administrators can view, update, rollback, version control, and restore old configuration. All changes to configuration are done in a single transaction, allowing administrators to make several (dozens or even 100s of changes) and commit them all as a whole (at a scheduled time perhaps). In the walkthrough, you will see how this can be done with ease.
Based on this configuration, every run-time instance of the Curity Identity Server will assume a certain role within Identity Management System (IMS). The possible roles include:
A Security Token Server is essential for providing both Web application and Web service security. To meet the need for mobile experiences and to facilitate microservices architectures, Web services or Web Application Programming Interfaces (APIs) are essential. To provide access via these networked endpoints, the service must reliably know who is at the other end of the wire. To this end, the Curity Security Token Server issues tokens that represent an end user after he or she has authenticated themselves. The Curity Security Token Server does not actually perform the authentication – a task left to an Authentication Server; instead, it exchanges this initial identity for a new one encoded in the form of a signed token. This token delivered to apps via the OAuth and OIDC standards. One the app obtains such a token, it can make secure API calls with them. By so doing, the API will verify the authenticity and trustworthiness of the token and grant access to the data if the user is authorized.
The Curity Security Token Server provides a number of features that you would expect from any Security Token Server which supports OAuth and OIDC. For example, the Curity Security Token Server support all of the standard OAuth flows (e.g., the implicit, resource owner credentials, and authorization code flows); it also supports lesser-known flows like the assisted token flow and the device flow. The former is a simplification of the implicit flow and greatly simplifies integration while simultaneously making the app integration more secure. These various flows or message exchange patterns can be implemented using various open and closed source frameworks, making it easy to retrieve tokens from the Curity Security Token Server.
While the Curity Authentication Server allows users to register for new accounts during authentication, organizations often need to provide users with a means to manage their profile outside of the login process. To this end, the Curity Profile Server provides profile management as a Web service API (which is protected by tokens issued by the Curity Security Token Server). The API itself conforms to the SCIM protocol, a standard specified by the IETF which is the same international standards body that also authored the OAuth, TLS, and HTTP standards. This API provides the ability to modify users, facilitating basic Create, Read, Update, and Delete (CRUD) operations. As with the other roles of the Curity Identity Server, the Curity Profile Server does not house or store any identities. Instead, the Curity Profile Server can be configured to use various identity repositories. These can include Relational Database Systems (RDBMS), other SCIM services (e.g., Windows Azure Active Directory), and LDAP (e.g., Active Directory). A growing list of RDBMS are supported, including HSQL (for testing and development), MariaDB (e.g., as provided by Amazon RDS), MySQL, SQL Server, Postgres, Oracle and CockroachDB. The API also makes it easy to integrate user management capabilities into existing web sites, Customer Relationship Management (CRM) systems, and customer care portals where Customer Service Representatives (CSRs) need to make changes on a user’s behalf.
Based on configuration, a run-time node will assume one or more of the above roles. Each of these roles and the related configuration is stipulated in what is referred to as a profile. A profile is a central concept to the Curity Identity Server. It is essentially an instance of an Authentication Server, a Security Token Server or a Profile Server. Multiple profile instances can be configured of the same type. For example, you can create an Security Token Server profile for employees that has different client applications than a profile that should only be used with customers. You could also create an Authentication Server profile that only allows for login to one particular app using one particular authentication method; you could then make this restricted profile available to a certain partner that uses this single app. Each profile not only contains the apps (or clients or service providers) that should use it, but also the server on which the profile is executed. Each profile contains a set of endpoints; these endpoints can be completely arbitrary, allowing an OAuth Security Token Server profile to serve tokens from /zort and an Authentication Server profile to authenticate users from /foo. This and the ability to designate profiles to certain servers makes it very easy to limit and obfuscate the endpoints as needed to meet certain situations. For example, in the previously mentioned example with a partner that should only be able to login to a certain app with a particular authentication method. If this app was integrated using OpenID Connect, then two profiles would be created – an authentication profile and an token service profile. Both of these profiles could be assigned to a server called partners.example.com. The endpoints might all be prefixed with the partner name, resulting in endpoints like https://partners.example.com/partner1/authenticate, https://partners.example.com/partner1/token and https://partners.example.com/partner1/authorize. For more background information on this topic, refer to the tutorial about endpoints on the developer portal.
In this way, profiles are used in the Curity Identity Server to wrap configuration together into a unit. This unit is also what is used at runtime to decide which components should be used to handle the request.
Architecturally speaking, the Curity Identity Server is made up of a number of pluggable components. The engine itself is relatively small, and, based on a node’s centrally-defined configuration, certain plug-ins are loaded and used to handle requests made to each particular node. It is important to understand what kind of plug-ins exists and how they fit together, as this will provide an good overview of the product’s capabilities. The supported types of plug-ins include the following:
Using these plug-ins together, many scenarios can be implemented. Almost all of these involve authentication in some way, so it good to acquaint yourself with the authentication capabilities of the Curity Identity Server.
Authentication is a really big part of any IMS, perhaps the biggest. Authentication is the process of confirming the identity of some entity. In other words, it is the task of answer the question “Who are you?” How this determination is done varies widely. In the Curity Identity Server, there are two general authentication use cases:
As the worth of the data that a user is trying to access increases, so does the risk associated with misidentifying that user or authenticating them incorrectly. If the value of the requested resource is very low, getting a right answer to the question “who are you?” is not as important as when the resource is very valuable. Therefore, the accuracy of the authentication method or the strength of the credential that is used to authenticate a user will be proportional to the value of the resource. It may be OK for a low-value resource to be accessed after authenticating a user with a very strong credential, but the converse is almost never the case; granting access to high-worth data after a user logs in with a very weak credential exposes your organization to risk. It is important, therefore, that users authenticate themselves using the right methods under the right circumstances.
Curity Identity Server vs. Curity Authentication Server
The Curity Authentication Server is the profile of the Curity Identity Server that does advanced authentication. The Curity Security Token Server and the Curity Profile Server can be used without the Curity Authentication Server, but all of the advanced authentication capabilities described in this section are only possible if the authentication profile of the product is used.
To this end, the Curity Identity Server provides a number of options for login, and a number of ways to select and control these choices. Most of them relate to the first case mentioned above when the user is directly involved; this is due to the dynamism of such interactions. For example, the Curity Authentication Server provides numerous Authenticators; all of these can be configured and used or, more typically, a subset of them can be setup. Just because some are configured, however, doesn’t mean that they should all be available in every situation. As described above, it is very common to restrict certain Authenticators based on the application that is requesting authentication. Take, for example, an intranet Web site. For such an app, the only authentication method that should be allowed is Integrated Windows Authentication (IWA) when the user is on the local network. In such cases, the user is known to have logged in to their workstation with a corporate account because only domain-joined PCs can connect to the local network. Under such circumstances, it is not necessary and quite annoying for the user to have to authenticate them self again. By configuring an instance of the IWA Authenticator and allowing this intranet app to use it (via configuration), employees on the network will receive a better user experience.
When such personnel take their laptops home, however, they may not be on the same network, preventing IWA from working. In such cases, it is usual for the employee to be prompted to enter their AD credentials into a Web-based form as well as a second factor of authentication using a hardware token, software token, or by entering a one-time code sent to them via SMS. The Curity Authentication Server can easily implement this use case. To do this, you should configure an Authenticator for the second factor, like SMS 2-FA Authenticator. As with all Authenticators, this one can require a previous Authenticator to run first. This could be an instance of HTML form Authenticator, for instance. The HTML form Authenticator needs an Account Manager to be configured. This Account Manager in turn needs a Data Source. If that Data Source is an LDAP one that is configured to communicate with AD, home workers will firstly be prompted to enter their AD credentials in a Web form, and then receive an SMS with a one-time usage code. The phone number to which this code is sent can be looked up in AD, but it can also be found in a different Data Source, like a RDBMS, because the Data Source of the two Authenticators are configured independently, enabling both simple and advanced implementations of this use case.
In this example, the intranet app uses three Authenticators: IWA, SMS 2FA, and an HTML form Authenticator. Because the SMS 2FA Authenticator instance requires the HTML form Authenticator instance to run first, they will manifest themselves as two choices to the user:
Fig. 2 Authenticator selection page using default styling
This type of Authenticator selector page is always shown to the user when multiple Authenticators are configured and there is not enough inputs in the request to narrow down the selection to just one. If only one Authenticator is configured or the inputs are given to reduce the number of selections to just one, the user will not see this screen. While the above screenshot shows how this page would normally look, it is possible to change the appearance for all apps or even just this intranet app. Rather than customizing it, however, it would be better in this use case if it were not shown at all. The easiest way to do this in this case would be to use an Authenticator Filter. The Curity Authentication Server includes an Authenticator Filter that can filter out Authenticators based on the IP address of the client. If the client’s IP address is not one from the local intranet, the Classless Inter-Domain Routing (CIDR) Authenticator Filter can be used to remove the IWA Authenticator. After which, the user will not see the authenticator selector page because the number of allowed Authenticators has been slimmed down to just one. Instead, the user will be prompted with an HTML form where they can enter their AD credentials:
Fig. 3 HTML Authenticator that is automatically show
Likewise, another instance of the CIDR Authenticator Filter can be used to determine if the user is within the corporate network. If they are, the HTML form Authenticator can be filtered out, thus reducing the number of allowed Authenticators to just one – the IWA Authenticator instance. Then, the Authenticator selector screen will not be shown, and IWA will log the user in directly without any prompt.
Usually, the Curity Identity Server will be used with a number of different applications. While this fictitious intranet application requires these types of authentication, they probably aren’t applicable for an application used by end customers. Imagine an organization’s web site. Imagine it requires users to login under certain circumstances. When a prospective customer visits the Web site, they can probably visit a lot of the site anonymously. Under certain circumstances, some form of identification might be needed. For example, if the prospective customer signs up for a new letter, or coupons, or other low-value resources, a simple username/password might be acceptable. Because users often reuse these credentials across sites, it might be more secure and easier for the user to let them login with their Google or Facebook account. For such an application, the allowed Authenticators would be instances of the Facebook, Google Authenticator, and the HTML form Authenticator (but a different instance then the one used with the intranet app). In this case, the user would be presented with three login options when they visit this app without a session:
Fig. 4 Alternative Authenticator selection page
Because this is a different app requesting login, the authentication methods that are available to the user are not the same ones from that of the fictitious intranet application. (They of course could be if so configured, but this isn’t a plausible setup.)
In the examples above, you may be wondering how the Curity Authentication Server determined which authentication methods to present to the user. It is done by an application identifier that is provided in the request, typically on the query string. What is stopping the user from changing that, you may now wonder? Nothing! How then will the app know that its authentication requirements were met? In those cases where the actual authentication method that was used must be made know to the application, the Curity Identity Server provides this information is what is know as an Authentication Class context Reference (ACR). An ACR is provided in the login token issued by the Curity Authentication Server and can also be included in tokens issued by the Curity Security Token Server. Sometimes tokens will be issued by the Curity Security Token Server hours, days or even weeks after the user logged in. Even in such cases, the original authentication method that was used can be determined by the application using the ARC in the token. (The authentication time can also be determined from information in the token.) This allows the application to decide if a newer, fresher authentication of the end user is needed.
Application often need a way to inform the Curity Identity Server about their requirements that a user authenticates using a certain methods, a particular Authenticator. This is also done using ACRs. In the request that an application sends to the Curity Identity Server is may include this information. This set of ACRs must correspond to a subset of the configured Authenticators that are allowed for the application. An ACR that corresponds to any unknown or disallowed Authenticator will be ignored. In any event, the Authenticator that is used will be communicated back to the application in the ACR of the token. This will allow the app to check that its authentication requirements were satisfied. Using the ACR like this is how things like step-up authentication can be implemented in the Curity Identity Server.
By default, an ACR has a standard format:
This value can be changed per Authenticator to whatever string value is desired.
Every script is given a run-time context. This context contains information about the calling client, the request parameters, the configured data sources and Authorization Managers, the configured token issuers, and other things. Each script can also use globally defined scripts that allow you create reusable libraries of functions. All scripts have access to a console object that can log information at run time which is logged in the regular server log; logging can be enabled or disabled for certain scripts or for all. To enable logging for a certain script only, a logger named se.curity.identityserver.scripting.token_procedure.<procedure-name> (where <procedure-name> is the ID of the script) should be configured in the log4j2.xml file located in $IDSVR_HOME/etc. To enable logging for all scripts, including global ones, a logger named se.curity.identityserver.scripting.token_procedure should be enabled at the DEBUG level.
Scripts are configuration like any other setting. When an administrator enters a script using any of the northbound APIs described above, they are validated. Only if the script parses will it be accepted as valid configuration data. If it does, it will be replicated to the appropriate run-time which will pre-compile it into byte code before making use of it. This ensures that the script is correct and optimized before it is used to service any requests.
For more information on scripting, refer to the scripting guide.
There are many more concepts that you will need to learn about, like SSO, the types of tokens, various flows, etc. These will be covered in the various guides included with this overview guide. Refer to them for more details or walkthrough some common scenarios to gain some first hand experience with these concepts.