Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] honor pwdReset: TRUE on openldap #1766

Open
davama opened this issue Feb 25, 2021 · 16 comments · May be fixed by #5425
Open

[Feature Request] honor pwdReset: TRUE on openldap #1766

davama opened this issue Feb 25, 2021 · 16 comments · May be fixed by #5425
Labels
area/ldap LDAP related features/bugs priority/4/normal Normal priority items status/needs-design Requires thoughtful design type/feature Request for adding a new feature

Comments

@davama
Copy link

davama commented Feb 25, 2021

Basically if attribute is present, then force user to reset their password.

with sssd when attribute is present, the user is given a msg that they must change their password and force to type old pass then new pass.

Of course willing to test.

thanks!

@james-d-elliott
Copy link
Member

james-d-elliott commented Mar 10, 2021

This would probably take a fair bit of thought. There are many LDAP implementations and they each have differing methods to signify this. We also have to ensure it's reset after. It would probably require 3 additional configuration options:

authentication_backend:
  ldap:
    password_reset_attribute: pwdReset
    password_reset_value_required: "TRUE"
    password_reset_value_not_required: "FALSE"

Ideally a feature like this should also exist as an alternative to the current email based password reset.

@james-d-elliott james-d-elliott added type/feature Request for adding a new feature status/needs-design Requires thoughtful design priority/4/normal Normal priority items labels Mar 10, 2021
@james-d-elliott james-d-elliott added the area/ldap LDAP related features/bugs label Dec 6, 2022
@james-d-elliott
Copy link
Member

This can be half done via a filter:

(!(pwdReset=TRUE))

We will have to think about the added functionality of forcing a reset, specifically.

@davama
Copy link
Author

davama commented Dec 6, 2022

Thank you!

Ill give it a try and post the results

@nightah
Copy link
Member

nightah commented Jan 9, 2023

@davama how'd you go with testing this, with the updated filter did it prevent you from being able to login with that user?

Just want to understand current behaviour so we know how to plan the second portion of this request.

@davama
Copy link
Author

davama commented Jan 10, 2023

@nightah

It works but will have an issue when it comes to email.
The user with the pwdReset=True is ignored, therefore he cannot authenticate to authelia. Once I reset try to reset my password, the user is not found therefore, no email is sent.

Im trying to figure out how to better write the filter:

users_filter: (&({username_attribute}={input})(objectClass=person)(!(pwdReset=TRUE)))

@james-d-elliott
Copy link
Member

We may have to have a set of filters for this purpose where the users_filter is remapped as a default. I think it's the most flexible overall.

@davama
Copy link
Author

davama commented Jan 13, 2023

That’ll be interesting to see
Let me know so i can test
Thank you for the support!

@james-d-elliott
Copy link
Member

@davama
Copy link
Author

davama commented May 11, 2023

Thank you very much @james-d-elliott !

I see there are a few changes to the ldap configuration settings.

i would like to give this a test.
how could I go about in downloading a PR based docker image?

Thanks!

@james-d-elliott
Copy link
Member

Tag is the branch name, so authelia/authelia:feat-ldap-reset-filter.

@davama
Copy link
Author

davama commented May 17, 2023

Hello @james-d-elliott

hope you are doing well.

I have no issue authenticating with my credentials and getting an email to reset my password. It is only after i clicked the reset password link and input my new password that i get the error below. I have yet to try an account with the pwdReset attribute. Simply wanted to make sure all previous functionality is good before i move on testing this feature.

perhaps it's a config issue?

