Tag: authentication

Understanding the login process

As authentication is pretty much the core functionality of OpenAM, I believe it is helpful to have a good understanding of how it works really. For starters let’s have a look at the different concepts around authentication.

Authentication modules

Authentication modules are just a simple piece of functionality that is meant to identify the user by some means. Depending on your requirements an authentication module could verify user credentials, or perform some kind of two factor verification process. For more complex use-cases you could use the auth module to collect informations about the end-user and with the help of a fraud-detection system determine if the current login attempt is “risky”.

In any case, the authentication modules are performing some (customizable) logic, and at the end of the module processing you can either ignore the current authentication module (neither a success nor a failure), OR succeed with a logged in user, OR just simply fail (invalid credentials, etc).

The authentication module implementations are JAAS based (with some abstraction on top of plain JAAS), so it is all based on callbacks (think of callbacks as input fields) that needs to be “handled” and submitted. When the callbacks are submitted, the AMLoginModule’s #process gets invoked with the callbacks. This is the time when the authentication module can start to process the submitted data and determine if the authentication attempt was successful. Since an authentication process can involve multiple steps (more than one set of callbacks to submit: for example requesting username, and than some verification code), the #process method needs to return a number that represents the next state (there are special numbers like ISAuthConstants.LOGIN_SUCCEED that represent successful authentication result, i.e. no further need to present callbacks), which then will be used to determine the next set of callbacks to display on the UI. Assuming that the authentication finished successfully, we need to return the magic LOGIN_SUCCEED state.

So how does OpenAM really know who the user is?

Once the authentication is successful, the auth framework will call AMLoginModule#getPrincipal which needs to return the authenticated user’s principal. #getPrincipal has a key role in the authentication process, so make sure its implemented correctly (or when using built-in modules, make sure they are configured correctly).

Authentication chains

The next sensible building blocks are the authentication chains. The auth chains can be considered as combinations of various authentication modules to present a single authentication procedure for the end-users. Following the previous example, one could think that checking some verification code after providing a username and password may not be actually the job of a single authentication module, and probably should be implemented separately. In that case one could implement one module for username/password login, and then implement an another module for code verification. To make sure the user logs in using both auth modules, one could create an authentication chain that includes both of them, and then the user will just need to authenticate against that chain.

Since the modules are JAAS-based, it makes sense to set up the chain configurations similarly to JAAS as well, but I’m not going to go into too much details on that front, instead you should just read about JAAS a bit more (especially about the “flags”).

Profile lookup

Once the user has successfully authenticated, there is a thing called “profile lookup”. This bit is all about trying to find the logged in user in one of the configured data stores, and then ensure that the user-specific settings (things like custom idle/max timeout values, or session quota even) are all applied for the just-to-be-created session. There are other additional checks as well, like ensuring that the logged in user actually has an active status in the system (e.g. doesn’t have a locked account).

To make things a bit more clearer let’s talk about User Profile Mode now (Access controlrealmAuthenticationAll Core Settings). The user profile mode tells what should happen at the profile lookup stage of the authentication, and these are the possible modes:

  • Required – this is the default mode, which just means that the user profile MUST exist in the configured data store.
  • Ignored – the user profile does not have to exist, the user profile will not be looked up as part of the authentication process.
  • Dynamic – the profile will be looked up, but if it doesn’t already exist, it will be dynamically created in the data store.
  • Dynamic with User Alias – this is similar to Dynamic, but it also appears to store user alias attributes in the newly created entries (I must admit I don’t fully understand this mode yet).

I believe it is important to stop here a bit and emphasize the following:
The authentication module may interact with arbitrary external components during the authentication phase, however when it comes to profile lookup, that will be always performed against the configured data stores. If you are running into the infamous “User has no profile in this organization” error message, then that means, that the authentication was successful, but the profile lookup failed, since OpenAM was unable to find the user in the configured data stores.

