I like to calculate the passowrd expiration date for the user in active directory
I am able to get the MaxPWdAge and LastPwdSet attributes.
But the problem is whenever i am changing the password of one of a user for testing purposes, lastPwdSet is not updating and it is still showing the old date?
Can anybody tell me why is this happen ?
public bool CheckPassWordExpiryDate(string LdapPath, string Username, string Password)
{
DomainConfiguration domainConfig = new DomainConfiguration();
// Configuration(web.config) changes
DirectoryEntry de = new DirectoryEntry("LDAP://" + LdapPath, domainConfig.UserName, domainConfig.Password);
DirectoryEntry entry = new DirectoryEntry();
entry.Username = Username;
entry.Password = Password;
//Function to get maximum password age from the active directory
int maxPwdAge = GetMaxPasswordAge();
// Function to get last password set date for the use.
DateTime pwdLastSet = GetPwdLastSet("pwdLastSet", Username);
//Add maximum password age days to Last password set days , if it is less than today's date means that password has been expired else it is not expired
if (pwdLastSet.AddDays(maxPwdAge) < DateTime.Now)
{
return true;
}
else
{
return false;
}
}
public static int GetMaxPasswordAge()
{
DomainConfiguration domainConfig = new DomainConfiguration();
using (new SPMonitoredScope("AD Properties"))
{
using (DirectoryEntry domain = new DirectoryEntry("LDAP://" + domainConfig.DomainName, domainConfig.UserName, domainConfig.Password))
{
DirectorySearcher ds = new DirectorySearcher(
domain,
"(objectClass=*)",
null,
SearchScope.Base
);
SearchResult sr = ds.FindOne();
TimeSpan maxPwdAge = TimeSpan.MinValue;
if (sr.Properties.Contains("maxPwdAge"))
maxPwdAge = TimeSpan.FromTicks((long)sr.Properties["maxPwdAge"][0]);
return maxPwdAge.Duration().Days;
}
}
}
public DateTime GetPwdLastSet(string attr, string UserName)
{
DomainConfiguration domainConfig = new DomainConfiguration();
using (new SPMonitoredScope("AD Properties"))
{
using (DirectoryEntry domain = new DirectoryEntry("LDAP://" + domainConfig.DomainName, domainConfig.UserName, domainConfig.Password))
{
//DirectorySearcher searcher = new DirectorySearcher(domain, "(|(objectClass=organizationalUnit)(objectClass=container)(objectClass=builtinDomain)(objectClass=domainDNS))");
DirectorySearcher searcher = new DirectorySearcher(domain);
searcher.PageSize = 1000;
searcher.Filter = "(SAMAccountName='" + UserName + "')";
searcher.Filter = "(|(objectCategory=group)(objectCategory=person))";
var user = searcher.FindOne();
DateTime pwdLastSet = DateTime.FromFileTime((Int64)user.Properties["PwdLastSet"][0]);
return pwdLastSet;
}
}
}
} }
Related
I would like to join the following statement with EPEmployee table on EPEmployee's BAccountID with FSAppointmentEmployee's EmployeeID column then put where condition on EPEmployee's UserID with currently logged in employee's user id in the current BQLCommand for PXAdapter, so that I can see the list of appointments that are assigned to current employee only.
public static PXAdapter PrepareCustomNavAdapter(PXAction action, PXAdapter adapter, bool prevNextAction = false)
{
var select = adapter.View.BqlSelect;
select = select
.WhereAnd<Where<EPEmployee.userID,Equal<AccessInfo.userID>>>()
.OrderByNew<OrderBy<
Desc<FSAppointment.createdDateTime,
Desc<FSAppointment.srvOrdType,
Desc<FSAppointment.refNbr>>>>>();
var newAdapter = new PXAdapter(new PXView(action.Graph, true, select))
{
MaximumRows = adapter.MaximumRows
};
object current = action.Graph.Views[action.Graph.PrimaryView].Cache.Current;
if (prevNextAction)
{
var sortColumns = new string[adapter.SortColumns.Count() + 1];
adapter.SortColumns.CopyTo(sortColumns, 1);
sortColumns[0] = "CreatedDateTime";
newAdapter.SortColumns = sortColumns;
var descendings = new bool[adapter.Descendings.Count() + 1];
adapter.Descendings.CopyTo(descendings, 1);
descendings[0] = true;
newAdapter.Descendings = descendings;
var searches = new object[adapter.Searches.Count() + 1];
adapter.Searches.CopyTo(searches, 1);
if (current != null && current is FSAppointment)
searches[0] = ((FSAppointment)current).CreatedDateTime;
newAdapter.Searches = searches;
}
else if (current != null)
{
adapter.Currents = new object[] { current };
}
return newAdapter;
}
So that, only these two employees would be able to see that appointment.
Thank you.
AccessInfo is a Singleton, you should decorate it with Current class:
Where<EPEmployee.userID, Equal<Current<AccessInfo.userID>>>
I have an ASP.NET Web Api that makes use of ASP.NET Identity v2.2.1 to manage users. I am able to add/edit users without issue. However, I have a second project that cannot make use of the API but needs to be able to change a Users password directly via the database.
I am trying to figure out how to hash the password entered by the user without going through the API. I need to make sure that I am using the same hashing algorithm that ASP.NET Identity is using. I came across some code in this SO article but I am not sure if it is the same hashing algorithm used by v2.2.1.
using using System.Security.Cryptography;
public static string HashPassword(string password)
{
private const int PBKDF2IterCount = 1000; // default for Rfc2898DeriveBytes
private const int PBKDF2SubkeyLength = 256 / 8; // 256 bits
private const int SaltSize = 128 / 8; // 128 bits
if (password == null)
{
throw new ArgumentNullException("password");
}
// Produce a version 0 (see comment above) text hash.
byte[] salt;
byte[] subkey;
using (var deriveBytes = new Rfc2898DeriveBytes(password, SaltSize, PBKDF2IterCount))
{
salt = deriveBytes.Salt;
subkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
}
var outputBytes = new byte[1 + SaltSize + PBKDF2SubkeyLength];
Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, PBKDF2SubkeyLength);
return Convert.ToBase64String(outputBytes);
}
I would like to avoid having to add ASP.NET Identity as a dependency to this project hence why I would like to hash the password manually.
I would recommend you to use SimpleCrypto
This is how I've used that in a project I believe this will help you. One can add this DLL from nuget
[HttpPost]
public ActionResult Register(RegisterViewModel model)
{
try
{
if (ModelState.IsValid)
{
{
var crypto = new SimpleCrypto.PBKDF2();
var encrypPass = crypto.Compute(model.Password);
var newUser = db.Users.Create();
newUser.Email = model.Email;
newUser.Password = encrypPass;
newUser.PasswordSalt = crypto.Salt;
// newUser.Name = model.UserName;
newUser.Username = model.UserName;
//newUser.AddedBy = model.;
db.Users.Add(newUser);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "");
}
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
return View();
}
Your valid check at login will be like this
private bool IsValid(string email, string password)
{
var crypto = new SimpleCrypto.PBKDF2();
bool isValid = false;
{
var user = db.Users.FirstOrDefault(u => u.Email == email);
if (user != null)
{
if (user.Password == crypto.Compute(password, user.PasswordSalt))
{
isValid = true;
}
}
}
return isValid;
}
DirectorySearcher deSearch;SearchResultCollection result;
deSearch.SearchRoot = baseResult.GetDirectoryEntry();// I know this one can be done like - PrincipalContext pContext = new PrincipalContext(ContextType.Domain, deSearch.SearchRoot.Path);
deSearch.Filter = "(&(&(objectClass=user)(objectCategory=person))(name=" + name + "))"; //???? **Not sure how to apply the filter in Principal Context**
results = deSearch.FindAll();
Please help me in applying filter in principlecontext
You can use PrincipalSearcher to search for a particular user.
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
UserPrincipal searchUser = new UserPrincipal(ctx);
searchUser.GivenName = "Name";
PrincipalSearcher srch = new PrincipalSearcher(searchUser);
foreach(var found in srch.FindAll())
{
//found will contain the info
}
}
You can also use UserPrincipal.
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.DistinguishedName, "DN"))
if (user != null)
{
//user contains info
}
}
You can define different IdentityType if you want to search by samAccountName or etc.
I'm trying to create a new user using the CoSign SPML WS.
The code I'm using (C#.NET) is below. Can someone please let me know if the PSOIdentifierType.ID is correct (i.e. "The ID of the User") and what should the Target ID be, I think it should be blank as the user does not exist yet.
private const readonly string addTargetDB = "CoSignDB";
public void CreateBasicUser(string userName, string userLoginName, string userPassword, string userCN, string userEmail)
{
SPMLSoapClient client = new SPMLSoapClient();
AddRequestType request = new AddRequestType();
PSOIdentifierType psoCreationType = new PSOIdentifierType();
psoCreationType.ID = userName;
psoCreationType.targetID = ""; //The parameter that was returned in the ListTargets operation
UserRecord newUserRecord = new UserRecord();
newUserRecord.UserLoginName = userLoginName;
newUserRecord.Password = userPassword;
newUserRecord.UserCN = userCN;
newUserRecord.EmailAddress = userEmail;
newUserRecord.RightsMask = (uint)1; // 1 - User
newUserRecord.UserKind = UserKindEnum.User;
request.returnData = ReturnDataType.everything;
request.targetID = addTargetDB;
request.psoID = psoCreationType;
request.UserRecord = newUserRecord;
AddResponseType clientAddResponse = client.add(request);
if(clientAddResponse.status == StatusCodeType.success)
{
// OK
}
else if(clientAddResponse.status == StatusCodeType.failure)
{
// Fail
}
}
The id of the user is correct (it should be the username) and the TargetID should be "CoSignDB"
I have been breaking my head over this. Please take a look at this code. This code is in the customer controller.
[HttpPost]
[Themed]
public ActionResult Register(string email, string password, string confirmPassword, Gender gender, string givenName, string familyName, string insertion, DateTime birthDate) {
ViewData["PasswordLength"] = MinPasswordLength;
var shape = _orchardServices.New.Register();
//1. Initialize new content of customer contenttype
var customer = _orchardServices.ContentManager.New("Customer");
if (customer != null) {
//2. Define the parts that need to be filled
var userPart = customer.As<UserPart>();
var customerPart = customer.As<CustomerPart>();
//3. Let's validate first if the user can be created
if (userPart!=null) {
//shape.Customer = _orchardServices.ContentManager.UpdateEditor(customer, this);
if (!ModelState.IsValid)
{
_orchardServices.TransactionManager.Cancel();
return new ShapeResult(this, shape);
}
//4. Now validate the user credentials.
if (ValidateRegistration(email, password, confirmPassword)) {
//Now create the actual customer.
userPart.UserName = email;
userPart.Email = email;
userPart.NormalizedUserName = email.ToLowerInvariant();
userPart.Record.HashAlgorithm = "SHA1";
userPart.Record.RegistrationStatus = UserStatus.Approved;
userPart.Record.EmailStatus = UserStatus.Approved;
customerPart.CreatedAt = DateTime.UtcNow;
customerPart.LastLogonAt = DateTime.UtcNow;
_membershipService.SetPassword(userPart, password);
var user = customerPart.User;
_authenticationService.SignIn(user, false /* createPersistentCookie */);
return Redirect("~/");
}
}
}
When this code is run, I end up with two entries for UserPart in my database. One with a related CustomerPart and one not.