AD Authentication Login page - asp.net

I am creating a helpdesk as a side project and have made a small login page with 'usernameTXT' and 'passwordTXT' textboxes.
I would like the username and password to authenticate against my AD server on my domain:
domain - home.local
dc - home-serv
I have tried all of the LDAP examples online with no luck. Could I be doing something wrong?
Please could someone help me to get ms site to authenticate with the domain? I would like all users to be able to login to the system.
Thanks!

Try something like this
Public Function Authenicate(ByVal username As String, ByVal password As String) As Boolean
Dim isValid As Boolean = False
Try
Dim de As New DirectoryServices.DirectoryEntry("LDAP://local.home", username, password, _
DirectoryServices.AuthenticationTypes.Secure Or _
DirectoryServices.AuthenticationTypes.Sealing Or _
DirectoryServices.AuthenticationTypes.Signing)
de.RefreshCache()
isValid = True
Catch
End Try
Return isValid
End Function

Related

WebClient.DownloadFile returns login page even when credentials are provided

I am trying to download a file that is behind a login page. I have looked into many ways to add credentials but the response is always the log in page's html. I have tried 2 passes with client.uploadValues or client.uploadstring to get a cookie and a single pass just providing credentials.
Public Sub downloadImage()
Dim username As String = "xxxxx"
Dim password As String = "xxxxx"
Using client As New WebClient()
client.Credentials = New NetworkCredential(username, password)
client.DownloadFile("https://retailerservices.domain.com/Image/ItemHighRes/26634/1", AppDomain.CurrentDomain.BaseDirectory & "test.jpg")
End Using
End Sub
Any recommendations?

How do I log a user back in after change of Email/Username? - Asp.net/VB.Net

I found this code on a site which was written for me and works, and I'm trying to use it on a new site. The code checks that a emailAddress doesn't already exist when a user edits their account details, and because the emailAddress is also used as the underlying .NET membership username it needs to change that too. So far I've managed to get it to change the email address in tblAccounts which is done with this call:
acc.UpdateUsername(txtEmailAddress.Text, lblEmailAddress.Text)
Then it needs to check if the user changing the email is the logged in user and re-log them back in. This doesn't seem to work as I get this error from the siteMaster when it tries to redirect to the homepage:
System.NullReferenceException: Object reference not set to an instance of an object.
The error is caused in the siteMaster when it tries to check messages for logged in user and it flags up the last line of this as where the error occurs:
If HttpContext.Current.User.Identity.IsAuthenticated Then
hypSettings.visible=true
Dim counter As Integer = messaging.CheckUnreadMessages(Membership.GetUser.ProviderUserKey)
It therefore looks like the email address is being updated where it should, but the site isn't logging the user back in correctly. As I say, it works on the site where I took the code from and there isn't much difference between the sites, but I don't understand memberships and cookies too well so I'm not sure if something needs altering elsewhere?
Here's the code for changing the users email address:
'Check if the Role has been changed
Membership.ApplicationName = "/OCBS"
Dim userID As Guid = Guid.Parse(Request.QueryString("aID"))
Dim usr As MembershipUser = Membership.GetUser(userID, False)
'Now check if the email address has been changed, because the email address is used for the username then the underlying .NET membership username needs changing
If txtEmailAddress.Text <> lblEmailAddress.Text Then
'Email has been changed, update the username for this user
Dim acc As New accounts(Guid.Empty)
acc.UpdateUsername(txtEmailAddress.Text, lblEmailAddress.Text)
'Check if the user changing the email is the logged in user and re-log them back in
If User.Identity.Name = lblEmailAddress.Text Then
'FormsAuthentication.SetAuthCookie(txtEmailAddress.Text, False)
Response.Cookies.Clear()
Dim expiryDate As DateTime = DateTime.Now.AddDays(100)
Dim ticket As New FormsAuthenticationTicket(2, txtEmailAddress.Text, DateTime.Now, expiryDate, True, [String].Empty)
Dim encryptedTicket As String = FormsAuthentication.Encrypt(ticket)
Dim authenticationCookie As New HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
authenticationCookie.Expires = ticket.Expiration
Response.Cookies.Add(authenticationCookie)
End If
End If
Oooh, I've managed it.. I added this..
Session.Abandon()
FormsAuthentication.SignOut()
after line: Response.Cookies.Clear()

SSO with Azure ADFS and OWIN

Thank you for providing help. I have a site that can authenticate with Active Directory Federated Services for Single Sign On. Currently, the way my site works is that, by default, when a user hits my site, my code attempts to log then into SSO (I use the OWIN library for this). If the user is not on our network, it fails to authenticate, and they are redirected to my companies login page, where they can provide their company credentials.
I would like to change this behavior, though. Instead, when the user hits my page, if they authenticate, it should continue as normal and they should be redirected to my site. But, if they do not authenticate, I do not want them redirected to our login page. instead, I want them to be redirected back to my site, where my code will determine what they can and cannot do on the site. I then would want to provide a link, so that they could decide to go to the login page.
I want this behavior because the majority of users of this site will not be a part of the companies network and will not be able to authenticate. SO, they should, by default, just see our home page. But, there may be times when a company member might be working from home, so wont be on our network to auto authenticate. In this case, they would then use the link that sends them to the Azure login page.
Here is the code that I am currently using (site is ASP.net, form web page (not MVC)):
Startup.Auth.vb:
Partial Public Class Startup
Dim appSettings = ConfigurationManager.AppSettings
Private realm As String
Private aadInstance As String
Private tenant As String
Private metadata As String
Private authority As String
Public Sub ConfigureAuth(app As IAppBuilder)
Try
Dim appSettings = ConfigurationManager.AppSettings
If (appSettings("releaseVersion") = "DEBUG") Then
realm = ConfigurationManager.AppSettings("test_ida:RPIdentifier")
aadInstance = ConfigurationManager.AppSettings("test_ida:AADInstance")
tenant = ConfigurationManager.AppSettings("test_ida:Tenant")
ElseIf (appSettings("releaseVersion") = "PROD") Then
realm = ConfigurationManager.AppSettings("ida:RPIdentifier")
aadInstance = ConfigurationManager.AppSettings("ida:AADInstance")
tenant = ConfigurationManager.AppSettings("ida:Tenant")
End If
metadata = String.Format("{0}/FederationMetadata/2007-06/FederationMetadata.xml", aadInstance)
authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant)
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType)
app.UseCookieAuthentication(New CookieAuthenticationOptions())
Dim authOption As WsFederationAuthenticationOptions = New WsFederationAuthenticationOptions()
Dim fn = Function(context)
context.HandleResponse()
context.Response.Redirect("Home/Error?message=" + context.Exception.Message)
Return Task.FromResult(0)
End Function
Dim auth_not As WsFederationAuthenticationNotifications = New WsFederationAuthenticationNotifications() With {
.AuthenticationFailed = fn
}
Dim auth_opt As WsFederationAuthenticationOptions = New WsFederationAuthenticationOptions() With {
.Wtrealm = realm,
.MetadataAddress = metadata,
.Notifications = auth_not
}
If (Not auth_opt.Wtrealm Is Nothing) Then
app.UseWsFederationAuthentication(auth_opt)
Else
End If
Catch ex As Exception
Throw ex
End Try
End Sub
End Class
Then, on my Default.aspx.vb page load event, I do this:
If (Not Request.IsAuthenticated) Then
Try
Dim newAuth As AuthenticationProperties = New AuthenticationProperties()
newAuth.RedirectUri = "/"
HttpContext.Current.GetOwinContext().Authentication.Challenge(newAuth, WsFederationAuthenticationDefaults.AuthenticationType)
Catch ex As Exception
Throw ex
End Try
End If
The problem is, I do not know how to attempt to authenticate the user, determine if they are authenticated, and redirect them accordingly. Any help would be greatly appreciated.
thanks
There is not solid/correct way how to check if anonymous user is inside your network(or I am not aware of one). Possible way is to check IP address (range) users inside your network have publicly on the Internet. This is something you can check with network administrator(s). They may tell you public IP address (range).
Once you know public IP address (range) you can check incoming request to compare if the request is coming from the known reange of IP address (range) inside RedirectToIdentityProvider function.
Dim redirectToIdentityProvider = Function(context)
Dim isCompanyNetworkUser = companyIPAddress == context.Request.RemoteIpAddress
' Or relevant check for range
' Dim isCompanyNetworkUser = (companyIPAddressRangeStart < context.Request.RemoteIpAddress AndAlso companyIPAddressRangeEnd > context.Request.RemoteIpAddress
If Not isCompanyNetworkUser Then
context.State = NotificationResultState.Skipped
context.HandleResponse()
End If
End Function
Dim auth_not As WsFederationAuthenticationNotifications = New WsFederationAuthenticationNotifications() With {
.AuthenticationFailed = fn
.RedirectToIdentityProvider = redirectToIdentityProvider
}
You may want to tweak it a bit as I didn't try it, but may point you to right direction.
Sorry to not providing full code example, but in my opinion :
You may try to bypass the sign-in page prompts, take a look here, which explain you how to :
bypass the sign-in page prompts by adding your company’s existing federated domain name to the end of the Windows Azure Management Portal URL
You may also find usefull information relative to Azure Active Directory Pass-through Authentication which allow that:
When users sign in using Azure AD, this feature validates users' passwords directly against your on-premises Active Directory.
You may also make appear your website as an "application" then added this app to your Azure Active Directory application gallery. then Managing single sign-on for enterprise apps
I found finally that this question may be relative to your question.

ASP application using the saved credentials even after the user cleared the username and password textboxes and hits submit

Could anyone please help, I have an asp application that asks for username and password in the login.aspx page and after logging in with the correct credentials, it prompts me whether to save the credentials. I clicked yes and after some time I logged out, then it takes me to the login.aspx page with the (saved) username and password already filled automatically in the boxes(because I saved previously above). Now my problem is that, now I cleared the username and password that are filled automatically in the boxes and hit submit. Then it should ask for username and password, but now actually it is using the old saved username and password and logging into the application !!!!
*To make it more brief and clear, this is the problem :-
"I am able to login even though I have removed the username and password. I logged out. Erased the content of both fields and then clicked 'Submit'. I was able to get into the Application."
Could anyone help please . Thanks in Advance !!!!
Here's my code for the 'Submit' button 'OnClick' Event :-
Protected Sub SignIn(sender As Object, e As EventArgs)
StatusText.Text = String.Empty
Dim Name As String = UserName.Text
Dim Password As String = UserPassword.Text
If IsValid Then
Try
Dim userStore = New UserStore(Of IdentityUser)()
Dim userManager = New UserManager(Of IdentityUser)(userStore)
userManager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(10)
userManager.MaxFailedAccessAttemptsBeforeLockout = 7
Dim user = userManager.FindByName(Name)
If user IsNot Nothing Then
If userManager.IsLockedOut(user.Id) Then
StatusText.Text = String.Format("Your account is locked. please contact administrator.")
Else
If userManager.CheckPassword(user, Password) Then
userManager.ResetAccessFailedCount(user.Id)
If Not userManager.GetLockoutEnabled(user.Id) Then
userManager.SetLockoutEnabled(user.Id, True)
End If
Dim tkt As FormsAuthenticationTicket
Dim cookiestr As String
Dim ck As HttpCookie
'Add Session to 5 Hours
tkt = New FormsAuthenticationTicket(1, user.UserName, DateTime.Now, DateTime.Now.AddHours(5), RememberMe.Checked, "")
cookiestr = FormsAuthentication.Encrypt(tkt)
ck = New HttpCookie(FormsAuthentication.FormsCookieName, cookiestr)
If RememberMe.Checked Then
ck.Expires = tkt.Expiration
End If
ck.Path = FormsAuthentication.FormsCookiePath
Response.Cookies.Add(ck)
Dim strRedirect As String
strRedirect = Request("ReturnUrl")
If strRedirect Is Nothing Then
strRedirect = "default.aspx"
End If
Response.Cookies.Add(New HttpCookie("adjusterId", New ContextProvider().GetAdjusterId(user.Id)))
Response.RedirectPermanent(strRedirect)
Else
userManager.AccessFailed(user.Id)
If userManager.IsLockedOut(user.Id) Then
StatusText.Text = String.Format("Your account is locked. please contact administrator.")
Else
StatusText.Text = String.Format("Invalid username or password, you have {0} more login attempt(s) left before account is locked out.", (3 - userManager.GetAccessFailedCount(user.Id)))
StatusText.Visible = True
End If
End If
End If
Else
StatusText.Text = String.Format("Invalid username or password.")
StatusText.Visible = True
End If
Catch ex As Exception
StatusText.Text = String.Format("Unable to login, please contact administrator.")
End Try
Else
StatusText.Text = String.Format("Enter username or password.")
End If
End Sub
Likely the authentication cookie is being remembered, after the initial login, and that still exists.
Somehow when you attempt to login with empty fields, it just uses the cookie instead of the empty fields. That would be my guess.
my best guess is that this method is where you will find the culprit code:
userManager.AccessFailed(user.Id)
It could also be a redirect problem. That you simply attempt to redirect the user back to a page on an invalid login, and since the cookie is still set, you are allow to see whatever page you are getting redirected too.
Main problem, your logout function doesn't remove the authentication cookie.
after a lot of banging, I found out a simple change that fulfilled my requirement, I just added the below properties for my 'username' textbox in .aspx as below :-
<asp:TextBox ID="UserName" runat="server" Width="295px" AutoCompleteType="None" EmptyMessage=" "></asp:TextBox>
(added AutoCompleteType and EmptyMessage).
Not sure whether that's the right approach, but that helps !!!! ThankYou.

