node-ldapjs
node-ldapjs copied to clipboard
bind response - password expiring overrides force password change
Hi! I'm implementing the feature of forcing password change on first login, when a user is added or when admin is changing user's password. I set ds-cfg-force-change-on-add and ds-cfg-force-change-on-reset to true, and following the spec, which defines:
10. Password Change After Reset This policy forces the user to select a new password on first bind or after password reset. After bind operation succeed with authentication, the server should check if the password change after reset policy is on and this is the first time logon. If so, the server should send bindResponse with the resultCode: LDAP_SUCCESS, and should include the password expired control in the controls field of the bindResponse message: controlType: 2.16.840.1.113730.3.4.4, controlValue: an octet string: "0", criticality: false
Indeed, when I call Client.bind, I get return value LDAP_SUCCESS, and the controls field as defined in the spec.
BUT - when I call Client.bind when the user is within its password expiration warning interval, I get the controls field only with the password expiring controlType (2.16.840.1.113730.3.4.5). I would expect to get both controlType elements (controls is an array), but 2.16.840.1.113730.3.4.4 is not there.
This is a major problem because if the controlType 2.16.840.1.113730.3.4.4 is not there - the user will be able to login although he supposed to be not.
What am I missing here?
Thanks.
How does this relate to the ldapjs
module?
because I'm using ldapjs package for all LDAP related code
because I'm using ldapjs package for all LDAP related code
Please provide a minimal reproduction. It is not at all clear what issue you are presenting.
ok, I'll try to clarify. I writing a service in node, and using ldapjs package.
I'm using Client.bind() method of the package. The signature of the method is: bind(dn: string, password: string, callback: CallBack): void;
The callback returns error in case of bind failure and 'result' with additional info in case of bind success.
When LDAP feature 'force password change' is set, when user should reset his password, his bind 'result' field indicates that by setting a field in 'result', called 'controls', with a 'controlType' attribute set to 2.16.840.1.113730.3.4.4.
The problem is, that when a user should change his password and he's also in the password expiring warning interval, the bind 'result' field indicates only the password expiring warning (by setting 'controlType' to 2.16.840.1.113730.3.4.5), and the force password change indication is not there.
It's a major problem, because if I don't get the 'controlType' of the force password reset, I don't know I should block this user login.
The client receives responses from the server and passes them along to your code. Unless you can provide a minimal reproduction to show there is an error in the ldapjs
client code, this is an issue with your server.
You are right. It's the behavior of the server, and not an error in ldapjs. However, I got this answer in StackOverflow: "The Netscape controls are very old and predate the OpenDJ password policy work. They are just there to ensure some form of compatibility with very old applications. New applications should send the Password Policy Request Control (1.3.6.1.4.1.42.2.27.8.5.1) and will receive the proper PwdPolicy control response."
The purpose here is probably to use the 'controls' argument in ldapjs bind method, to explicitly request the password policy controls of the user. I failed to find the proper way to provide this argument. I tried:
Client.bind(<dn>, <password>, {type: "1.3.6.1.4.1.42.2.27.8.5.1", criticality: false}, <callback>)
but it throws the exception:
controls must be [Control]
What is the right syntax to use?
Hi, Can someone please answer my last syntax question above....?
What does the documentation state?
So does your example provide an array of controls?
It throws the exception also when I use an array:
Client.bind(<dn>, <password>, [{type: "1.3.6.1.4.1.42.2.27.8.5.1", criticality: false}], <callback>)
According to the types file, it can be either an array or not
This project does not provide any "types file". Please review the tests for sample usages. For example:
https://github.com/ldapjs/node-ldapjs/blob/1f85db9a00426abda117abace7dd3b283e08fc25/test/client.test.js#L581-L591
What do you mean This project does not provide any "types file"?
npm install ldapjs
is not enough. It gives the warning:
Could not find a declaration file for module 'ldapjs'. 'c:/develop/ldapUmsSearchTest/node_modules/ldapjs/lib/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/ldapjs` if it exists or add a new declaration (.d.ts) file containing `declare module 'ldapjs';`ts(7016)
I don't know how to be any clearer: ldapjs
does not provide any types file or package.
I don't understand.
I'm writing ts code, and using ldapjs package.
As defined in your README,
so that's what I do. I install the package. Since I'm writing in ts, I need types.
This project is a JavaScript project. If you use it with TypeScript then anything pertaining to TypeScript is up to you.
As for the original question, I think we have covered the usage of controls through reading the documentation and unit tests. Is this the case?
types are provided by @types/ldapjs
. We cannot confirm that they are accurate since we did not write them.
Follow the directions in the error message:
Try `npm i --save-dev @types/ldapjs` if it exists or add a new declaration (.d.ts) file containing `declare module 'ldapjs';`
If you have an issue with the types in @types/ldapjs you can create an issue on the DefinitelyTyped repo.
Hi, I think this thread has revolted on Typescript when it's not part of the issue at all, only that is not being helpful restricting the type, so it allowed @ShlomitGilo1 to make a mistake.
The actual issue seems to be that @ShlomitGilo1 is using a POJO (plain old JS object), when the ldapjs library requires an actual instance of the Control
class.
You can see this in:
-
In the docs
Note that all client APIs can optionally take an array of
Control
objects.There
Control
refers to theldap.Control
class, although is not very explicit. I think docs could be improved. -
In the sample that @jsumners provided: link There you can see it's using
new ldap.Control({ type: ... })
I think docs could be improved.
Yes. The docs need a lot of attention.
ok, I got over the ts issue, and now I'm able to use the controls argument. Great. But I probably don't understand how to use it. All I want is, as documented, "to request information about the current password policy information for a user entry" (https://docs.oracle.com/cd/E19476-01/821-0506/searching-using-controls.html). I want to get to a situation where I receive in the response for bind/search requests, both controls of 2.16.840.1.113730.3.4.4 and 2.16.840.1.113730.3.4.5.
BUT when I set the controls argument in the request to: {type: "1.3.6.1.4.1.42.2.27.8.5.1", criticality: true}
for providing it in the search request I get the exception:
UnavailableCriticalExtensionError: The search request cannot be processed because it contains a critical control with OID 1.3.6.1.4.1.42.2.27.8.5.1 that is not supported by the Directory Server for this type of operation
and for providing it in the bind request I get back the same value I sent in the request: "controls":[{"type":"1.3.6.1.4.1.42.2.27.8.5.1","criticality":false,"value":{"type":"Buffer","data":[48,3,129,1,2]}}]
What am I missing here?? how can I get 2.16.840.1.113730.3.4.4 and 2.16.840.1.113730.3.4.5 in the response?
Your server told you: OID 1.3.6.1.4.1.42.2.27.8.5.1 that is not supported by the Directory Server for this type of operation
.
👋
On February 22, 2023, we released version 3 of this library. As a result, we are closing this issue/pull request.
Please see issue #839 for more information, including how to proceed if you feel this closure is in error.