OpenAM: Forcing users to reset password on next login.

Overview

A very common use case, when implementing ForgeRock’s OpenAM, is forcing a user to reset their password the next time they login. Seems easy enough right? … next time a particular user authenticates in they should be prompted to change their password before continuing on to the resource (web page) that they had originally requested.

The documentation does mention a setting, in section 8.3, to enable this:

Force Change Password on Next Login

When enabled, the user must change her password next time she logs in after OpenAM resets her password.

 

Unfortunately, this doesn’t seem to work. Doing a little “googling” you can find there is an open bug on this.

There are several places online where ForgeRock’s Peter Major (aka @aldaris) recommends implementing this at the directory server layer instead. This is pretty easy to implement if you are using OpenDJ as your user identity repository.

I am going to explain how to configure this here:

OpenAM

In OpenAM your authenication module needs to be set to LDAP instead of DataStore. The default ldapService authentication module uses the DataStore authentication module, which does not support forcing a user to reset their password. Instead you shoud create a new authentication chain which uses LDAP as the authentication module.

Note
: I am assuming that your LDAP authentication module is configured to use an OpenDJ instance.

OpenDJ

There are two settings in OpenDJ which need to be enabled.

  1. Modify the Password Policy to enforce Password Reset on Next Login
  2. Enable pwdReset attribute on the user’s record

Modify the Password Policy:
Using OpenDJ’s dsconfig command line tool you can edit the user’s password policy to enable the Password Reset settings. In this example the user’s password policy is the Default Password Policy. Change the setting force-change-on-reset from false to true. (Note: in production you probably would have created a different policy and wouldn’t be using the default policy)

Enable pwdReset attribute on the user’s record:
This setting can be changed either via an ldap browser, command line (ldapmodify) or even by using a provisioning tool like OpenIDM. Keep in mind that this is considered an operational attribute so you’ll need to ensure that you have permission to change the value.

Note: The embedded OpenDJ instance that comes with OpenAM is configured to prevent a user from changing their password so you will likely run into errors unless you have modified the ACI. It’s actually not recommended to use the embedded OpenDJ instance as a user identity store, in production. So, use an external instance of OpenDJ and you’ll be fine.

So, let’s see this in action:

by the way … this works just fine using the XUI as well:

Wrap up

So, we’ve demonstrated how easy it is to implement the force password reset on next login functionality. We’ve validated that this approach works whether you are using the legacy UI or the new modern XUI.

Don’t hesitate to reach out if you have any questions. If you need help implementing OpenAM or any other product’s in ForgeRock’s Open Identity Suite drop us a line through our contact page.

#ForgeRock: Using #OpenIDM to sync Account Lockout Status #IDM

Use Case:

In an enterprise setup you would likely want to know when a user has locked their account (e.g. too many failed password attempts) and more than likely want to distribute that information to other systems in your environment. One solution would be to enable OpenIDM to monitor the user identity repository for changes to the user’s status.

This post will demonstrate one possible configuration for this use case.

Starting out with a typical ForgeRock set up … OpenIDM to provision and synchronize users, OpenAM to manage access and OpenDJ and the configuraton and user data store.


Assumptions:

  • OpenDJ is already Installed ( or you plan to use the OpenAM’s embedded directory store )
  • OpenAM is already configured to use OpenDJ as it’s configuration store and user identity store
  • OpenIDM is already installed (and using OrientDB as the repo DB)
  • The OrientDB console has been installed (not part of the ForgeRock software stack)

Steps to Configure:

OpenDJ:

  • Modify the Default Password Policy (using OpenDJ’s dsconfig tool)
    • Set the # of Password Failures before Lockout

  • Enable Change Logs (by enabling replication)
    • Using OpenDJ’s ./dsconfig tool
      • Create a replication server
      • Create a replication domain

OpenIDM

  • Create a connector to OpenDJ

  • Create an OpenIDM to OpenDJ Mapping

 

  • Create an OpenDJ to OpenIDM Mapping


Testing

First Lock the Account by failing the login. I am using the REST API but this can be done via the OpenAM UI as well.

 

Once the account is locked, verify that the attribute (pwdAccountLockedTime) now has a date time stamp as a value.

 

Now, verify that the OpenIDM repostitory has been updated with the same value.

 

Unlocking the Account

Unlocking the account is as simple as changing the password in OpenAM. Once you change the password you should be able to repeat the Testing steps to ensure that the pwdAccountLockedTime attribute has been returned to null.

Next Steps

Now that the pwdAccountLockedTime attribute is syncing between OpenDJ and OpenIDM you can take the next steps and have OpenIDM syncronize the changed value out to other systems as well.

Give us a call if you need help implementing this use case or any other similar use cases.

