ADAM and AuthorizationStoreRoleProvider

J

jbijleveld

Hello,

I'm having a problem configuring ADAM and the
AuthorizationStoreRoleProvider in .NET 2.0 and I hope someone can help
me out since I've been stuck with this one for quite some time.

I did install ADAM, the Win2003 Admin Pack etc and configured my
web.config file using the instructions on the following website (for
those who are still looking for that info)

http://www.oftedal.no/~erlend/?blogid=6&show_comment=1
http://forums.asp.net/1023737/ShowPost.aspx
http://blogs.msdn.com/dansellers/archive/2005/10/11/479941.aspx


What does work (using the Web Site Administration Tool (WSAT)):
I can properly view the users, delete them, view the roles, add and
remove roles.

What's still a problem:
I cannot view the members of a role or assign a role to a user using
the "Manage Role" option. Also, if I create a user, it does appear in
the container properly but then WSAT tries to assign the role and fails
with the following exception:

Exception has been thrown by the target of an invocation.
at
System.Web.Administration.WebAdminPage.CallWebAdminHelperMethod(Boolean
isMembership, String methodName, Object[] parameters, Type[]
paramTypes)
at
ASP.security_roles_managesinglerole_aspx.__DataBinding__control30(Object
sender, EventArgs e) at System.Web.UI.Control.OnDataBinding(EventArgs
e)
etc...

It seems to me that the membership provider works properly but there's
still some problem with the AuthorizationStoreRoleProvider.

I'm working on a WinXP SP2 PC and ADAM is installed on a Win2003 SP1
server.

I didn't find many posts about this issue yet, only people asking the
same question, no answers. Can anyone please tell me how to fix this?

Thanks in advance!

Jeroen
 
J

JB

Thanks for pointing that out...

I found some other postings telling me that AzMan Role Membership
provider does NOT support assigning roles to ADAM users, only to
Windows users. That's consistent with what I found out. The solution
would be to write another RoleProvider, which does support this. And
that's what I've been doing yesterday and at the end of the day I got
it to work properly, except for two methods: FindUsersInRole and
GetRolesForUser.

I'll post the sourcecode shortly and I hope someone can help me to
implement these methods as well.
 
J

JB

Hello,

This post contains code for a RoleProvider that allows you to assign
ADAM roles to ADAM users only.

To make it work, just paste it into a new cs file, add a reference to
the Microsoft.Interop.Security.AzRoles dll
I hope someone with knowledge of ADAM and/or Active Directory will
assist in completing the last two methods of this provider!

Here's the code for so far:

==========================================

using System.Web.Security;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Collections;
using System;
using System.Resources;
using System.Data;
using System.Data.Odbc;
using System.Configuration;
using System.Diagnostics;
using System.Web;
using System.Security;
using System.Globalization;
using Microsoft.Interop.Security;
using Microsoft.Interop.Security.AzRoles;
using System.Security.Principal;
using System.DirectoryServices;
using System.Runtime.InteropServices;