Validate ASP.NET membership Username and Password when IsApproved is false

How can I check if the password entered by the user matches the password stored in the database when the IsApproved value is FALSE?
What I hope to do is as follows...
User registers - details saved and IsApproved is set to false
User recieves welcome email with membership confiirmation link
User clicks link in email - IsApproved is set to True at this point
User can NOW login
Okay everyting is fine with all of the above and i dont percieve any problems.
Where I'm having issues is...
When the user attempts to login and his/her IsApproved flag is FALSE
I need to cross reference his/her password wih the one stored in DB
And thats where i'm stuck.
The idea was to cross check the password, and if the user entered VALID credentials then to show a message to the user to say ACTIVATE your membership by clicking in the email blah blah blah.
But even if the password entered matches, because I cannot check it in the code the ValidateUser function always returns false because IsApproved is set to false!
Can anyone point me in the right direction please?
ALSO I dont actually need to see the password, so even if theres a sealed function I can call that simply confirms if the pasword matches thats fine too...
Below is my code block..
Public Function ValidateUser(ByVal Username As String, ByVal Password As String, ByRef PwdMatches As Boolean, ByRef Approved As Boolean) As Boolean Implements IMembershipService.ValidateUser
'
Dim ThisMember As MembershipUser = Nothing
Dim ThisResult As Boolean = Nothing
'
Approved = False
ThisResult = False
PwdMatches = False
If String.IsNullOrEmpty(Username) Then
Throw New ArgumentException("Value cannot be null or empty.", "Username")
ElseIf String.IsNullOrEmpty(Password) Then
Throw New ArgumentException("Value cannot be null or empty.", "Password")
ElseIf _Provider.ValidateUser(Username, Password) Then
ThisResult = True
Else
Try
ThisMember = _Provider.GetUser(Username, False)
Try
If (ThisMember Is Nothing) = False Then
Approved = ThisMember.IsApproved
Try
<!-- This is the point im stuck on -->
If Password_Matches_With_Password_In_Db Then
PwdMatches = True
Else
PwdMatches = False
End If
Catch ex As Exception
ThisResult = False
End Try
Else
ThisResult = False
End If
Catch ex As Exception
ThisResult = False
End Try
Catch ex As Exception
ThisResult = False
End Try
End If
Return ThisResult
ThisMember = Nothing
ThisResult = Nothing
End Function
I think one way to do it create a table that stores user accounts pending for approval. When user registers, populate this table with the userID or userName or set some flags indicating users who account has not been activated and who mails have been sent. Check this table when user logs in, if exist or flag not set, display "Activate your account to user"
Write a function that connects to the DB and use the userId to get the approval status from Aspnet_Membership table. The column name is IsApproved which is true or false
Dim user As MembershipUser = Membership.GetUser(userName);
Dim isApproved As Boolean = myMethodCheckIfUserIsApproved(user.ProviderUserKey); //userID
You should be able to call the Membership GetPassword method, passing Nothing in as the passwordAnswer parameter, which should just cause the password to be returned.
A disclaimer on this approach, however: we have implemented our own membership provider and SQL, and I don't have the original code to validate this against, so there may be something in the default provider that would prevent this approach, but it is worth trying.
EDIT:
In the case that the password is hashed, a possible solution to the problem is to perform a direct database query against the users table to get the state of the IsApproved flag. You could do this either before or after the call to GetUser, depending on how much you trust your end users (if you don't trust them, I would call it after in order to prevent someone from trying multiple users to see which are active).
UPDATE & ANSWER TO MY QUESTION
Hello everyone who replied to my question and thank you for your help,
It seems I was barking up the wrong tree by trying to validate the PASSWORD before trying to see if the account membership had been approved.
I have resolved the issue in a VERY SIMPLE WAY indeed.
This is how I did and I did not need to DIRECTLY interogate the database password field nor did i have to worry about hashing the password.
First of all I modified the default VALIDATELUSER call declaration....
in the SERVICES region of the ACCOUNTS MODEL
from...
Function ValidateUser(ByVal Username As String, ByVal Password As String) As Boolean
To...
Function ValidateUser(ByVal Username As String, ByVal Password As String, ByRef IsApproved As Boolean) As Boolean
This enabled me to call my newly modfied validation process also in the SERVICES region of the Accounts model where the ORGINIAL CODE was as follows...
Public Function ValidateUser(ByVal userName As String, ByVal password As String) As Boolean Implements IMembershipService.ValidateUser
If String.IsNullOrEmpty(userName) Then Throw New ArgumentException("Value cannot be null or empty.", "userName")
If String.IsNullOrEmpty(password) Then Throw New ArgumentException("Value cannot be null or empty.", "password")
Return _provider.ValidateUser(userName, password)
End Function
And the MODIFIED function which is now as follows...
Public Function ValidateUser(ByVal Username As String, ByVal Password As String, ByRef Approved As Boolean) As Boolean Implements IMembershipService.ValidateUser
Dim ThisMember As MembershipUser = Nothing
Dim ThisResult As Boolean = Nothing
'
Approved = False
ThisResult = False
If String.IsNullOrEmpty(Username) Then
Throw New ArgumentException("Value cannot be null or empty.", "Username")
ElseIf String.IsNullOrEmpty(Password) Then
Throw New ArgumentException("Value cannot be null or empty.", "Password")
ElseIf _Provider.ValidateUser(Username, Password) Then
ThisResult = True
Else
ThisMember = _Provider.GetUser(Username, False)
If (ThisMember Is Nothing) = False Then
Approved = ThisMember.IsApproved
End If
End If
Return ThisResult
ThisMember = Nothing
ThisResult = Nothing
End Function
I'm much happier with this prcoedure than with messing about with direct manipulation of the DB and also hashing the password.
So in effect, it was more about the original sequence of processing being back to front....
IE.
Not (1)validate login credentials then (2)check if email confirmed? (via link in welcome message)
but rather...
(1)Email Confirmed then (2)validate login credentials

Resources