The profile lookup itself is performed based on the return value of #getPrincipal, so this is why it is really important to ensure that the module works correctly. The returned principal can be simply a username like “helloworld”, but it can also have a DN format like “uid=helloworld,ou=people,dc=example,dc=com” (see LDAP module’s Return User DN to DataStore setting). When the returned value is a DN, then the RDN value will be used for the data store search (so helloworld), hence it is important to ensure that the data store has been configured to search users based on the attribute that is expected to have the value of helloworld.

The idea behind all of this is that in #getPrincipal the username returned should be unique across the user base, so even if let’s say you allow someone authenticating with “John Smith”, you should still return a bit more meaningful username (like jsmith123) to the backend. That way you can ensure that when you ask for “John Smith”‘s user details, you will get the right set of values.

Post authentication actions

After a successful profile lookup there are various additional things that OpenAM does, but I’m not really going to go into the nifty details for those. Here’s a small list of things that normally happens:

  • Check if user account is active.
  • Check if the account is locked (using OpenAM’s built-in Account Lockout feature).
  • Check if there are user-specific session settings configured for the user, and apply those values for the newly created session.
  • When the user session is created, check if the session quota has been exhausted and run the corresponding quota exhaustion action if yes.
  • Execute the Post Authentication Processing plugins.
  • Determine the user’s success login URL and also ensure that the goto URL is validated.

Summary

Whilst we only discussed portions of the actual authentication process, I think the main concepts for authentication are laid out, so hopefully when you need to configure OpenAM the next time around, you can reuse the things learned here. πŸ™‚

Certificate authentication over REST

A little bit of background

Amongst the various different authentication mechanisms that OpenAM supports, there is one particular module that always proves to be difficult to get correctly working: Client certificate authentication, or Certificate authentication module as defined in OpenAM. The setup is mainly complex due to the technology (SSL/TLS) itself, and quite frankly in most of the cases the plain concept of SSL is just simply not well understood by users.

Disclaimer: I have to admit I’m certainly not an expert on SSL, so I’m not going to deep dive into the details of how client certificate authentication itself works, instead, I’m just going to try to highlight the important bits that everyone should know who wants to set up a simple certificate based authentication.

The main thing to understand is that client cert authentication happens as part of the SSL handshake. That is it… It will NOT work if you access your site over HTTP. The authentication MUST happen at the network component that provides HTTPS for the end users.
Again, due to SSL’s complexity there are several possibilities: it could be that SSL is provided by the web container itself, but it is also possible that there is a network component (like a load balancer or a reverse proxy) where SSL is terminated. In the latter case it is quite a common thing for these components to embed the authenticated certificate in a request header for the underlying application (remember: the client cert authentication is part of the SSL handshake, so by the time OpenAM is hit, authentication WAS already performed by the container).

Now this is all nice, but how do you actually authenticate using your client certificate over REST?

Setting it all up

Now some of this stuff may look a bit familiar to you, but for the sake of simplicity let me repeat the exact steps of setting this up:

  • Go to Access Control – realm – Authentication page and Add a new Module Instance called cert with type Certificate
  • Open the Certificate module configuration, and make sure the LDAP Server Authentication User/Password settings are correct.
  • Generate a new self signed certificate by following this guide, but make sure that in the CSR you set the CN to “demo”. The resulting certificate and private key for me was client.crt and client.key respectively.
  • Create PKCS#12 keystore for the freshly generated private key and certificate:
    openssl pkcs12 -export -inkey client.key.org -in client.crt -out client.p12
  • Install the PKCS#12 keystore in your browser (Guide for Firefox)
  • Enable Client Authentication on the container. For example on Tomcat 7.0.53 you would have to edit conf/server.xml and set up the SSL connector like this:
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
     maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
     keystoreFile="/Users/aldaris/server.jks" keystorePass="changeit"
     truststoreFile="/Users/aldaris/trust.jks" truststorePass="changeit"
     clientAuth="true" sslProtocol="TLS" />
    
  • Add your user’s public certificate into the truststore (since the container performs the authentication, it needs to trust the client):
    keytool -import -keystore /Users/aldaris/trust.jks -file client.crt -alias demo

    In cases when the truststoreFile attribute is missing from the Connector settings, Tomcat by default falls back to the JVM’s truststore, so make sure you update the correct truststore.

  • Restart the container