namespace InSumma.Security.Adam.Roles
{
/// <summary>
/// Implementation of a .NET 2.0 Role Provider that supports
/// assigning roles to ADAM users. The standard AzMan Role Provider
/// only supports assigning roles to Windows Users.
/// </summary>
public sealed class AdamRoleProvider : RoleProvider
{
//
// Global connection string, generic exception message, event
log info.
//
private string eventSource = "AdamRoleProvider";
private string eventLog = "Application";
private string exceptionMessage = "Er is een fout opgetreden in
de RoleProvider. Meer details staan in de Event Log.";

private string azManApplicationName="";
private ConnectionStringSettings pConnectionStringSettings;
private string azManConnectionString="";


//
// If false, exceptions are thrown to the caller. If true,
// exceptions are written to the event log.
//

private bool pWriteExceptionsToEventLog = false;

public bool WriteExceptionsToEventLog
{
get { return pWriteExceptionsToEventLog; }
set { pWriteExceptionsToEventLog = value; }
}



//
// System.Configuration.Provider.ProviderBase.Initialize Method
//

public override void Initialize(string name,
NameValueCollection config)
{
//
// Initialize values from web.config.
//
System.Diagnostics.TextWriterTraceListener twtl = new
TextWriterTraceListener(@"c:\AdamRoleProvider.txt");
System.Diagnostics.Trace.Listeners.Add(twtl);
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
Initialize");
System.Diagnostics.Trace.Flush();

if (config == null)
throw new ArgumentNullException("config");

if (name == null || name.Length == 0)
name = "AdamRoleProvider";

if (String.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Role Provider supporting
assignment of roles to ADAM users");
}

// Initialize the abstract base class.
base.Initialize(name, config);


if (config["applicationName"] == null ||
config["applicationName"].Trim() == "")
azManApplicationName =
System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
else
azManApplicationName = config["applicationName"];


if (config["writeExceptionsToEventLog"] != null)
{
if (config["writeExceptionsToEventLog"].ToUpper() ==
"TRUE")
{
pWriteExceptionsToEventLog = true;
}
}

//
// Initialize AdamRoleProvider
//

// Read connectionstring only if it's not yet set by the
property
if (azManConnectionString=="")
{
pConnectionStringSettings =
ConfigurationManager.ConnectionStrings[config["connectionStringName"]];
if (pConnectionStringSettings == null ||
pConnectionStringSettings.ConnectionString.Trim() == "")
throw new ProviderException("AdamRoleProvider
connection string cannot be blank.");
azManConnectionString =
pConnectionStringSettings.ConnectionString;
}
}


//
// Allow to set a connectionstring by code (for testing)
//
public string ConnectionString
{
set { azManConnectionString = value; }
}


//
// System.Web.Security.RoleProvider properties.
//
public override string ApplicationName
{
get { return azManApplicationName; }
set { azManApplicationName = value; }
}


#region Implementation of AdamRoleProvider
//
// System.Web.Security.RoleProvider methods.
//

//
// RoleProvider.AddUsersToRoles
//

public override void AddUsersToRoles(string[] usernames,
string[] rolenames)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
AddUsersToRoles");
System.Diagnostics.Trace.Flush();

// Check for duplicate roles
foreach (string rolename in rolenames)
{
if (!RoleExists(rolename))
throw new ProviderException("Role name not
found.");
}

foreach (string username in usernames)
{
if (username.IndexOf(',') > 0)
throw new ArgumentException("User names cannot
contain commas.");

foreach (string rolename in rolenames)
{
if (IsUserInRole(username, rolename))
throw new ProviderException("User is already in
role.");
}
}


try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();

// Loop users and roles
foreach (string username in usernames)
{
MembershipUser user = Membership.GetUser(username);

foreach (string rolename in rolenames)
{
IAzRole role = _azApp.OpenRole(rolename, null);
role.AddMember(user.ProviderUserKey.ToString(),
null);
role.Submit(0, null);
}
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "AddUsersToRoles");
else
throw e;
}
}


//
// RoleProvider.CreateRole
//

public override void CreateRole(string rolename)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
CreateRole");
System.Diagnostics.Trace.Flush();

// Check precondition
if (rolename.IndexOf(',') > 0)
throw new ArgumentException("Role names cannot contain
commas.");

if (RoleExists(rolename))
throw new ProviderException("Role name already
exists.");

try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();

// Add a role
IAzTask task = _azApp.CreateTask(rolename, null);
task.IsRoleDefinition = 1;
task.Submit(0, null);

IAzRole role = _azApp.CreateRole(rolename, null);
role.AddTask(rolename, null);
role.Submit(0, null);
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "CreateRole");
else
throw e;
}
}


//
// RoleProvider.DeleteRole
//

public override bool DeleteRole(string rolename, bool
throwOnPopulatedRole)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
DeleteRole");
System.Diagnostics.Trace.Flush();

// Check preconditions
if (!RoleExists(rolename))
throw new ProviderException("Role does not exist.");

if (throwOnPopulatedRole && GetUsersInRole(rolename).Length
throw new ProviderException("Cannot delete a populated
role.");

try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();

// Delete a role
_azApp.DeleteTask(rolename, null);
_azApp.Submit(0, null);

_azApp.DeleteRole(rolename, null);
_azApp.Submit(0, null);
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "DeleteRole");
return false;
}
else
throw e;
}

return true;
}


//
// RoleProvider.GetAllRoles
//

public override string[] GetAllRoles()
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
GetAllRoles");
System.Diagnostics.Trace.Flush();

try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();

int i = 1;
string[] roles = new string[_azApp.Roles.Count];
while (i <= _azApp.Roles.Count)
{
IAzRole role = (IAzRole)_azApp.Roles;
roles[i-1] = role.Name;
i++;
}

return roles;
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "GetAllRoles");
else
throw e;
}