{
  "level": "error",
  "method": "POST",
  "msg": "unable to update password. Cause: cannot find user DN of user 'myusername'. Cause: LDAP Result Code 4 \"Size Limit Exceeded\": ",
  "path": "/api/reset-password",
  "remote_ip": "10.x.x.x",
  "stack": [
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/authelia_context.go",
      "Line": 67,
      "Name": "(*AutheliaCtx).Error"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/handlers/handler_reset_password_step2.go",
      "Line": 52,
      "Name": "ResetPasswordPOST"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/bridge.go",
      "Line": 54,
      "Name": "(*BridgeBuilder).Build.func1.1"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/headers.go",
      "Line": 25,
      "Name": "SecurityHeadersCSPNone.func1"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/headers.go",
      "Line": 51,
      "Name": "SecurityHeadersNoStore.func1"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/headers.go",
      "Line": 16,
      "Name": "SecurityHeaders.func1"
    },
    {
      "File": "github.com/fasthttp/router@v1.4.19/router.go",
      "Line": 420,
      "Name": "(*Router).Handler"
    },
    {
      "File": "github.com/valyala/fasthttp@v1.47.0/http.go",
      "Line": 158,
      "Name": "(*Response).StatusCode"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/metrics.go",
      "Line": 22,
      "Name": "NewMetricsRequest.func1.1"
    },
    {
      "File": "github.com/valyala/fasthttp@v1.47.0/server.go",
      "Line": 2365,
      "Name": "(*Server).serveConn"
    },
    {
      "File": "github.com/valyala/fasthttp@v1.47.0/workerpool.go",
      "Line": 224,
      "Name": "(*workerPool).workerFunc"
    },
    {
      "File": "github.com/valyala/fasthttp@v1.47.0/workerpool.go",
      "Line": 196,
      "Name": "(*workerPool).getCh.func1"
    },
    {
      "File": "runtime/asm_amd64.s",
      "Line": 1598,
      "Name": "goexit"
    }
  ],
  "time": "2023-05-17T19:34:13Z"
}

below is my update ldap config:

authentication_backend:
  password_reset:
    disable: false
    custom_url: ""
  refresh_interval: 5m
  ldap:
    implementation: custom
    address: 'ldap://dcom-dave-vm.domain.com'
    timeout: '5s'
    start_tls: false
    tls:
      skip_verify: false
      minimum_version: TLS1.2
    base_dn: 'dc=domain,dc=com'
    additional_users_dn: 'ou=people'
    users_filter: '(&({username_attribute}={input})(objectClass=person))'
    users_reset_filter: '(!(pwdReset=TRUE))'
    additional_groups_dn: 'ou=group'
    groups_filter: '(&(member={dn})(objectClass=groupOfNames))'
    group_search_mode: 'filter'
    mail_attribute: mail
    display_name_attribute: cn
    permit_referrals: false
    permit_unauthenticated_bind: false
    user: cn=pwmanager,dc=domain,dc=com
    #password: is via ENV var
    attributes:
      distinguished_name: 'dn'
      username: 'uid'
      display_name: 'cn'
      mail: 'mail'
      member_of: 'memberOf'
      group_name: 'cn'

I can post my openldap logs too, but want to make sure that my config is sane before i do so.

Best,
Dave

@james-d-elliott
Copy link
Member

Try this:

authentication_backend:
  password_reset:
    disable: false
    custom_url: ""
  refresh_interval: 5m
  ldap:
    implementation: custom
    address: 'ldap://dcom-dave-vm.domain.com'
    timeout: '5s'
    start_tls: false
    tls:
      skip_verify: false
      minimum_version: TLS1.2
    base_dn: 'dc=domain,dc=com'
    additional_users_dn: 'ou=people'
    users_filter: '(&({username_attribute}={input})(objectClass=person)(!(pwdReset=TRUE)))'
    users_reset_filter: '(&({username_attribute}={input})(objectClass=person))'
    additional_groups_dn: 'ou=group'
    groups_filter: '(&(member={dn})(objectClass=groupOfNames))'
    group_search_mode: 'filter'
    mail_attribute: mail
    display_name_attribute: cn
    permit_referrals: false
    permit_unauthenticated_bind: false
    user: cn=pwmanager,dc=domain,dc=com
    #password: is via ENV var
    attributes:
      distinguished_name: 'dn'
      username: 'uid'
      display_name: 'cn'
      mail: 'mail'
      member_of: 'memberOf'
      group_name: 'cn'

@james-d-elliott
Copy link
Member

Also @davama I was literally coming on to ask how you were going with this, so good timing!

@davama
Copy link
Author

davama commented May 18, 2023

Also @davama I was literally coming on to ask how you were going with this, so good timing!

thats funny

appreciate the input!
I’ll report back tomorrow with findings

