IDM Generate Password Token Workaround

0 Likes
As many IDM developers already know IDM has a token called "Generate Password" that can be used to generate a password that conforms to a specified password policy.

It's very easy to use, just point it to a password policy object in your eDirectory and you will get a password that fulfills all the password policy rules, most of the time that is.

Recently a client had a requirement that the initial password a user received when he or she was created must not contain certain characters or numbers since they would confuse the user when entering the password, the user would enter 1 instead of l or something similar.

I created a password policy where I've excluded those characters. I assigned the password policy to a user and then I proceeded to try to change the password as that user, and it worked nicely, I couldn't enter a password that contained those characters that were excluded in the policy.

Then I proceeded to implement this in IDM using the Generate Password token, here I stumbled upon a problem, for some reason the password returned by the Generate Password token sometimes contained the excluded characters, i.e. the Generate Password token didn't respect the password policy 100%.

This posed a problem, I really wanted to used the built-in function for generating the password instead of resorting to ECMAScript or some calls to Java using XPath.

So I came up with this workaround which basically reads the nspmExcludeList attribute on the password policy, converts the multivalue attribute to a string variable and then uses the XPath translate() function on the generated password to strip the unwanted characters from the password.

Here is the rule that does it.
<rule>
<description>Set initial password using generate password token</description>
<conditions>
<and>
<if-class-name mode="nocase" op="equal">User</if-class-name>
<if-operation mode="case" op="equal">add</if-operation>
<if-password op="not-available"/>
</and>
</conditions>
<actions>
<do-set-local-variable name="pwdPolicyDN" scope="policy">
<arg-string>
<token-text xml:space="preserve">Security\Initial Pwd Policy</token-text>
</arg-string>
</do-set-local-variable>
<do-set-local-variable name="pwd" scope="policy">
<arg-string>
<token-generate-password policy-dn="$pwdPolicyDN$"/>
</arg-string>
</do-set-local-variable>
<do-set-local-variable name="excludeList" scope="policy">
<arg-node-set>
<token-base64-decode charset="UTF-8">
<token-dest-attr name="nspmExcludeList">
<arg-dn>
<token-local-variable name="pwdPolicyDN"/>
</arg-dn>
</token-dest-attr>
</token-base64-decode>
</arg-node-set>
</do-set-local-variable>
<do-set-local-variable name="join" scope="policy">
<arg-string>
<token-replace-all regex="\n" replace-with="">
<token-local-variable name="excludeList"/>
</token-replace-all>
</arg-string>
</do-set-local-variable>
<do-set-local-variable name="pwd" scope="policy">
<arg-string>
<token-xpath expression="translate($pwd, $join, '')"/>
</arg-string>
</do-set-local-variable>
<do-set-dest-password>
<arg-string>
<token-local-variable name="pwd"/>
</arg-string>
</do-set-dest-password>
<do-set-src-password>
<arg-string>
<token-local-variable name="pwd"/>
</arg-string>
</do-set-src-password>
</actions>
</rule>

Here I will explain each action.
<do-set-local-variable name="pwdPolicyDN" scope="policy">
<arg-string>
<token-text xml:space="preserve">Security\Initial Pwd Policy</token-text>
</arg-string>
</do-set-local-variable>

First we point out the DN of the password policy that the Generate Password token will use.

At my client I use a GCV instead of a local variable.
<do-set-local-variable name="pwd" scope="policy">
<arg-string>
<token-generate-password policy-dn="$pwdPolicyDN$"/>
</arg-string>
</do-set-local-variable>

Then we generate the initial password.
<do-set-local-variable name="excludeList" scope="policy">
<arg-node-set>
<token-base64-decode charset="UTF-8">
<token-dest-attr name="nspmExcludeList">
<arg-dn>
<token-local-variable name="pwdPolicyDN"/>
</arg-dn>
</token-dest-attr>
</token-base64-decode>
</arg-node-set>
</do-set-local-variable>

Next we fetch the nspmExcludeList attribute from the password policy and perform a Base 64 decode on it so we get the clear text. We tell the decode token that the content is UTF-8 encoded. The excludeList variable now contains the excluded characters but each characters is on a separate line.
<do-set-local-variable name="join" scope="policy">
<arg-string>
<token-replace-all regex="\n" replace-with="">
<token-local-variable name="excludeList"/>
</token-replace-all>
</arg-string>
</do-set-local-variable>

We convert the excludeList to a string by replacing all new line characters with nothing. The effect is a variable that looks like this:

1iIoO0
<do-set-local-variable name="pwd" scope="policy">
<arg-string>
<token-xpath expression="translate($pwd, $join, '')"/>
</arg-string>
</do-set-local-variable>

This action strips the unwanted characters from the generated password by using the XPath translate() function which replaces all characters in the $pwd variable that are located in the $join variable with '' (i.e. "nothing"), effectively removing unwanted characters from the password.
<do-set-dest-password>
<arg-string>
<token-local-variable name="pwd"/>
</arg-string>
</do-set-dest-password>
<do-set-src-password>
<arg-string>
<token-local-variable name="pwd"/>
</arg-string>
</do-set-src-password>

The last two actions send the password to the destination eDirectory (customers File and Print tree) and back to the source Identity Vault.

Depending on your password policy the stripping of unwanted characters might mean that you get a password that no longer fulfills the complexity requirements.

In that case you could replace with the unwanted characters with some other characters instead of deleting them like I do, or you could have the Generate Password token inside a while loop that checks the generated password until it has no excluded characters.

Labels:

How To-Best Practice
Comment List
  •  
    Hello Stefaan,
    Good point, I'm aware of that and I also have a note about that at the end of the article. :-)

    About logging a bug with Novell, apparently its already logged.
    It's bug number 667749.

  •  
    Doing this might violate the password length.
    It might be better to loop over the the code from "generate-password" up to and including "translate", until the generated password equals the translated password. If so, the generate-password policy generated a password without the excluded characters, and with a valid length.

    Since you pointed out that this is a bug in the generate password token, logging a bug with Novell might also help :-)

    Stefaan
Related
Recommended