[OPENIDM-6325] Users which have no password should not be prompted to enter their current password Created: 27/Jul/16  Updated: 26/Jan/17  Resolved: 16/Aug/16

Status: Closed
Project: OpenIDM
Component/s: Module - Web UI
Affects Version/s: OpenIDM 5.0.0
Fix Version/s: OpenIDM 5.0.0

Type: Improvement Priority: Major
Reporter: Jason Browne Assignee: Jake Feasel
Resolution: Fixed Votes: 0
Labels: CLARK
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
is required by OPENIDM-7517 Document the "isProtected" managed ob... Closed
Relates
is related to OPENIDM-6394 Describe the new way that reauthentic... Closed
Target Version/s:
Verified Version/s:
Epic Link: Customer Data Management: Social Provisioning

 Description   

End-users have non-password options for logging into the self-service UI - for one example, it could be via OpenID Connect authentication. Since passwords are not required for login, there is a good chance that these users don't have a password saved as part of their profile (as would be the case when they use social registration to create their account).

It may be desirable for these password-less users to still have the option to create a local password, so that they can login with their local credentials instead of being forced to rely on whatever other mechanism they had used to authenticate.

The default user model has a policy for passwords which requires that all end users must supply their "current" password before changing it (this is called "reauthentication"). This policy does not make sense for those users with no password defined. Therefore, the system must be able to take this condition into account when deciding whether or not to enforce reauthentication.

The current implementation enforces reauthentication via a policy evaluation. This design decision prevents the context-awareness needed to determine whether or not to allow a given request to change the password. The mistaken design around reauthentication is apparent when considering the nature of "context" - the reauthentication policy is presently the only policy which is context-aware. This context-awareness makes it a very awkward fit for policy enforcement - instead of evaluating the content of the data, the reauthentication policy only considers the context under which it is supplied. The problem for the bug described above is that the policy service does not evaluate policy functions on a per-record basis when listing the requirements for a resource - instead it merely returns a static list of policies which are known to apply to it. This would be fine behavior if those policies were all context-independent; however, for this one policy (reauthentication) context is everything.

To correctly solve this buggy behavior with reauthentication, the logic for enforcement needs to be moved out of policy (policy.js) and instead moved into the authorization logic (router-authz.js). To accomplish this, the declaration on the managed object schema will need to change slightly (so that it is no longer part of the policy configuration) and there will need to be a new way of expressing this authorization requirement to the end-user. The admin UI for configuring the managed object will need to be adjusted to account for this different authorization property, and the self-service UI will need to be adjusted slightly to account for the new way of determining which properties will require this reauthentication behavior. Finally, there will need to be additional customAuthz functions created in router-authz.js which perform the reauthentication check and only allow the request through if the check passes.



 Comments   
Comment by Andi Egloff [ 28/Jul/16 ]

First I would like to double check the requirements around allowing local password when authentication against an external was set up.

If we assume it's desired, I believe we do support context aware field policy since the addition of OPENIDM-4199.

For example, depending on a user's OU, they should have different field policy applied.

Can this not be modeled in a similar fashion, where depending on password, conditionalPolicies are used if this is to be supported?

If we did want to move this out of field policy, this may be more in line with things like step-up authentication requirements. Rather than just adding to IDM specific authorization, it might take some discussion of how to play well both in the context of OpenAM protecting it, or running in stand-alone mode.

Comment by Jake Feasel [ 01/Aug/16 ]

It may be possible to use the conditional policies mechanism, however it would have to change substantially in order to be usable in the UI. The present implementation of conditional policies has no UI support, the main reason being that conditional policies are not included in the list of "policyRequirements" for each property. For example, if I modify the policy on password so that "re-auth-required" is configured like so:

                        "conditionalPolicies" : [
                            {
                                "dependencies": [],
                                "condition": {
                                    "type": "text/javascript",
                                    "source": "(fullObject.password != null)"
                                },
                                "policies": [
                                    {
                                        "policyId" : "re-auth-required",
                                        "params" : {
                                            "exceptRoles" : [
                                                "system",
                                                "openidm-admin",
                                                "openidm-reg",
                                                "openidm-cert"
                                            ]
                                        }
                                    }
                                ]
                            }
                        ]

The response from the read call on the policy service is this:

...snip...
        {
            "policyRequirements": [
                "REQUIRED",
                "MIN_LENGTH",
                "VALID_TYPE",
                "AT_LEAST_X_CAPITAL_LETTERS",
                "AT_LEAST_X_NUMBERS",
                "CANNOT_CONTAIN_OTHERS"
            ],
            "fallbackPolicies": null,
            "name": "password",
            "policies": [
...snip...
            ],
            "conditionalPolicies": [
                {
                    "dependencies": [],
                    "condition": {
                        "type": "text/javascript",
                        "source": "(fullObject.password != null)"
                    },
                    "policies": [
                        {
                            "policyId": "re-auth-required",
                            "params": {
                                "exceptRoles": [
                                    "system",
                                    "openidm-admin",
                                    "openidm-reg",
                                    "openidm-cert"
                                ]
                            }
                        }
                    ]
                }
            ]
        },
...snip....

So, while the "conditionalPolicies" is returned to the client, the UI needs to know about the policy requirement "REAUTH_REQUIRED". This is not possible for the UI to determine by itself from that response, for a number of reasons - one is that the function definition for "policyId": "re-auth-required" is not client-side executable (and so not returned to the client); another is that our "password" field is configured to be "private", which means that from the client's perspective, (fullObject.password != null) will never be true (since the password is never included in the response).

The conditional policy facility was initially built with the understanding that it wasn't usable for the UI. While that would be a good enhancement to make, I still think that this particular logic would be better expressed as a auth rule, rather than a policy one.

Comment by Jake Feasel [ 16/Aug/16 ]

See write-up here for details on solution: https://stash.forgerock.org/projects/OPENIDM/repos/openidm/pull-requests/1320/overview

Comment by David Chodur [ 05/Dec/16 ]

Tested with OpenIDM 5.0.0. revision: 861579b and works like a charm.

Generated at Tue Sep 22 11:27:52 UTC 2020 using Jira 7.13.12#713012-sha1:6e07c38070d5191bbf7353952ed38f111754533a.