thank you @james-d-elliott !!

@davama
Copy link
Author

davama commented May 18, 2023

@james-d-elliott

These new filters definitely help in a user not being able to successfully auth/authorize with some dummy password that an administrator set and with the pwdReset: TRUE in their dn account. This is only because according to authelia no user is found

"msg":"Unsuccessful 1FA authentication attempt by user 'myusername': user not found","path":"/api/firstfactor","remote_ip":"10.x.x.x"

I will say that that's as far as a user can go. They are not able to reset their password on their own. No email is sent and according to authelia logs, no user is found (which makes sense according to this filter (&({username_attribute}={input})(objectClass=person)(!(pwdReset=TRUE))) ).

Log of the authelia error:

{
  "level": "error",
  "method": "POST",
  "msg": "user not found",
  "path": "/api/reset-password/identity/start",
  "remote_ip": "10.x.x.x",
  "stack": [
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/identity_verification.go",
      "Line": 34,
      "Name": "IdentityVerificationStart.func1"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/bridge.go",
      "Line": 54,
      "Name": "(*BridgeBuilder).Build.func1.1"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/headers.go",
      "Line": 25,
      "Name": "SecurityHeadersCSPNone.func1"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/headers.go",
      "Line": 51,
      "Name": "SecurityHeadersNoStore.func1"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/headers.go",
      "Line": 16,
      "Name": "SecurityHeaders.func1"
    },
    {
      "File": "github.com/fasthttp/router@v1.4.19/router.go",
      "Line": 420,
      "Name": "(*Router).Handler"
    },
    {
      "File": "github.com/valyala/fasthttp@v1.47.0/http.go",
      "Line": 158,
      "Name": "(*Response).StatusCode"
    },
    {
      "File": "github.com/authelia/authelia/v4/internal/middlewares/metrics.go",
      "Line": 22,
      "Name": "NewMetricsRequest.func1.1"
    },
    {
      "File": "github.com/valyala/fasthttp@v1.47.0/server.go",
      "Line": 2365,
      "Name": "(*Server).serveConn"
    },
    {
      "File": "github.com/valyala/fasthttp@v1.47.0/workerpool.go",
      "Line": 224,
      "Name": "(*workerPool).workerFunc"
    },
    {
      "File": "github.com/valyala/fasthttp@v1.47.0/workerpool.go",
      "Line": 196,
      "Name": "(*workerPool).getCh.func1"
    },
    {
      "File": "runtime/asm_amd64.s",
      "Line": 1598,
      "Name": "goexit"
    }
  ],
  "time": "2023-05-18T14:28:52Z"
}

I believe it would be beneficial for the users to know that they MUST reset their password (via email perhaps).

As sssd does this quite well.

# change the password of myusername which sets the `pwdReset: TRUE` attribute on their dn
> ldappasswd -D admindn -W -s dummypass uid=myusername,dc=bla
# later the user attempts to ssh into the server with their dummy ldap creds

(myusername@server) Password: <dummyadminprovidedpass>
(myusername@server) Your secret token: 123456
(myusername@server) Password expired. Change your password now.
Current Password: <dummyadminprovidedpass>
(myusername@server) New password: <somethingnew>
(myusername@server) Retype new password: <somethingnew>
# user is auth/authorized

I understand that the less info you give back on the UI the better.
So if the user contains pwdReset: TRUE and that same user attempts to authenticate, then send them an email that they MUST reset their password (with the included reset link).

Thank you very much for your help in this!

Looking forward to your thoughts

Best,
Dave

@james-d-elliott
Copy link
Member

I think I know why. Should be easy to fix.

I understand the desire for making this more than just allowing the reset but preventing a user login, however I'm skeptical about the idea of this specifically because it may not prove to be very portable. For example as far as I am aware FreeIPA doesn't have an attribute like this, it has a date time. Variances like this make it difficult to support this well without creating painful issues to solve or heavily restricting the directory servers we support.

In addition the feature does not currently exist for the file provider which must be considered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/ldap LDAP related features/bugs priority/4/normal Normal priority items status/needs-design Requires thoughtful design type/feature Request for adding a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants