Redirect digest request to active directory - c#

I am trying to redirect an http request with digest MD5 header information to an active directory to validate the credentials.
I do have the information given by the http header like nonce and username. My problem now is that I have no link to put this information into a PrincipalContext object.
I obviously can't use PrincipalContext.ValidateCredentials(username, password) cause it requires the password in plain text.
The only validation that I am able to use is UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);, but this does not include the password.
I do have a HttpListenerContext object. But the user variable is null.

After I told my server to user AuthenticationSchemes.IntegratedWindowsAuthentication he automaticaly deliveres a WindowsPrincipal, which provides information from the AD.

Tim once you get the information you can do something like this to check if is Valid or not If I am understanding what you want to test properly then try something like this
if you are running this via code or a service you should have no issues with the password in regards to being exposed ..if you are concerned about that then you need to write something that will decrypt the MD5 Header Information where the pass word is.
using(PrincipalContext prContext= new PrincipalContext(ContextType.Domain, "Your Domain"))
{
bool isValid = prContext.ValidateCredentials("Username", "Password");
}

Related

Verify an AD users PrincipalContext on server-side connection

To preface, I've got a client and a server program, and the client connects to the server over SSL.
I'm looking for a way to verify, with Active Directory, a PrincipalContext or UserPrinicpal that is passed to a server, over the SSL tunnel. This is to verify the identity of the client. Does anyone know how I would go about doing this?
Or, does anyone know of a different/simpler way of doing this?
NOTE: If you want to authenticate user using LDAP, then it has already been answered here for how to "Validate a username and password against Active Directory?".
From what I can understand from your question, you simply want to search if the user exists in AD.
On the basis of my assumption, I've given a similar answer here on C# PrincipalContext only changes password for some users, not all, but that is a step-ahead of what you require. The subset of that answer answers your queries.
Sample code:
try
{ // assuming _userID is the user-id to be checked in AD.
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, "domain.name", "DC=domain,DC=name", ContextOptions.SimpleBind, "bindUserID", "bindPassword");
UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, _userID);
if(null != oUserPrincipal){
// user-id found and valid, continue further.
// If you want to authenticate user, go as per NOTE section in my answer instead.
}
else{
// return the message that the user-id could not be found.
// preferably the user-id should be **SamAccountName**
}
}
catch (Exception e)
{
message = e.ToString();
}
EDIT (Based on your comment):
J. Doe -> Despite the flack this might get me...It's going to be a broker
between a DMZ and clients on an internal network.
It seems you're looking for something like ADFS. Read more about ADFS from MSDN.

How to tell if SPUser is Active Directory account

I'm working on a project where the client wants to restrict some content to only Active Directory users . Is there any way to identify that a SPUser is an AD user short of parsing the username string for the domain (or something along those lines). Something like SPUser.IsADUser would be awesome.
Edit
This seems to work, but I'm not sure if this is reliable enough? For this use case, identifying that a user is a windows user is enough (there are no local system accounts)
SPUser user = SPContext.Current.Web.CurrentUser;
string userName = user.LoginName.Substring(user.LoginName.IndexOf('|') + 1);
SPPrincipalInfo info = SPUtility.ResolveWindowsPrincipal(SPContext.Current.Site.WebApplication, userName, SPPrincipalType.User, false);
if(info != null){
//THIS IS A WINDOWS ACCOUNT
}
In my experience it is much better to use audiences for this purpose. You then can easily trim any web part using "Audience" property. You can read about audiences here. Of course it will only work if you have user profile synchronization configured.

How to allow Unauthenticated users to reset password?

