How to connect LDAP With username and password? - ldap

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.

Related

Removing a user from backend created by IdentityServer4

I am debugging confirmation email flow when signing up a new User in Asp.Net Core web application with Identity Server 4.
Since I had already signed up with my actual email, to reuse it, I modified the UserName and Email in AspNetUsers table using SQL Update to some random value.
Now when I am signing up with the original email again. I am getting a duplicate user error
result = await _userManager.CreateAsync(user, model.Password);
I have already:
Cleared browser cache.
Closed local IIS Express
Restarted Visual Studio.
Used_userManager.DeleteAsync() after updating the UserName and Email back to original values but this gives an Microsoft.AspNetCore.Identity.IdentityError with description Optimistic concurrency failure, object has been modified.
On running this query on Sql Server
select * from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME in ( 'UserName' , 'Email')
I get the following:
I know that this is not a good practice to mess with backend, but this is development environment and I could continue my work with another email.
I would request readers to help in understanding how the User could be safely scorched to be able to reuse the email.
Appreciate your time
I agree with Kyle's comment and to further speed up your debug process you should note that if you use gmail to do this you can debug this process using one email.
from google/gmails perspective myaccount#gmail.com == my.acount#gmail.com == m.y.a.c.c.ount#gmail.com etc etc just try it out, google disregards all period characters in the email. you can enumerate/exhaust ~2^8 emails (in this example) if you just enumerate through the local-part of the e-mail address. but from your applications side, myaccount#gmail.com is not the same as my.account#gmail.com, ie they are different user accounts. Basically you can use one email to test out this feature of yours without having to delete the user.
Here is how I did it and finally got passed the pesky "concurrency failure" error message... This works in ASP.NET CORE 2.2
Obtain the user object through the FindByName method first.
Remove the user from their assigned Role (in this case I hard coded "Admin" because that is the role I'm interested in but fill in your own), then delete the user.
//Delete user.
//Obtain the user object through the FindByName method first.
//Remove the user from their assigned Role, then delete the user.
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
ApplicationUser delAppUser = new ApplicationUser
{
Email = "SomeEmailForindividualAdminUser",
UserName = "SomeUsernameindividualAdminUser"
};
Task <ApplicationUser> taskGetUserAppUser = userManager.FindByNameAsync(delAppUser.UserName);
taskGetUserAppUser.Wait();
Task<IdentityResult> taskRemoveFromRoleAppUser = userManager.RemoveFromRoleAsync(taskGetUserAppUser.Result, "Admin");
taskRemoveFromRoleAppUser.Wait();
Task<IdentityResult> taskDeleteAppUser = userManager.DeleteAsync(taskGetUserAppUser.Result);
taskDeleteAppUser.Wait();

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);

authenticate user in LDAP with email and password

I am new to LDAP API. I am able to connect to a LDAP server and search the user. How would I authenticate a user with email/password using UnboundID LDAP API ?
I have not seen any authentication in LDAP which uses email and password to authenticate user?
Is it Possible to authenticate the user using email and password
What I am doing to authenticate the user given as below
Searching below the USERS Directory and matching Email and Finding his DN
Based on DN connecting the user and if Connection Successful, Authenticate the user or Execption occurs in Connecting then user is not Authenticated
Is there right way to authenticate the User?
You have to do two steps.
Using an administrative login, search the directory for the user.
Using that user's DN and the password he supplied, attempt to bind.
If either didn't succeed, either the identity or the password is incorrect.
Using the UnboundID LDAP SDK, this simple piece of code searches for the entry. If there is one entry that has the known email address, BIND using that DN (the password has to come from someplace else). Nothing happens (authenticated is false) is there is more one entry that matches the search parameters or if no entries match the search parameters. This code assumes that baseObject is dc=example,dc=com, subtree search is required, and the attribute with the email address has an alias mail. The code also assumes there is a bindDN and bindPassword that has sufficient access rights to search for the user with the email address. The email address for which it searches is assumed to be babs.jensen#example.com.
Exceptions are ignored throughout.
String baseObject = "dc=example,dc=com";
String bindDN = "dn-with-permission-to-search";
String bindPassword = "password-of-dn-with-permission-to-search";
// Exceptions ignored.
LDAPConnection ldapConnection =
new LDAPConnection(hostname,port,bindDN,bindPassword);
String emailAddress = "babs.jensen#example.com";
String filterText = String.format("mail=%s",emailAddress);
SearchRequest searchRequest = new SearchRequest(baseObject,
SearchScope.SUB,filterText,"1.1");
SearchResult searchResult = ldapConnection.search(searchRequest);
boolean authenticated = false;
if(searchResult.getEntryCount() == 1)
{
// There is one entry with that email address
SearchResultEntry entry = searchResult.getSearchEntries().get(0);
// Create a BIND request to authenticate. The password has
// has to come from someplace outside this code
BindRequest bindRequest =
new SimpleBindRequest(entry.getDN(),password);
ldapConnection.bind(bindRequest);
authenticated = true;
}
else if(searchResult.getEntryCount() > 1)
{
// more than one entry matches the search parameters
}
else if(searchResult.getEntryCount() == 0)
{
// no entries matched the search parameters
}

Accounts.registerLoginHandler with passwords in Meteor

I'm new to meteor and am stuck on registering a login handler that lets me use the password to authenticate the user.
I'm working off the code from http://meteorhacks.com
The server side code is as follows:
Accounts.registerLoginHandler(function(loginRequest) {
var userId = null;
var user = Meteor.users.findOne({'emails.address': loginRequest.email, password: loginRequest.password, 'proile.type': loginRequest.type});
if(user) {
userId = user._id;
}
return { id: userId}
This works fine if I take out the password field and just use the email and type ones. How do I get this working with the password as well?
Bottom line, you can't directly search via the plaintext password. You need to verify the password via SRP which is a little tricky as there isn't any documentation on it. Luckily Meteor is open source! A good start is at the accounts-password : https://github.com/meteor/meteor/blob/master/packages/accounts-password/password_server.js
There already is a package that can do password logins for you (the one the above file is from). You can add it to your project via meteor add accounts-password.
Then you could login with Meteor.loginWithPassword

How do I access the user's password from LDAP in a LdapUserDetailsMapper using spring security?

We are using spring security in our web application based on spring MVC.
We are doing authentication using LDAP module of spring security which is working properly. Now I need to get the user password from LDAP for saving in the database.
For this I am using this in my code.
public class PersonContextMapper implements UserDetailsContextMapper {
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authorities) {
Person.Essence p = new Person.Essence(ctx);
p.setUsername(username);
p.setAuthorities(authorities);
Object passwordValue = ctx.getObjectAttribute("userPassword");
return p.createUserDetails();
}
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
Assert.isInstanceOf(Person.class, user, "UserDetails must be a Person instance");
Person p = (Person) user;
p.populateContext(ctx);
}
}
But I am not getting the any value for the password. Its always null.
Please help.
PS. My authentication is successful. It means password entered in the login form is matches properly with the password stored in the LDAP.
It might be that the authentication state of the connection does not have permission to read the value of the userPassword attribute. Most often, applications issue a BIND request to the directory server, including appropriate controls as necessary. The password is included in the BIND request and the directory server changes the authentication state of the connection upon successful completion of the BIND request. In any case, the value of the userPassword attribute is encrypted or hashed more often than not, and applications have no need to read the value.