Custom Authorization with Windows Authentication
Posted on 2004-09-13
I've tried to write a routine which will assign custom roles from a database. It's not working quite as I hoped, and I reckon I need some help. It is called from the Global.asax Application_AuthenticateRequest event.
I store the custom roles of the user in the database, and keep a DataTable in Application state to save making a connection on every request. A custom error is thrown if the routine cannot find the current user's username in the DataTable. The problem I'm having is that when I add a new user, even though I make certain to update the DataTable and confirm visually that the new user is in there, the routine still throws this custom error. This seems only to be fixed by restarting the app.
'Assign the custom roles to the user. This is done on every request.
Private Sub AssignUserRoles()
'Only do this if user is authenticated.
If Not Request.IsAuthenticated Then
Throw New Exception("Access denied. ")
'Get the essential Windows domain + group. ("MACHINENAME\AppUsers")
Dim windowsDomainAndGroup As String = AppSettings.WindowsDomain & "\" & AppSettings.WindowsGroup
'If the user is not in the essential Windows group initially, NO CHANGES will be made to her Roles.
' This means also that such a user cannot access the "admin" folder, as the "admin"
' role will not get assigned here unless they first belong to the essential Windows group.
If User.IsInRole(windowsDomainAndGroup) Then
'Get the user's custom roles from the cached "users" datatable, and
' try to assign the user's roles from the cached "users" datatable.
Dim users As DataTable = CType(Application("users"), DataTable)
Session("testUsers") = users
'Get the value in the "Roles" column of the first ((0) - and only) DataRow
' in an array of DataRows produced from Selecting from the "users" DataTable
' where "Username" = the user's name.
' If the username doesn't exist, an IndexOutOfRangeException will occur as there
' will be no DataRows in the array. (Thrown below.)
Dim customRoles As String = users.Select("Username = '" _
& User.Identity.Name _
'Assign the roles to the user, including the essential Windows group
' (as this is not retained when the User is replaced by a New GenericPrincipal).
HttpContext.Current.User = New System.Security.Principal.GenericPrincipal( _
Context.User.Identity, (windowsDomainAndGroup & "," & customRoles).Split(Convert.ToChar(",")))
Catch ex As System.IndexOutOfRangeException 'username doesn't exist in database.
Throw New System.Exception("Access denied. Have a superUser (a user able to " _
& "configure the database) set your permissions correctly, " _
& "or log out of Windows and try again.")
'Update "users" datatable (used to store their custom roles)
' in case it is an old version which is causing the problem.
' They can then try again.
End If 'User.IsInRole(windowsDomainAndGroup)