Please see Update Below:
I am using ASP.NET SQL Membership Provider.
So far I am able to allow users to change their password but only if they are authenticated or logged into the application.
What I really need is for users to be able to get a link in an email. They can click this link and reset their password.
Example: Lets say a user forgets his or her password, they can visit a page which they can either enter security question and answer; or their email address on file. They will then get an email with a link to reset their password.
All I have so far is this: Which allows only authenticated users to reset their passwords:
I do not want to use the Recovery Control which generates a password.
public void ChangePassword_OnClick(object sender, EventArgs args)
{
MembershipUser user = Membership.GetUser(User.Identity.IsAuthenticated);
try
{
if (user.ChangePassword(OldPasswordTextbox.Text, PasswordTextbox.Text))
{
Msg.Text = "Password changed.";
}
else
{
Msg.Text = "Password change failed. Please re-enter your values and try again.";
}
}
catch (Exception e)
{
Msg.Text = "An exception occurred: " + Server.HtmlEncode(e.Message) + ".
try again.";
}
}
I can create the store procedure and the email using a String Builder but I do not know how to get the un-authenticated user to change password. Is there a way for the user to be Authenticated when they click the link. I am not sure how to even ask this.
Thanks for reading:
Update:
Okay I managed to get the password to Reset using this code:
protected void btnResetPassword_Click(object sender, EventArgs e)
{
string username = "ApplePie12";
MembershipUser currentUser = Membership.GetUser(username);
currentUser.ChangePassword(currentUser.ResetPassword(), txtResetPassword.Text);
}
Here is my plan:
Make this page public so that it is access by Un-Authenticated Users but only via email link.
Create a Stored Procedure that verifies a user Exists either by the UserName they enter or by the Security Question/Answer.
If they exists, they are sent a link containing a token/GUID
Lastly when they click the link they will land on this page asking them to change password. *The Link Expires as soon as it is used.
My only question is: Doing all of the above requires turning off using security Question/Answer in the Web Config file.
I really would love to have the Security question as an option for the user to either verify by email or security question. If this is not possible, I'll have to create some kind of account number or userid (not membership user id) as an alternative.
My answer is not specific to Membership Provider, but hopefully will point you in the right direction. Typically the way to approach this is to generate a very long random string, called a token. You send them a link that includes this token as a parameter, something like:
http://foo.bar/reset?token=asldkfj209jfpkjsaofiu029j3rjs-09djf09j1pjkfjsodifu091jkjslkhfao
Inside your application you keep track of tokens you have generated. If you receive a request containing that token, you authenticate it as if it was that user.
A couple notes:
The token generated should be random and effectively unguessable in a short period of time.
The token should only work for a short period of time after being generated, ideally shorter than the time required to guess it.
The token should only be usable once. Once a user has changed their password using it, remove it from the system.
Chris has given definitely the correct solution.
You can use the sql table for token management. the token may be UserId or Email that are unique. the link used for reset email like http://test.com/reset?id=sfksdfh-24204_23h7823.
The id in the url is encrypted Userid or Email as you like.
Fetch the detail from table on the basis of id in Url. if id contain in database. then reset the password for user. and remove that token from DB.

Setting user password using C# does not work, any ideas?

I need to reset a user password. to do so, I use the following code:
DirectoryEntry de = ..
de.AuthenticationType = AuthenticationType.Secure
de.Password = txtPassword.text
de.CommitChanges()
When i run the code - nothing happens. The user password does not change, and no exception is thrown.
if i use the following method:
de.Invoke("SetPassword", .. );
when i run the code, I get a message that says: Please insert smartcard ...
I have admin privilages over the user account.
The user does not have UAV set for smart card.
Any ideas ?
The Password property of the DirectoryEntry class isn't what you think it is. You're not changing the user's password, you're changing the password you're using to access further information from the DirectoryEntry object.
From the MSDN documentation:
You can set the Username and Password properties to specify alternate
credentials with which to access the information in Active Directory
Domain Services. Any other DirectoryEntry objects retrieved from this
instance (for example, through Children) are automatically created
with the same alternate credentials.
With your second method, if you're being asked to insert a smartcard I doubt that has anything to do with the user you're modifying - it's more likely it's asking for your smartcard. If you're not set up to use smartcards either, then I'm really not sure why it's asking you for one at all.
Take a look at this related question and see if the answers there help.

Authenticate user by ADFS (Active Directory Federation Service)

I need to check whether particular user exist OR not in Active Directory by ADFS.
So, I want my ADFS to check user Authentication by UserName/Password.
Could anybody please provide the sample code OR tutorial for the same.
Thanks in advance!
To use Username/Password authentication you can use the
trust/13/UsernameMixed
endpoint of the ADFS 2.0.
This does NOT check if the user exists in the Active Directory!
In code you request the token like this:
WSTrustChannelFactory adfsfactory = new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
StsEndpoint);
adfsfactory.TrustVersion = TrustVersion.WSTrust13;
// Username and Password here...
factory.Credentials.UserName.UserName = "domain\username";
factory.Credentials.UserName.Password = "password";
IWSTrustChannelContract channel = adfsfactory.CreateChannel();
// request the token
SecurityToken token = channel.Issue(rst);
Then create the channel factory for your service using your token:
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message);
var factory = new ChannelFactory<IYourInterface >(binding, "your service address");
factory.ConfigureChannelFactory();
IYourInterface channel = factory.CreateChannelWithIssuedToken(token);
Hope this helps!
The AD FS 2.0 sign-in pages support username/password authentication out of the box. No code or customizations necessary.
As per #Marnix, this is out the box behavior.
However, just to point out:
Authenticating the user is NOT the same as checking whether a particular user exists in Active Directory.
e.g. the user could be locked out. He still exists in AD but will not be able to authenticate.

Categories