Now if you did everything correctly, you should be able to go to /openam/UI/Login?module=cert and the browser should ask for the client certificate. After selecting the correct certificate you should get access to OpenAM right away.

It’s time to test it via REST

For my tests I’m going to use curl, I must say though that curl on OSX Mavericks (7.30) isn’t really capable to do client authentication, hence I would suggest installing curl from MacPorts (7.36) instead.
To perform the login via REST one would:

$ curl -X POST -v -k --cert-type pem --cert client.crt --key client.key.org "https://openam.example.com:8443/openam/json/authenticate?authIndexType=module&authIndexValue=cert"

And if you want to authenticate into a subrealm:

$ curl -X POST -v -k --cert-type pem --cert client.crt --key client.key.org "https://openam.example.com:8443/openam/json/subrealm/authenticate?authIndexType=module&authIndexValue=cert"

Simple as that. πŸ˜‰

Custom Auth module – Configuration basics

If you want to create a custom OpenAM auth module or a service, then you probably going to end up writing a configuration XML. This XML describes to OpenAM what kind of UI elements to render on the admin console, and what values should be stored in the configuration store for the given module.
Let’s take a look at the following sample XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ServicesConfiguration
PUBLIC "=//iPlanet//Service Management Services (SMS) 1.0 DTD//EN"
"jar://com/sun/identity/sm/sms.dtd">

<ServicesConfiguration>
    <Service name="sunAMAuthMyModuleService" version="1.0">
        <Schema
serviceHierarchy="/DSAMEConfig/authentication/sunAMAuthMyModuleService"
            i18nFileName="amAuthMyModule"
            revisionNumber="1"
            i18nKey="sunAMAuthMyModuleServiceDescription">

            <Organization>
                <AttributeSchema name="sunAMAuthMyModuleAuthLevel"
                                 type="single"
                                 syntax="number_range" rangeStart="0"
                                 rangeEnd="2147483647"
                                 i18nKey="a500">
                    <DefaultValues>
                        <Value>0</Value>
                    </DefaultValues>
                </AttributeSchema>

                <SubSchema name="serverconfig" inheritance="multiple">
                    <AttributeSchema name="sunAMAuthMyModuleAuthLevel"
                                     type="single"
                                     syntax="number_range" rangeStart="0"
                                     rangeEnd="2147483647"
                                     i18nKey="a500">
                        <DefaultValues>
                            <Value>0</Value>
                        </DefaultValues>
                    </AttributeSchema>
                </SubSchema>
            </Organization>
        </Schema>
    </Service>
</ServicesConfiguration>

What you should know about authentication module service XMLs:

  • According to this piece of code the service name HAS to start with either iPlanetAMAuth or sunAMAuth, and HAS to end with Service (like sunAMAuthMyModuleService in our case)
  • the serviceHierarchy attribute is /DSAMEConfig/authentication/<service-name>
  • in the i18nFileName attribute you need to add the name of a properties file, which is on OpenAM classpath (like openam.war!WEB-INF/classes). This internationalization file will be used by OpenAM to lookup the i18nKeys for the various items in the XML.
  • You should put the module options into an Organization Schema, this will make sure that the module will be configurable per realm.
  • All the attribute schema definitions should be also listed under a SubSchema element (this will allow you to set up two module instances based on the same module type with different configurations).

The AttributeSchema element contains informations about a single configuration item (what name should OpenAM use to store the parameter in the configstore, what kind of UI element needs to be rendered, what restrictions does the attribute have, etc).

Available types for an attribute:

  • single -> singlevalued attribute
  • list -> multivalued attribute
  • single_choice -> radio choice, only one selectable value
  • multiple_choice -> checkboxes, where multiple item could be selected
  • signature -> unknown, possibly not used
  • validator -> if you want to use a custom validator for your attribute, you need to include the validator itself (beware of OPENAM-974).

Available uitypes for an attribute:

  • radio -> radiobutton mostly for displaying yes-no selections
  • link -> this is going to be rendered as a link, where the href will be the value of the propertiesViewBeanURL attribute
  • button -> unknown, not used
  • name_value_list -> generates a table with add/delete buttons (see Globalization settings for example)
  • unorderedlist -> a multiple choice field in which you can dynamically add and remove values. The values are stored unordered.
  • orderedlist -> a multiple choice field in which you can dynamically add and remove values. The values are stored ordered.
  • maplist -> a multiple choice field in which you can add/remove key-value pairs
  • globalmaplist -> same as maplist, but it allows the key to be empty.
  • addremovelist -> basically a palette where you can select items from the left list and move them to the right list

Available syntaxes for an attribute:

  • boolean -> can be true or false
  • string -> any kind of string
  • paragraph -> multilined text
  • password -> this will tell the console, that it should mask the value, when it’s displayed
  • encrypted_password -> same as the password syntax
  • dn -> valid LDAP DN
  • email
  • url
  • numeric -> its value can only contain numbers
  • percent
  • number
  • decimal_number
  • number_range -> see rangeStart and rangeEnd attributes
  • decimal_range -> see rangeStart and rangeEnd attributes
  • xml
  • date

NOTE: Some of these syntaxes aren’t really used within the product, so choose it wisely.

Other than these, there is also the i18nKey attribute, which basically points to i18n keys in the referred i18nFile configured for the service. This is used when the config is displayed on the admin console.
This should cover the basics for authentication module service configuration I think. πŸ˜‰

Implementing remember me functionality – part 2

In my last post we were trying to use the built-in persistent cookie mechanisms to implement remember me functionality. This post tries to go beyond that, so we are going to implement our own persistent cookie solution using a custom authentication module and a post authentication processing hook. We need these hooks, because:

  • The authentication module verifies that the value of the persistent cookie is correct and figures out the username that the session should be created with.
  • The post authentication processing class makes sure that when an authentication attempt was successful a persistent cookie is created. Also it will clear the persistent cookie, when the user logs out.

In order to demonstrate this implementation, I’ve created a sample project on Github, so it’s easier to explain, the full source is available at:
https://github.com/aldaris/openam-extensions/tree/master/rememberme-auth-module
You most likely want to open up the source files as I’m going through them in order to see what I’m referring to. πŸ˜‰

Let’s start with the Post Authentication Processing (PAP) class, as that is the one that actually creates the persistent cookie. In the PAP onLoginSuccess method, I’m checking first whether the request is available (for REST/ClientSDK authentications it might not be!), then I try to retrieve the “pCookie” cookie from the request. If the cookie is not present in the request, then I start to create a string, that holds the following informations:

  • username – good to know who the user actually is
  • realm – in which realm did the user actually authenticate (to prevent accepting persistence cookies created for users in other realms)
  • current time – the current timestamp to make the content a bit more dynamic, and also it gives a mean to make sure that an expired cookie cannot be used to reauthenticate

After constructing such a cookie (separator is ‘%’), I encrypt the whole content using OpenAM’s symmetric key and create the cookie for all the configured domains. The created cookie will follow the cookie security settings, so if you’ve enabled Secure/HttpOnly cookies, then the created cookie will adhere these settings as well.
In the onLogout method of the PAP I make sure that the persistent cookie gets cleared, so this way logged out users will truly get logged out.

