I have a serious problem authenticating my user against AD. I can use the PrincipalContext way or the DirectoryEntry way and check whether login was successful or not. But this is not enough for my case. I need to know why authentication failed(eg: password expiration, account locked, bad password count limit). Is there anyway of achieving this without using native win32 dll's. By the way this may not be a web project all the time. My optimal solution could be a generic one.
Thanks for any help...
You should get the reason for the error in the exception.
Regardles of that you get the information if authentication will fail by using the PrincipalContext members like:
AccountExpirationDate (is the account expired)
AccountLockoutTime (is the account locked)
Enabled (is the account enabled)
IsAccountLockedOut (is the account locked)
PermittedLogonTimes (is the user allowed to login now)
PermittedWorkstations (is the user allowed to login from this client)
Related
I'm trying to access the groups a user is a member of using the Microsoft Graph API.
I'm facing an issue because I think my permissions are set correctly, however, when I sign into the app, I get the message :
AADSTS90093: Calling principal cannot consent due to lack of permissions.
The weird thing is that I'm only asking for this permission scope :
public static String[] ClientScope = { "User.Read", "User.ReadBasic.All", "Group.Read.All"};
What makes me confused is that if I sign in the Microsoft Graph explorer and go to https://graph.microsoft.com/v1.0/me/memberOf ,
I get the correct results.
I got an admin to consent to the permissions I'm asking in the scope of course.
Has anyone encountered that issue ?
Any idea how I should correct that ?
The memberOf API requires one of the following scopes:
Directory.Read.All
Directory.ReadWrite.All
Directory.AccessAsUser.All
Regardless of which of these scopes you choose, they all will require administrative consent before a regular user can authorize them. To do this, you'll first need to have them go through the “Admin Consent” workflow. This workflow requires an administrator but once complete any users of your application will have “admin consent” to the restricted scope.
For example, you would normally you would then authenticate users by redirecting them to
https://login.microsoftonline.com/common/oauth2/authorize?<your params>.
Since this scope requires an Admin however, you fist need to obtain consent by first having an Admin authenticate by redirecting them to
https://login.microsoftonline.com/common/adminconsent?<yours params>.
Once an Admin grants consent, normal users will be able to use OAUTH to authenticate.
I have implemented Active Directory authentication in my application and it is working properly.
But when entering an incorrect password five times, the account gets locked.
Is there any possible way to avoid account locking for the invalid authentication?
Thank u,
Ganesh. K
Your code won't have control over that because this is an Active Directory password policy settings.
Active Directory Account Lockout is controlled by the the Domain Policy, a Group Policy Object (GPO) linked to the domain.
You can change the policy.
Lockouttime can only triggered by the system itself.
You may also un-lock an account by setting the Lockouttime attribute to "0".
If a domain AD user account is hidden * and expired, is there a way to change the password (not reset) in .net / c# ?
The code I have currently is using System.DirectoryServices.AccountManagement and is essentially something like
using (var context = PrincipalContext(ContextType.Domain, server, container)
{
var directoryUser = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
directoryUser.ChangePassword(oldPassword, newPassword);
}
This works OK for users that the application service account can find, but some "hidden" users are in OUs that the application service account does not have read permissions to - and hence this fails with a null user.
I thought I would change it so that the PrincipalContext is established with the username and password of the user themselves (since they will have permissions to find themselves) - but often the account is expired by the time they come to change their password and so the FindByIdentity call fails as invalid credentials since the account is expired..
It's kind of a catch-22 where I can't find the user unless I search as the user, but I can't search as the user since they are expired, and I can only unexpire them by getting them to change their password.
If they have access to a workstation they can change their password using the Windows login controls but how to achieve this same level of functionality in c#?
EDIT1: I'm hoping for a solution that does not involve a service account with read-access to the hidden OUs - that would be difficult to achieve for various organization reasons.
Thanks for reading and for your thoughts; this is a hairy problem, so I thought I'd share to see if it is actually a fair challenge for more seasoned developers than ourselves.
We're developing a web application for a corporate Microsoft Active Directory environment, and we use Windows Authentication provided by IIS to authenticate users for single-sign-on, alongside Forms Authentication. I know IIS complains when both are enabled, but it works very well, and every site we've deployed at has had no weird quirks to work around - until now.
The new site has "shared" machines, logged in permanently with a generic account that has read-only access to the applications they need to use. This means that we can't differentiate between users who should have different permissions to the application; we need some way of prompting the user for authentication details.
First try was some serious googling; nobody else in the world seemed to have our problem except for a few misguided souls who had asked questions into the ether and received no response.
After a bit of brainstorming and nutting out the way IIS's authentication works, it seemed that the most straightforward way to approach the problem was to issue a 401 Unauthorized in response to a user known to be a shared account. Initial tests here seemed fruitful, yielding successful changes of username inside the browser, however a prototype at the site did not prompt for credentials, and the browser kept the same account details. We also hit on the IE-specific javascript
document.execCommand("ClearAuthenticationCache")
which, again, worked in the lab but not onsite. Further experiments with IE security settings onsite revealed that the browser would automatically reauthenticate if the webapp site was excluded from the Intranet Zone, regardless of the method used to trick the browser into prompting the user for new account details.
Now we're stuck. We've got workaround options for getting it going on time, but they're definitely not the "right" answers:
require users to log out of the shared account before logging into our app (...yuck)
exclude our webapp from Intranet Zone on all machines
provide a non-SSO login service for users
I'm convinced that there's a canonical way to do this - a known pattern, a common base problem that's already been solved, something like that - and I'm very interested to hear what sort of inventive methods there are to solve this sort of problem, and if anyone else has actually ever experienced anything remotely like it.
We ended up settling on a solution that submits a query to the LDAP directory the server knows about. It means having to accept the user's password, but no other solution was solid enough to run in a production environment.
Hopefully this helps someone. .NET Framework 3.5+ required.
using System.DirectoryServices.AccountManagement;
private static bool IsLdapAuthenticated(string username, string password)
{
PrincipalContext context;
UserPrincipal principal;
try
{
context = new PrincipalContext(ContextType.Domain);
principal = Principal.FindByIdentity(context, IdentityType.SamAccountName, username) as UserPrincipal;
}
catch (Exception ex)
{
// handle server failure / user not found / etc
}
return context.ValidateCredentials(principal.UserPrincipalName, password);
}
Could you not create a page to which the shared accounts are denied access. Then do a redirect to that page, with a return URL encoded in the query string, at any point where you need the user to reauthenticate with a non-shared account? This should trigger the browser to put up the usual login dialog.
After the user reauthenticates, the new page should just redirect back to the return URL in the query string.
I have some code in asp.net ( kindly given by someone else ) to query AD to get user name and email etc.
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using ActiveDs;
DirectorySearcher search = new DirectorySearcher(new DirectoryEntry(), string.Format("(samaccountname={0})", id));
if (search == null)
return id;
if (search.FindOne() == null)
return id;
DirectoryEntry usr = search.FindOne().GetDirectoryEntry();
IADsUser oUsr = (IADsUser)usr.NativeObject;
return string.Format("{0} {1}", usr.Properties["givenname"].Value, usr.Properties["sn"].Value);
However this requires impersonation with an id that's required to be changed every 2 weeks and then updated in the web.config which is often forgotten
Is there any non impersonation code to achieve the same result ?
UPDATE - it's a config tool and it looks up name, email id etc.
I like the service a/c idea
Q - How is it possible to run ( impersonate ) just the AD code with a "service" a/c ? any samples/code ?
how do you impersona
For your particular purpose, a ServiceAccount shall be added to AD;
If you ASP.NET application is for a LAN in your organization, you could simply forget about providing Username and Password and only provide the root domain. This way, Active directory will search for Windows authenticated user instead of using impersonnation (this assumes that the user accessing your application has the rights to perform the tasks provided by your application).
What exactly does your application need to do?
If your application manages user accounts, groups and OU, then you need to use impersonnation only if the user doing these tasks through the application has no rights of managing the AD with her/his regular user account. This, should not happen. So, event for this, if the user has the proper rights, omitting your credentials will only allow AD to search for the current logged on user.
We usually request IT to give us a domain service account. You still need to impersonate, but with a service account, the password will not have to be changed every 2 weeks, and is granted specific rights for the particular function you need it for, so it would mean very low maintenance for you.
I don't think so, because you need to bind to the domain with valid credentials in order to read from active directory.
Think of the username/password as part of a connection string to a database. I'd request a complex username and password from your domain administrator and request that they give it limited login permissions and set the password to never expire. Then store and use those in your Web.config file.