return new string[0];
}


//
// RoleProvider.GetRolesForUser
//

public override string[] GetRolesForUser(string username)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
GetRolesForUser");
System.Diagnostics.Trace.Flush();

try
{
throw new NotSupportedException("GetRolesForUser is not
supported by the AdamRoleProvider");

//TODO Implement this method!!!

}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "GetRolesForUser");
else
throw e;
}

return new string[0];
}


//
// RoleProvider.GetUsersInRole
//

public override string[] GetUsersInRole(string rolename)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
GetUsersInRole");
System.Diagnostics.Trace.Flush();

try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();

IAzRole role = _azApp.OpenRole(rolename, null);
if (role == null) throw new ProviderException("Role
"+rolename+" was not found");

object[] members = (object[]) role.Members;
string[] usernames = new string[members.Length];

int i = 1;
while(i <= members.Length)
{
usernames[i-1] = members[i-1].ToString();
i++;
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "GetUsersInRole");
else
throw e;
}

return new string[0];
}


//
// RoleProvider.IsUserInRole
//

public override bool IsUserInRole(string username, string
rolename)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
IsUserInRole");
System.Diagnostics.Trace.Flush();

try
{
string[] roles = GetRolesForUser(username);
foreach(string role in roles)
{
if (role==rolename)
return true;
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "IsUserInRole");
else
throw e;
}

return false;
}


//
// RoleProvider.RemoveUsersFromRoles
//

public override void RemoveUsersFromRoles(string[] usernames,
string[] rolenames)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
RemoveUsersFromRoles");
System.Diagnostics.Trace.Flush();

foreach (string rolename in rolenames)
{
if (!RoleExists(rolename))
throw new ProviderException("Role name not
found.");
}

foreach (string username in usernames)
{
foreach (string rolename in rolenames)
{
if (!IsUserInRole(username, rolename))
throw new ProviderException("User is not in
role.");
}
}


try
{
IAzApplication _azApp = GetAdamApp();
foreach (string username in usernames)
{
MembershipUser user = Membership.GetUser(username);

foreach (string rolename in rolenames)
{
IAzRole role = _azApp.OpenRole(rolename, null);

role.DeleteMember(user.ProviderUserKey.ToString(), null);
role.Submit(0, null);
}
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "RemoveUsersFromRoles");
else
throw e;
}
}


//
// RoleProvider.RoleExists
//

public override bool RoleExists(string rolename)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
RoleExists");
System.Diagnostics.Trace.Flush();

bool exists = false;
try
{
IAzApplication _azApp = GetAdamApp();

// Warning! The Roles collection is 1-bases instead of
0-based!!
int i = 1;
while (i <= _azApp.Roles.Count && !exists)
{
IAzRole role = (IAzRole)_azApp.Roles;
if (role.Name == rolename)
exists = true;
i++;
}
}
catch (Exception ex)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(ex, "RoleExists");
else
throw ex;
}

return exists;
}

//
// RoleProvider.FindUsersInRole
//

public override string[] FindUsersInRole(string rolename,
string usernameToMatch)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
FindUsersInRole");
System.Diagnostics.Trace.Flush();

try
{
throw new NotSupportedException("FindUsersInRole is not
supported by the AdamRoleProvider");

//TODO Implement this method!!!

}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "FindUsersInRole");
else
throw e;
}

return new string[0];
}

#endregion


#region Support methods

//
// WriteToEventLog
// A helper function that writes exception detail to the
event log. Exceptions
// are written to the event log as a security measure to avoid
private database
// details from being returned to the browser. If a method does
not return a status
// or boolean indicating the action succeeded or failed, a
generic exception is also
// thrown by the caller.
//

private void WriteToEventLog(Exception e, string action)
{
EventLog log = new EventLog();
log.Source = eventSource;
log.Log = eventLog;

string message = exceptionMessage + "\n\n";
message += "Action: " + action + "\n\n";
message += "Exception: " + e.ToString();

log.WriteEntry(message);
}


/// <summary>
/// Initializes communication with ADAM
/// </summary>
/// <returns>A reference to the ADAM application</returns>
private IAzApplication GetAdamApp()
{
AzAuthorizationStore _azStore = new
AzAuthorizationStoreClass();
_azStore.Initialize(0, azManConnectionString, null);
IAzApplication _azApp =
_azStore.OpenApplication(azManApplicationName, null);
return _azApp;
}

#endregion

}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top