Skip to content
This repository has been archived by the owner on May 14, 2024. It is now read-only.

bind response - password expiring overrides force password change #770

Closed
ShlomitGilo1 opened this issue Nov 17, 2021 · 23 comments
Closed

Comments

@ShlomitGilo1
Copy link

ShlomitGilo1 commented Nov 17, 2021

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.

@jsumners
Copy link
Member

How does this relate to the ldapjs module?

@ShlomitGilo1
Copy link
Author

because I'm using ldapjs package for all LDAP related code

@jsumners
Copy link
Member

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.

@ShlomitGilo1
Copy link
Author

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.

@jsumners
Copy link
Member

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.

@ShlomitGilo1
Copy link
Author

ShlomitGilo1 commented Nov 22, 2021

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?

@ShlomitGilo1
Copy link
Author

Hi,
Can someone please answer my last syntax question above....?

@jsumners
Copy link
Member

What does the documentation state?

@ShlomitGilo1
Copy link
Author

image
image

@jsumners
Copy link
Member

So does your example provide an array of controls?

@ShlomitGilo1
Copy link
Author

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
image

@jsumners
Copy link
Member

This project does not provide any "types file". Please review the tests for sample usages. For example:

tap.test('delete with control (GH-212)', function (t) {
const control = new ldap.Control({
type: '1.2.3.4',
criticality: false
})
t.context.client.del('cn=delete, ' + SUFFIX, control, function (err, res) {
t.error(err)
t.ok(res)
t.end()
})
})

@ShlomitGilo1
Copy link
Author

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)

@jsumners
Copy link
Member

I don't know how to be any clearer: ldapjs does not provide any types file or package.

@ShlomitGilo1
Copy link
Author

I don't understand.
I'm writing ts code, and using ldapjs package.
As defined in your README,
image

so that's what I do. I install the package.
Since I'm writing in ts, I need types.

@jsumners
Copy link
Member

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?

@UziTech
Copy link
Member

UziTech commented Nov 28, 2021

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';`

@UziTech
Copy link
Member

UziTech commented Nov 28, 2021

If you have an issue with the types in @types/ldapjs you can create an issue on the DefinitelyTyped repo.

@pmoleri
Copy link

pmoleri commented Dec 7, 2021

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 the ldap.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: ... })

@jsumners
Copy link
Member

jsumners commented Dec 8, 2021

I think docs could be improved.

Yes. The docs need a lot of attention.

@ShlomitGilo1
Copy link
Author

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?

@jsumners
Copy link
Member

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.

@jsumners
Copy link
Member

👋

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.

@ldapjs ldapjs locked as resolved and limited conversation to collaborators Feb 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants