DirectoryEntry authentication throws COMException instead of DirectoryServicesCOMException - authentication

I'm using .NET and creating a DirectoryEntry and the access the NativeObject member to validate a user's credentials against AD.
There are some situations, where the login will fail, because the "User must change password on next logon" flag is set or the user is currently not allowed to logon because the logon times do not match.
I want to distinguish if one of these situations occured or if the user just entered a wrong password.
If I create the DirectoryEntry object with parameter AuthenticationTypes.None, a DirectoryServicesCOMException is thrown if the login failed. The information in this exception can be used to determine e.g. if the "password change" flag is set.
Unfortunately, using AuthenticationTypes.None is not a secure way, as the password is transmitted.
If I create the DirectoryEntry object with the parameter AuthenticationTypes.Secure, a COMException is thrown instead of a DirectoryServicesCOMException. This exception is very generic, as it always has the error code ERROR_LOGON_FAILURE. I cannot distinguish if the user has entered a bad password or if the password has to be changed.
MSDN documentation says: If AuthenticationTypes.Secure is set, the WinNT provider uses NTLM to authenticate the client. I guess this leads to a different behavior where only a COMException is thrown.
Works, but insecure:
var de = new DirectoryEntry(path, user, pass, AuthenticationTypes.None);
Secure, but throws only COMException:
var de = new DirectoryEntry(path, user, pass, AuthenticationTypes.Secure);
The first option uses basic authentication and throws specific DirectoryServicesCOMException, second option uses NTLM and throws only a generic COMException.
Has anyone an idea how I can detect if a user has to change the password, the account is locked or expired, logon times are invalid, ... or if the user has just entered a wrong password ?
Many thanks.

Related

How to disable the property of password-generator in OpenDJ

By default, the value of password-generator in Default Password Policy is Random Password Generator, and then if I try to set a password for a user, I'll get an error shows I cannot provide a password.
But in my case, I want the user can set his/her initial password when the account is created. So, how can I disable the property and just let user set the password?
The password-generator is only used when trying to set or change a password with ldappasswordmodify and no new password is passed as parameter.
If you are getting an error when trying to set a password for a user, it is not due to the password-generator. It's something else, and the error message that you can find in the Access log should be pretty explicit.

How to connect LDAP With username and password?

I have my Ldap working the only issue i'm facing was when I try to login with email that is when I land in the else part in the below code. If my username is different from email then it throws error. i.e if my email is 'skumar#gmail.com' and my username is 'saurakumar' then it will through invalid username password error.
As internally I'm using username to make email i.e if the user login with name 'karan' then i'm expecting the email to be karan #gmail.com which is not true in many scenario and the Authentication fails. I'm looking for some solution wherein I can login either via email or via username I'll be able to authenticate user. Below is the snippet of my code. Please suggest?
ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
ldapEnv.put(Context.PROVIDER_URL, url);
ldapEnv.remove(Context.SECURITY_PROTOCOL);
if (email == null) {
lContext = new InitialLdapContext(ldapEnv, null);
entryResult = searchUserEntry(lContext, user, searchCtrls);
final String usrDN = ((Context) entryResult.getObject()).getNameInNamespace();
lContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
lContext.addToEnvironment(Context.SECURITY_PRINCIPAL, usrDN);
lContext.addToEnvironment(Context.SECURITY_CREDENTIALS, pass);
lContext.reconnect(null);
} else {
ldapEnv.put(Context.SECURITY_PRINCIPAL, email);
ldapEnv.put(Context.SECURITY_CREDENTIALS, credentials);
lContext = new InitialLdapContext(ldapEnv, null);
return lContext;
searchUserEntry(lContext, user, searchCtrls);
}
Normally this is a 3-step process:
Bind to LDAP as an administrative user. Note that this should not be the master user defined in the configuration file: that's for OpenLDAP's use itself. Instead it should be a user mentioned in the DIT that has the appropriate search access for the next step.
Search for the user via some unique attribute, e.g. in your case email.
Using the found DN of the user and the password he specified, attempt to bind as that user (with the reconnect() method, after changing the environment of the context appropriately).
If all that succeeds, you have a login success. If (2) or (3) fail, you have a failure, and note that you should not tell the user which it was: otherwise you are leaking information to attackers. You should not mention whether it was the username (email) or the password that was wrong.