On the other hand the authentication module’s job is to figure out whether the incoming request contains an already existing “pCookie”, and if yes, whether the value is valid. In order to do that, again, we check whether the request is available, then try to retrieve the cookie. If there is no cookie, then there is nothing to talk about, otherwise we will decrypt the cookie value using OpenAM’s symmetric key.
The decrypted value then will be tokenized based on the “%” character, then we first check whether the current realm matches with the cookie’s realm. If yes, then we check for the validity interval and the stored timestamp. If things don’t add up, then this is still a failed authentication attempt. However if everything is alright, then we can safely say that the user is authenticated, and the username is coming from the decrypted content.
In case there was some issue with the cookie, then we will just simply remove the “pCookie”, so hopefully we won’t run into it again.

Limitations

There are a couple of limitations with this example module though:

  • when the PAP is part of the authentication process, it will always create a persistent cookie for every single user (but only when the cookie don’t already exist).
  • the validity interval and the cookie name is hardcoded, moreover every single realm will use the same cookie, that can be a problem in certain deployments.

If you are looking for installation details, then check out the Github project README πŸ˜‰

Implementing remember me functionality – part 1

It’s quite common requirement to have long running sessions within OpenAM, so I’m going to try to enumerate the different ways to achieve “persistent” sessions and provide some comparison.
There is two main way to achieve long running sessions:

  • Using built-in functionality
  • Implementing custom authentication module + post processing class

Today we are only going to deal with the built-in persistent cookie features, the next article will describe the more user-specific solution.

Setting Expires attribute on session cookie

By default OpenAM issues session cookies without Expires attribute, meaning the cookie is only stored until the browser is stopped/restarted. This solution is especially handy if you have large session timeout values set, because in any other cases your session cookie would be saved in the browser for a good while, but the underlying session could have already time out.
Now there are two ways to enable this mode:

  • Enable persistent cookies globally for all sessions:
    Go to Configuration -> Servers and Sites -> Default Server Config -> Advanced tab, then add the following properties:

    openam.session.persist_am_cookie=true
    com.iplanet.am.cookie.timeToLive=100
    
  • After doing so you will probably need to restart the container for the changes to take effect. Any new sessions created afterwards will set the Expires attribute on the session cookie.
    When using DAS you need to set these properties in the DAS configuration file instead.

  • Allow to have persistent sessions on-demand:
    Go to Configuration -> Servers and Sites -> Default Server Config -> Advanced tab, then add the following properties:

    openam.session.allow_persist_am_cookie=true
    com.iplanet.am.cookie.timeToLive=100
    

    In this case to get a persistent cookie you need to include the openam.session.persist_am_cookie=true parameter on the Login URL (so you can’t actually put this on the Login form unfortunately)

  • When using DAS you need to set these properties in the DAS configuration file instead.

NOTE: the timeToLive value is in minutes.
NOTE 2: these properties only fully work on the core servers if you have OPENAM-1280 integrated, but if you use DAS these should work just fine.
NOTE 3: the timeToLive value only tells how long the cookie should be stored by the browser, it has absolutely NO influence to the actual session timeout intervals.

Creating a long living non-session cookie

When using this option OpenAM will create a second “DProPCookie” cookie next to the iPlanetDirectoryPro cookie with an encrypted content. This encrypted cookie stores a set of informations that are necessary to “recreate” a session when a user goes to OpenAM without a valid session cookie, but with a valid persistent cookie. OpenAM then decrypts the cookie and based on the stored information, it will create a new session.
In order to enable this persistent cookie mode you need to go to Access Control -> realm -> Authentication -> All Core Settings page and do the followings:

  • Enable the “Persistent Cookie Mode” option
  • Set “Persistent Cookie Maximum Time” option

After this when you include the “iPSPCookie=Yes” parameter on the login URL, or you have an actual checkbox on your Login.jsp submitting the exact same parameter during login, OpenAM will issue the DProPCookie persistent cookie with the configured timeout.
This method does not seem to be implemented for DAS.
NOTE: OpenAM will delete the persistent cookie as well, when the user logs out.
NOTE 2: due to a possible bug (OPENAM-1777) OpenAM may not invoke Post Authentication Processing classes when it recreates the user session.

Conclusion

As you probably noticed, the Expires on session cookie method is only really useful when you have large timeouts, also it is a global option, meaning that once you enable it, it will be set for all the different realms.
On the other hand DProPCookie is configurable per realm, but it does not seem to work when using DAS.

That’s all folks, this is how the built-in persistent cookies work, if these do not seem to match your requirements, then stay tuned for the next post.

How to use Certificate module with DAS

Previously I have described how to install the DAS properly. Today’s entry is all about using the Certificate authentication module in a deployment where you have a DAS instance. So here are the steps required to make this work:

  • Follow the DAS install guide, but with the only difference being that you install the DAS on a HTTPS URL (OpenAM can keep running on HTTP). Since you are now using HTTPS, you need to make sure that the OpenAM server trusts the DAS’s certificate, otherwise OpenAM won’t be able to send notifications to the DAS, which could result in strange situations when a given session remains valid for a short period of time even though the user has logged out on a different DAS instance.
  • Go to Access Control – realm – Authentication page and Add a new Module Instance called cert with type Certificate
  • Open the Certificate module configuration, and change the followings:
    • Set the LDAP Server Authentication User/Password to correct values
    • For evaluation purposes set the Trusted Remote Hosts to “all”
  • Generate a new self signed certificate by following this guide, but make sure that in the CSR you set the CN to “demo”.
  • Create PKCS#12 keystore for the freshly generated private key and certificate:
    openssl pkcs12 -export -inkey server.key.org -in server.crt -out server.p12
  • Install the PKCS#12 keystore in your browser (Guide for Firefox)
  • Enable Client Authentication on the DAS’s container. For example on GlassFish 3.1.2 Admin Console you would have to go to Configurationsserver-configHTTP serviceHttp Listenershttp-listener-2 then open the SSL tab and check the Client Authentication option.
  • Install the public certificate into the container’s truststore, so the container will actually trust your certificate:
    keytool -import -keystore glassfish3/glassfish/domains/domain2/config/cacerts.jks -file server.crt -alias mycert

    You need to make sure that you install the certificate to the actually used truststore, some containers may use the JVM’s truststore instead having one on their own.

  • On the DAS enable the Request/Response serialization by setting the following property in the ~/FAMDistAuth/*.properties file:
    openam.remoteauth.include.reqres=true
  • Restart the DAS’s container
  • Open /auth/UI/Login?module=cert and choose your certificate
  • Profit

How to set up multiple DAUI instances

Let’s start at the beginning: what is the DAUI exactly?

The DAUI (Distributive Authentication User Interface) is basically a small subset of the OpenAM server UI containing simple login logic, which basically just receives authentication requests from the users and forwards those requests to the core OpenAM servers. For this the DAUI is using the ClientSDK, especially the underlying JAX-RPC interfaces. Now that we know this, let’s see the pros and cons for using DAUI.

Advantages:

  • Hides sensitive parts of the OpenAM server
  • Lowers the load on the actual core servers

Disadventages:

  • Adds one more component which could break
  • Has no federation capability

How to set up a DAUI instance

This tutorial requires that you have an OpenAM instance already deployed and configured on your favorite application server. If you’re not sure how to do that, please read Mark’s great article about it.
In order to install a DAUI instance you’re going to need to take the following steps:

  • Download the OpenAM zip distribution from the OpenAM download page and extract into ~/install directory.
  • Execute the following commands:
    cd ~/install/deployable-war
    mkdir temp # Create a temporary directory
    cp openam.war temp # Copy the WAR file into it
    cd temp
    jar xf openam.war # Extract the content of the WAR file
    rm openam.war # Remove the WAR file
    cd ..
    chmod +x createwar.sh # Add execution permission to the script
    ./createwar.sh -s temp -t distauth -w auth.war # Create a distauth war named auth.war based on the temp folders content
    
  • Deploy the auth.war onto a different application server than OpenAM is deployed.
  • Log on the admin console and go to Access Control -> / (Top Level Realm) -> Authentication -> 2.2 Agents then click on the New button. Create an agent user (you should use the same credentials on the DAUI config screen).
  • Open daui.example.com:8080/auth in your browser, where you should see a configuration screen.
  • Configure the DAUI instance parameters:
    Server Protocol http or https
    Server Host openam.example.com
    Server Port 8080
    Server Deployment URI /openam
    DistAuth Cookie Name AMDistAuthCookie – this cookie tracks which DAUI server the user belongs to
    OpenAM LB Cookie Name amlbcookie – this cookie tracks which AM server the user belongs to
    DistAuth LB Cookie Name DistAuthLBCookieName – additional cookie for LB routing purposes
    DistAuth LB Cookie Value DistAuthLBCookieValue – should be different for each DAUI server
    Debug directory /opts/openam/debug – where to store the debug logs
    Debug level off, message, warning or error
    Encryption Key This symmetric key to be used for passwordencryption
    Application user name An agent user
    Application user password Password for the agent user

    At the end click on the Configure button.

  • If you try now to follow the login link, then it is very likely that you’re going to see a No such Organization found. error message. This happens, because OpenAM does not recognize the daui.example.com as a valid domain. To solve this you need to add the DAUI URL to the Realm/DNS Aliases list by going to Access Control -> Realm -> General tab. The DNS alias will bind itself to the given realm, so usually the Top level realm is the best place to configure this.
    You only need to set the DNS Aliases for externally accessible URLs.
  • After setting up the DNS Alias the error message should disappear, so there is only one caveat left: on the Configuration -> System -> Platform page you have to make sure that the Cookie domain list contains all or part of the DAUI’s FQDN. If this is not the case the DAUI login page will not give access, and every time the form is submitted it will just render the first login page again.

After setting up the first DAUI instance setting up the second instance is a piece of cake. πŸ™‚ Just follow the previous steps and you should be OK. However if you cannot implement sticky loadbalancing, then you can see a weird error message saying: http://daui2.example.com:8080/auth/UI/Login is not the trusted server. Internally the DAUI servers needs to know about each other, so they can safely forward authentication requests from one server to another.

How does the authentication request forwarding work?

Basically when you open the Login page your browser will store the AMDistAuthCookie identifying the DAUI server. When a subsequent request goes to a different server, DAUI will first check whether it can trust the server (value of the AMDistAuthCookie), then it will actually forward the request and render the response to the user. Such trust between the DAUI servers can be created by setting the following property in the DAUI configuration files (under ~/FAMDistAuth):

com.sun.identity.distauth.cluster=http://daui.example.com:8080/auth/UI/Login,http://daui2.example.com:8080/auth/UI/Login

Restart your servers and off you go. πŸ˜‰

How to develop custom auth module

NOTE: if you’re looking for a quick way to learn how to develop auth modules, then you may want to read this or this instead.

In the OpenAM world an authentication module is responsible for authenticating a user, but sometimes the method of authentication is not that simple, as we think. For example the OpenAM gives out-of-the-box support for LDAP, Cert, SPNEGO token, etc. based authentication, but what happens if you need to authenticate (for some reason) from a WebService, this is when you’re probably going to end up developing a custom authentication module.

OpenAM is using JAAS, so if you don’t know what JAAS is, probably you need to read this, this is going to help you understand the basic concepts of the Auth API.

To create an authentication module, you’re going to need the followings:

  • Configuration-UI descriptor XML with localization
  • Callback-descriptor XML for login page UI
  • Some java code for authentication logic
  • maybe some JSP
  • and lot’s of lot’s of OpenAM container restarts πŸ™‚

So based on these needs I’m going to write a few more posts in this area, probably in the following structure:

  • Configuration basics
    • Config UI elements
    • Validation of configuration
  • Login UI basics
    • Callbacks
    • Dynamic Callback-handling
  • How to write the Java code
  • Gotcha’s, best practices
  • How to install auth module

I hope you will find these articles useful, some of them are new stuff for me too, so it may going to need some time to write them, but they’re going to (Forge)ROCK! πŸ˜€