|
-
Aug 8th, 2009, 08:37 AM
#1
Authenticating users / membership provider AND windows authentication
We have only ever used the membership provider to give users access to our pages. With all the folder protection stuff and roles and so on.
But now we have a public-facing website where both teachers and parents will be connecting from outside the network.
The teachers already have inside-the-network domain usernames and passwords.
How can I have the teachers log in with the same un/pw as their domain un/pw but still have them be part of the membership provider world.
The parents do not have domain un's - so we know we have to give them membership/provider un's.
Is it even a good idea to do what I'm asking? Is this a bad security model?
-
Aug 8th, 2009, 11:01 AM
#2
Re: Authenticating users / membership provider AND windows authentication
Have you ever seen Outlook Web Access? When logging in to your OWA account, it'll ask you for your domain username/password. So the point is, it's possible and commonly used. But you'll need to do a bit of work for this - you'll need to make a custom membership and roles provider that talks to ActiveDirectory.
The good news is that, like I said, it's common. So there's sample code for this.
http://msdn.microsoft.com/en-us/library/ms998360.aspx
-
Aug 8th, 2009, 12:20 PM
#3
Re: Authenticating users / membership provider AND windows authentication
Excellent - OWA was kind of what I was thinking about - I've got EXCHANGE on my SBS in the office and I use OWA when outside my network...
I'll look at the link.
Thanks again.
btw - do you think we will be able to mix both the SqlMembershipProvider (for parents) and the ActiveDirectoryMembershipProvider (for teachers).
-
Aug 9th, 2009, 02:21 AM
#4
Re: Authenticating users / membership provider AND windows authentication
You'll need to make a SqlAndActiveDirectoryMembershipProvider... When any of the methods are being called, such as ValidateUser, you'll need to distinguish between the two types of credentials before sending the query to AD or SQL. Then again that could be easy, the AD credentials will be networkname\something, the SQL credentials will not.
But yes, you'll be able to combine them. You could write both providers separately, and write a third provider which in turn simply calls one of the original two based on the username.
-
Aug 10th, 2009, 12:04 PM
#5
Re: Authenticating users / membership provider AND windows authentication
We started trying to validate users with Active Directory and have hit a road block.
How is the DirectoryEntry path supposed to be structured? Ours looks like :
Code:
LDAP://antares.local/CN=Users,DC=antares,DC=local
With this path (and with a correct un/pw combo) we never find the user and the result is always nothing.
Our Active Directory structure looks like this :

When we change the string such as
Code:
LDAP://antares.local/CN=MyBusiness\SBSUsers\Users,DC=antares,DC=local
We get 'there is no such object on the server'.
We use this code to check for the user.
Code:
Protected Function AuthenticateUserAD(ByVal domain As String, ByVal username As String, ByVal password As String) As Boolean
Dim domainAndUserName = domain + "\" + username
Dim LDAPPATH As String
Dim entry As New DirectoryEntry("LDAP://antares.local/CN=Users,DC=antares,DC=local", domainAndUserName, password)
Try
Dim obj = entry.NativeObject
Dim search As DirectorySearcher = New DirectorySearcher(entry)
search.Filter = "(SAMAccountName=" + username + ")"
search.PropertiesToLoad.Add("cn")
Dim result As SearchResult = search.FindOne
If result Is Nothing Then
Return False
Else
LDAPPATH = result.Path
Return True
End If
Catch ex As Exception
Return False
End Try
End Function
What are we doing wrong?
-
Aug 10th, 2009, 02:26 PM
#6
Re: Authenticating users / membership provider AND windows authentication
The machine that you're calling this LDAP connection string (or binding string) from - is it in the same domain as antares.local or is it outside? If it's inside the same domain, then forget the server name, skip straight to the filters, you're mentioning it in the DC attribute anyways.
LDAP://CN=Users,DC=antares,DC=local
But that's not important, you can still use the domain controller if you want. Your first binding string looks right...
OK, that aside... I just noticed that I missed out on an important link in a previous post. Sorry 
http://msdn.microsoft.com/en-us/libr...pprovider.aspx
There's a provider that already exists for AD membership... it involves configuring something called ADAM (Active Directory for App Management, I think) on your DC boxes. Have a read through. Sorry about the confusion.
-
Aug 11th, 2009, 01:32 PM
#7
Re: Authenticating users / membership provider AND windows authentication
Using the same connection string in the email above we used Membership.CreateUser() to create a test user with a test password. Then when we use Membership.Validate() with the test user and password it returns true. However, none of the users in the OU "MyBusiness\Users\SBSUsers" can be validated. When the test user is moved into that OU it can no longer be validated either.
We tried using this connection string :
Code:
LDAP:\\antares.local\OU=MyBusiness,OU=Users,OU=SBSUsers,DC=antares,DC=local
And it claims the container doesnt exist.
What is wrong with the connection string?
What does the domain (ex: DOMAIN\User) mean to the membership provider and how do we use it?
-
Aug 11th, 2009, 01:56 PM
#8
Re: Authenticating users / membership provider AND windows authentication
With no "CN=Users" and with attritubeMapUsername="sAMAccountName" it returns true for users in SBSUsers.
-
Aug 11th, 2009, 02:55 PM
#9
Re: Authenticating users / membership provider AND windows authentication
Really can't say much, that should be working. 
Wait - how are you 'using' the connection string. What is the ASP.NET application's identity? Does it start working if you change it to a privileged user?
Throwing another link your way - http://blogs.msdn.com/gduthie/archiv...17/452905.aspx
This guy talks about using the AD membership provider.
-
Aug 12th, 2009, 04:10 PM
#10
Re: Authenticating users / membership provider AND windows authentication
So we now have membership working with both SQL and ActiveDirectory, and we have a SQLRoleProvider and an ActiveDirectoryRoleProvider.
How do we set up authorization to use both Role Providers and Membership?
Does it know which one to use based on which one contains a [currently] valid user?
How does it know which role provider to use?
-
Aug 13th, 2009, 07:39 AM
#11
Re: Authenticating users / membership provider AND windows authentication
You got it working? What was wrong, and how did you get it working?
To do the 'switch' you're going to have to do it programmatically. Here's what I'm thinking. When the user goes to the login form, there's a dropdown they have to choose from. Parent or Teacher. (Or whatever your categories were). The value chosen then determines which provider you're going to load up.
Start by creating yet another Membership Provider. Call it the MixedAuthenticationProvider. In each of its methods, look at the current session value (parent/teacher - you have to store that always, or in a cookie, but encrypted) and based on that, use it in each of the implemented methods. So as an example, in the mixed provider's UpdateUser method, look at the session variable, then load up the correct provider, then call, in turn, its UpdateUser method.
vb Code:
Dim actualMembershipProvider = Membership.Providers.Item("MyActiveDirectoryMembershipProvider") actualMembershipProvider.UpdateUser(...)
Remember that both membership providers must be registered in web.config.
-
Aug 13th, 2009, 12:03 PM
#12
Re: Authenticating users / membership provider AND windows authentication
We took out the CN="Users" and ended up with just "LDAP://antares.local/DC=antares,DC=local". We then made two membership and role providers. The membership providers are called ActiveDirectoryMembership and SQLMembership and the role providers are called ActiveDirectoryRoles and SQLRoles.
The mixed providers would both be the default providers, right?
Then we would override the subs that do membership validation to check to see which membership to use and then call that memberships validation. Is ASP smart enought to do that?
With the MixedRoles would that work with our authorization tags? ie: <deny roles="student">
How does ASP determine the current user is a "student"? Does it ask the default role provider? Is there a specific function it uses? Like IsUserInRole and if our role provider returns true it would block them from the web page.
-
Aug 13th, 2009, 03:49 PM
#13
Re: Authenticating users / membership provider AND windows authentication
Mendhak,
Here is some of our code:
This code defines our AD and SQL Membership Providers
Code:
<membership defaultProvider="SqlProvider">
<providers>
<clear />
<add
name="SqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="LocalSQLServer"
applicationName="GradeAnywhere"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed" />
<add
name="MembershipADProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="ADConnectionString"
connectionUsername="admin"
connectionPassword="password"
attributeMapUsername="sAMAccountName"/>
</providers>
</membership>
And this code defines our role providers
Code:
<roleManager enabled="true" cacheRolesInCookie="true"
defaultProvider="SqlRoleManager"
cookieName=".ASPXROLES" cookiePath="/" cookieTimeout="
30" cookieRequireSSL="false"
cookieSlidingExpiration="true"
createPersistentCookie="false" cookieProtection="All">
<providers>
<add name="SqlRoleManager"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="LocalSQLServer"
applicationName="GradeAnywhere" />
<add name="MyADRoleProvider"
type="CustomRoleProvider" connectionStringName="ADConnectionString"
applicationName="/"
connectionUsername="admin"
connectionPassword="password" />
</providers>
</roleManager>
And this code defines our "CustomRoleProvider" class.
Code:
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.DirectoryServices
Imports System.Web.Configuration
Imports System.Web.Security
Public Class CustomRoleProvider
Inherits RoleProvider
Dim _connectionString As String = ""
Dim _applicationName As String = ""
Dim _userName As String = ""
Dim _userPassword As String = ""
Public Overrides Sub Initialize(ByVal name As String, ByVal config As System.Collections.Specialized.NameValueCollection)
_connectionString = config("connectionStringName")
If String.IsNullOrEmpty(config("applicationName")) Then
_applicationName = config("applicationName")
End If
If String.IsNullOrEmpty(config("connectionUsername")) Then
_userName = config("connectionUsername")
End If
If String.IsNullOrEmpty(config("connectionPassword")) Then
_userPassword = config("connectionPassword")
End If
MyBase.Initialize(name, config)
End Sub
Public Overrides Property ApplicationName() As String
Get
Return _applicationName
End Get
Set(ByVal value As String)
_applicationName = value
End Set
End Property
Public Overrides Sub AddUsersToRoles(ByVal usernames() As String, ByVal roleNames() As String)
End Sub
Public Overrides Sub CreateRole(ByVal roleName As String)
End Sub
Public Overrides Function DeleteRole(ByVal roleName As String, ByVal throwOnPopulatedRole As Boolean) As Boolean
End Function
Public Overrides Function FindUsersInRole(ByVal roleName As String, ByVal usernameToMatch As String) As String()
End Function
Public Overrides Function GetAllRoles() As String()
End Function
Public Overrides Function GetRolesForUser(ByVal username As String) As String()
Dim obEntry As DirectoryEntry = New DirectoryEntry(WebConfigurationManager.ConnectionStrings(_connectionString).ConnectionString)
Dim srch As DirectorySearcher = New DirectorySearcher(obEntry, "(sAMAccountName=" + username + ")")
Dim res As SearchResult = srch.FindOne()
Dim dictionary As Dictionary(Of String, String) = New Dictionary(Of String, String)
If res IsNot Nothing Then
Dim obUser As DirectoryEntry = New DirectoryEntry(res.Path)
Dim rootPath As String = WebConfigurationManager.ConnectionStrings(_connectionString).ConnectionString
rootPath = rootPath.Substring(0, rootPath.LastIndexOf("/") + 1)
GetMemberships(obUser, dictionary, rootPath)
End If
Dim ary(dictionary.Count) As String
dictionary.Values.CopyTo(ary, 0)
Return ary
End Function
Private Sub GetMemberships(ByRef entry As DirectoryEntry, ByRef dictionary As Dictionary(Of String, String), ByVal rootPath As String)
Dim childrenToCheck As List(Of DirectoryEntry) = New List(Of DirectoryEntry)
Dim children As PropertyValueCollection = entry.Properties("memberof")
For Each childDN As String In children
'childDN = Mid(childDN, 1, InStr(childDN, ",") - 1)
If Not (dictionary.ContainsKey(childDN)) Then
Dim obGpEntry As DirectoryEntry = New DirectoryEntry(rootPath + childDN)
Dim groupName As String = obGpEntry.Properties("sAMAccountName").Value.ToString()
dictionary.Add(childDN, groupName)
childrenToCheck.Add(obGpEntry)
End If
Next
For Each child In childrenToCheck
GetMemberships(child, dictionary, rootPath)
Next
End Sub
Public Overrides Function GetUsersInRole(ByVal roleName As String) As String()
End Function
Public Overrides Function IsUserInRole(ByVal username As String, ByVal roleName As String) As Boolean
Dim ary As String()
ary = GetRolesForUser(username)
For Each item In ary
If roleName.ToLower = item.ToLower Then Return True
Next
Return False
End Function
Public Overrides Sub RemoveUsersFromRoles(ByVal usernames() As String, ByVal roleNames() As String)
End Sub
Public Overrides Function RoleExists(ByVal roleName As String) As Boolean
End Function
End Class
So when we use authorization code like this :
Code:
<authorization>
<deny roles="student"/>
</authorization>
How do the role providers or MixedRoleProvider determine whether the user is blocked?
Is it as simple as them calling "IsUserInRole(currentuser)"?
How does the membership keep track of whether or not there even is a current user and what that users name is?
-
Aug 13th, 2009, 05:52 PM
#14
Re: Authenticating users / membership provider AND windows authentication
Yes, that's right - it will call IsUserInRole, many times in fact. Everything the membership provider does (User.Identity.Name) centers around its own session variable. Any extra information that's needed is retrieved from the methods you write in those providers, such as IsUserInRole or GetRoleForUser. No session variable means no user or user has logged out.
-
Aug 15th, 2009, 02:59 PM
#15
Re: Authenticating users / membership provider AND windows authentication
 Originally Posted by mendhak
... Everything the membership provider does (User.Identity.Name) centers around its own session variable...
This is blank for us - look how we got here
Code:
Imports Microsoft.VisualBasic
Public Class MixedMembership
Inherits MembershipProvider
Public Overrides Property ApplicationName() As String
Get
Stop
End Get
Set(ByVal value As String)
Stop
End Set
End Property
.
.
.
Public Overrides Function UnlockUser(ByVal userName As String) As Boolean
Stop
End Function
Public Overrides Sub UpdateUser(ByVal user As System.Web.Security.MembershipUser)
Stop
End Sub
Public Overrides Function ValidateUser(ByVal username As String, ByVal password As String) As Boolean
If Membership.Providers("ActiveDirectoryMembershipProvider").ValidateUser(username, password) Then
Return True
ElseIf Membership.Providers("SQLMembershipProvider").ValidateUser(username, password) Then
Return True
Else
Return False
End If
End Function
End Class
Validate user runs fine - the first IF with ActiveDirectoryMembershipProvider validates the username and password - returns TRUE like it should.
Login control then redirects to the next page where we have this
Code:
Imports System.Security.Principal
Partial Class ClassSelection
Inherits System.Web.UI.Page
Dim SProcinator As New SprocExecutor
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim myPrincipal As IPrincipal = Me.User
Dim ds As Data.DataSet = SProcinator.ExecSproc("dbo.gspGetTeaNum", True, "@TeaUserName", User.Identity.Name)
The myPrincipal stuff was just me debugging - but the point is that ME.USER is not setup
Code:
?Me.User.Identity
{System.Security.Principal.GenericIdentity}
System.Security.Principal.GenericIdentity: {System.Security.Principal.GenericIdentity}
AuthenticationType: ""
IsAuthenticated: False
Name: ""
Why is ME.USER.IDENTITY blank????
-
Aug 16th, 2009, 12:35 AM
#16
Re: Authenticating users / membership provider AND windows authentication
Could be for several reasons, but the most common reasons are
1. You're still using no authentication/anonymous authentication. Change the web.config authentication mode node to Forms.
2. Are you remembering to set the auth cookie?
3. http://support.microsoft.com/?id=306359
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|