How do I administratively set a new password for ASP.net Identity User who forgot their password?

I am not looking for a solution that involves the user, a token generated, and emailing in order to reset a user's password.
The scenario is a user contacts the admins and asks them to reset their password (internal organization web app). They are then told what that new temporary password is so they can log in and change it.
I see no function that lets me do the above. My attempt:
string passwordToken = await UM.GeneratePasswordResetTokenAsync(user.Id);
IdentityResult res = await UM.ResetPasswordAsync(user.Id, passwordToken, "newPassword##!$%");
UM is UserManager.
I get error "No IUserTokenProvider is registered". I think GeneratePasswordResetToken is the one causing the error. If so, why?
How do I properly do what I need?
Use the combination of RemovePasswordAsync and AddPasswordAsync
UserManager.RemovePasswordAsync(user.Id);
UserManager.AddPasswordAsync(user.Id, tempPassword);

updateSiteAccountCredentials throws IllegalArgumentValueException

I'm using the Yodlee REST API and try to update the credentials at a site.
I'm doing the following sequence:
authenticate/coblogin
authenticate/login
SiteAccountManagement/updateSiteAccountCredentials
In 3 I pass:
cobSessionToken <cobSessionToken>
userSessionToken <userSessionToken>
memSiteAccId <memSiteAccId>
credentialFields.enclosedType com.yodlee.common.FieldInfoSingle
credentialFields[0].name LOGIN
credentialFields[0].displayName User ID
credentialFields[0].valueMask LOGIN_FIELD
credentialFields[0].fieldType.typeName IF_LOGIN
credentialFields[0].valueIdentifier LOGIN
credentialFields[0].value <username>
credentialFields[1].name PASSWORD
credentialFields[1].displayName Password
credentialFields[1].valueMask LOGIN_FIELD
credentialFields[1].fieldType.typeName IF_PASSWORD
credentialFields[1].valueIdentifier PASSWORD
credentialFields[1].value <password>
All according to the API spec.
But all I get back is:
"errorOccured": "true",
"exceptionType": "com.yodlee.core.IllegalArgumentValueException",
"refrenceCode": <referenceCode>,
"message": "Multiple exceptions encapsulated within: invoke getWrappedExceptions for details"
What am I missing?
I'd recommend that you try and do the same credential edit call for another site too.
If the call works for the other site, chances are it is an error related specifically to the site you're trying to edit above (and so, a ticket with Yodlee likely needs to be opened). HTH!

Error changing password of user using WinNT string connection (and authenticating the current password)

I am developing a website which will authenticate the user and change the old password with new password.
I am using WinNT string connection and setting password, without the old password check, works.
My code is as below:
'actual setting password
Dim entryD As New DirectoryEntry("WinNT://" + Environment.MachineName + ",computer")
Dim NewUser As DirectoryEntry = entryD.Children.Find(username, "user")
Dim nativeobject As Object = NewUser.NativeObject
NewUser.Invoke("SetPassword", New Object() {strPassNew})
NewUser.CommitChanges()
'setting password ends
This works fine, but authentication code is not working.
It is as below:
'authentication starts
Dim adsiPath As String
adsiPath = String.Format("WinNT://{0}/{1},user", domain, username)
Dim userEntry = New DirectoryEntry(adsiPath, username, password, AuthenticationTypes.Secure)
'Dim nativeobject1 As Object = userEntry.NativeObject
Dim newobj As ActiveDs.IADsUser = userEntry.NativeObject
authent = True
'authentication ends
This authenticates but the exception which it throws is:
logon failure: unknown username or bad password
for the first time, but if i do it again the error is:
"Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again.
"
Which I don't want to happen... I don't want to use LDAP, I want a solution please, to authenticate the old password. Please help?
I had this error in my code where requirement was to add domain users to local admin group of a system. While testing the code after the first try I used to get "Multiple connections to a server ..." error and then I if try the code code later(an hour or so) it worked fine. After searching thru various forms I came know the we can see user logged-on to a computer using
NET SESSION /LIST
command in cmd of remote system and it appears that when we use WinNT provider it actually creates an user session with idle timeout on remote computer (there can be a situation where other programs are creating sessions) which conflicts the connection when you try for second time. So I tried deleting the previous session by
NET SESSION \\RequestingComputerName /DELETE
then I did n't got the error. If that doesn't solve the problem then the last resort is to restart the system.