Disclaimers:

  • OrientDB is not supported by ForgeRock for production installs
  • Whether you use the embedded OpenDJ as part of your architecture would depend on your performance and scalability requirements.
  • This particular architecture is for demo purposes and may not be suitable for your specific requirements.  Give us a call if you need assistance in designing an appropriate architecture for your specific requirements.

LDAP Command Line Cheat #OpenDJ

I use the command line a lot when interfacing with OpenDJ. One of the issues with this is that I often run into an issue with the BindDN user’s password has an “!” (bang) in it. As this is a special character in Unix/Linux command line, it will typically cause unexpected results.

With ldapsearch you can just leave the password paramater off and you will be prompted to provide the password. I have found that this is not the case with ldapmodify and ldapdelete. So, this can be problematic when trying to delete a user’s record.

Another work-around is to set up a tools.properties file in your user’s home directory. So, if you typically run these commands as a user named “opendj” then you would create the following file, in the opendj user’s home directory:

~/.opendj/tools.properties
hostname=directory.example.com
port=1389
bindDN=uid=kvaughn,ou=People,dc=example,dc=com
ldapcompare.port=1389
ldapdelete.port=1389
ldapmodify.port=1389
ldappasswordmodify.port=1389
ldapsearch.port=1389

So, then to delete a user:

Create an ldif file containing the user’s DN and the change type:

ex. vi deleuser.ldif
dn: uid=newuser,ou=People,dc=example,dc=com
changetype: delete

Then run the ldapmodify command:

$ldapmodify -p 1389 -f deluser.ldif

You will be prompted for the password which you can type in and not worry about any conflicts with the OS command line.

OpenIDM: Implementing a custom password policy

OpenIDM 3.1 comes with several password policies enabled by default.  There are often times when you will need to implement additional policies or even modify or extend existing policies.  This is a quick guide that will walk you through the basics of implementing your own password policies.

Let’s talk a little bit about what’s there by default.

Policies are enabled in the openidm/conf/policy.json file.  This file is organized by resources (e.g. managed/user, internal/user, etc).  Each resource in turn has a properties section in which policies are defined for a specific attribute (e.g. userName, password, email, etc).

Here is an example:

The policies that are reference in policy.json are actually defined in:  openidm/bin/defaults/script/policy.js

policy.js looks something like this:

 “policies” : [

        {   “policyId” : “required”,

            “policyExec” : “required”,

            “clientValidation”: true,

            “policyRequirements” : [“REQUIRED”]

        },

 policyFunctions.required = function(fullObject, value, params, propName) {

        if (value === undefined) {

            return [ { “policyRequirement” : “REQUIRED” } ];

        }

        return [];

    };

I wouldn’t make changes directly to policy.js as these changes could get overwritten by an updated from ForgeRock.  

So, now to implement your own policies … let’s add in a policy that will enforce a maximum length for passwords.

  • First make a copy of the policy.js file, rename it and save to: /openidm/script/custom-name-policy.js
  • Remove all of the policies, from the new file, that you don’t need
  • Add in your new custom policy 

At the top of the file add in:

var policy1 = {
“policyId” : “maximum-length”,
“policyExec” : “maxLength”,
“clientValidation” : true,
“validateOnlyIfPresent” : true,
“policyRequirements” : [“MAX_LENGTH”]
}

addPolicy(policy1);

function maxLength(fullObject, value, params, property) {
var maxLength = params.maxLength;
var val = “”;

if (value != null) {
val = value;
}

if (val.length > max.length) {
return [ { “policyRequirement” : “ No more than “ + maxLength + characters”, “params” : {“maxLength”:maxLength} } ];
}
return []
};

A simple function that checks to make sure that the password length is not longer than the maxLength parameter.

Great, so how do we enable that (and where do we set that maxLength parameter?)

Let’s go back and modify the policy.json file.  Near the top of the file there is a parameter called “additionalFiles”.  Add the path and name of your custom file to that parameter.

“additionalFiles” : [
“script/custom-name-policy.js
],

Next,

find the password policy section (in the policy.json file).  Under the “managed/user” resource …

“name” : “password”,
“policies” : [
{
“policyId” : “notNull”
  },
{
“policyId” : “atLeastXCapLetters”,
“params” : {
“numCaps” : 1
        }
},

Now add in a reference to the new policy, that was created in the custom-name-policy.js file.  So policy.json would now look like this:

“name” : “password”,
“policies” : [
{
“policyId” : “notNull”
  },
{
“policyId” : “atLeastXCapLetters”,
“params” : {
“numCaps” : 1
        }
},
{
“policyId” : “
maximum-length”,
“params” : {
“maxLength” : 16
          }
},

Save this file and restart OpenIDM.  Your new new policy should now be enabled and when creating a password for a managed/user object (i.e. user) you will get a policy validation error if the password is longer than 16 characters.

Custom Password Policy Validation in OpenIDM

A customer needed to ensure that passwords contained at least one ‘special character’ when a new password was created in OpenIDM.

I borrowed heavily from the provided samples but had to figure out the correct regexp formatting.

Here is the function that I used to implement this:

function atLeastXSpecialChars(fullObject, value, params, property) {
   isRequired = _.find(this.failedPolicyRequirements, function (fpr) {
       return fpr.policyRequirement === "REQUIRED";
   }),
   isNonEmptyString = (typeof(value) === "string" && value.length),
   valuePassesRegexp = (function (v) {
   var testResult = isNonEmptyString ? v.match(/\(|\)|\!|\$|\`|\~|\:|\.|\,|\<|\>|\=|\?|\^|\_|\{|\}/g) : false;
       return testResult;
   }(value));
   if ((isRequired || isNonEmptyString) && !valuePassesRegexp) {
       return [ {"policyRequirement" : "AT_LEAST_X_SPECIAL_CHARS"}];
   }
    return [];
};

Using a different Oracle schema with OpenIDM’s Scripted SQL Connector

Here is a quick note to help you correctly configure the Scripted SQL Connector when working with different schemas in an Oracle Database.  By default the connector assumes that you are querying the default schema, which can be problematic if you happen to be using a different schema (user).

The default connector file will look something like this:

"configurationProperties" : {
    "host" : "localhost",
    "port" : "3306",
    ...
    "database" : "HRDB",
    "autoCommit" : false,
    "reloadScriptOnExecution" : true,
    "createScriptFileName" : "&{launcher.project.location}/tools/CreateScript.groovy",

To query a different schema you can add the attribute “defaultCatalog” to the configurationProperties.  So, if for example your database schema is “myschema” you can add “defaultCatalog” : “myschema”, as shown below:

"configurationProperties" : {
    "host" : "localhost",
    "port" : "3306",
    ...
    "database" : "HRDB",
    "defaultCatalog" : "myschema".
    "autoCommit" : false,

Once you save the connector you should be able to query the correct schema.

Resetting Forgotten Passwords with @ForgeRock #OpenAM

Implementing the “Resetting Forgotten Passwords” functionality as described in the OpenAM Developer’s Guide requires some additional custom code.

It’s pretty straight forward to implement this functionality and can be done in 4 steps (per the Developer’s Guide):

  1. Configure the Email Service
  2. Perform an HTTP Post with the user’s id
  3. OpenAM looks up email address (based on user id) and sends an email with a link to reset the password
  4. Intercept the HTTP GET request to this URL when the user clicks the link.

All of this functionality is available out of the box with the exception of #4.  I wrote some really simple javascript that can be deployed to the OpenAM server that will handle this.  This code was written as a proof-of-concept and doesn’t include any data-validation or error handling but that could be added fairly easily.  This script can be deployed to the root directory of your OpenAM deployment.  Just be sure to update the Forgot Password Confirmation Email URL in the OpenAM Console under Configuration > Global > REST Security.

I have made the code available on my GitHub page and you are welcome to use it or modify it.

As described on the README:

  • These files are a proof of concept to extend OpenAM’s REST-based password reset functionalit
  • Add these two files to your OpenAM deployment root (e.g. /tomcat7/webapps/openam
  • Modify the server urls to the appropriate servers in your environmet
  • Change the REST Security settings in the OpenAM console (e.g. http://[AM server and port]/openam/forgotPassword.jsp)

The file resetPassword.jsp is an optional file that will display a field for the user to provide their id and will then POST to /json/users?_action=forgotPassword (Step #2 from the Developer’s Guide).

Acknowledgements:

Thanks to @Aldaris and @ScottHeger for providing advice while I was working on this.

Seeking Senior OpenAM Engineers

A client of mine has asked me to assist them in finding a full-time Senior OpenAM Engineer.  They are a startup, based in Northern, Virginia.  They are working on some pretty cool initiatives with OAUTH2 and SAML and need an experienced engineer to lead this effort. 

If you are interested in this please feel free to reach out to me and I’ll put you in touch.

2014 IDM Conference Season Planning

Looks like it’s time to start planning for the IDM conference season.  There are some great conferences planned and I need to figure out how to start budgeting for some of these.  Let me know if I have missed any conferences that should be listed.

March:

May:

June:

July:

September:

December:

Finally connected the dots …

My son (10) has been asking about VPNs a lot lately. Which I thought was because of all of the news lately about the NSA. I ended up showing him tunnel bear, which he quickly installed on his laptop and iPhone. I complimented my son for his interest in security and gave a wink about sticking it to “the man”.

A few days later my wife and I were chatting about letting the kids have more access to social media and she said, “well I still have the kids convinced that you can see everything they do on our home network”.   A lightbulb immediately went on over my head.

… Apparently I am “the man”.