I need to replace the role provider in Umbraco with my own. This is due to me having to use an existing database of users/roles for a web application.
As far as my application is concerned I only need to override 2 methods in the RoleProvider: IsUserInRole and GetAllRoles.
I've implemented this and changed my web.config role providers section.
In the Umbraco backoffice, when I go to Members => Roles (it's no longer called Member Groups), GetAllRoles is called as it should be and I can list all my roles. I can also go to Content => Public access, choose role based protection and protect a page with one or all of my roles.
However, the problem is when the page is published and viewed. It doesn't seem to hit my custom role provider. I don't actually know where it's going, but it is recognising the page is protected and it's taking me to the log-in screen, but no matter what I do it doesn't ever let me see the protected page and it doesn't call my IsUserInRole method.
Has anyone any experience implementing a custom role provider?
I've tried implementing umbraco.providers.members.MembersRoleProvider and System.Web.Security.RoleProvider to no avail.
I hope it's possible to replace the role provider in Umbraco, otherwise I'm screwed :)
Yes, like I said it works in the back office. My roles are being listed in the Member's section and I can see them when I protect a page in the Content section.
It's only when I actually view the site do I have a problem.
I'm still struggling with this. I've basically stripped the role provider down to the bare minimum, so here it is:
namespace Abbott.PsoriASSESS.Web.code.Providers {
using System;
using System.Web.Security;
public class AbbottRoleProvider : RoleProvider
{
/// <summary>
/// Gets the friendly name used to refer to the provider during configuration.
/// </summary>
/// <returns>The friendly name used to refer to the provider during configuration.</returns>
public override string Name
{
get
{
return "AbbottRoleProvider";
}
}
/// <summary>
/// Gets or sets the name of the application to store and retrieve role information for.
/// </summary>
/// <returns>
/// The name of the application to store and retrieve role information for.
/// </returns>
public override string ApplicationName { get; set; }
/// <summary>
/// Gets an array of user names in a role where the user name contains the specified user name to match.
/// </summary>
/// <returns>
/// A string array containing the names of all the users where the user name matches <paramref name="usernameToMatch"/> and the user is a member of the specified role.
/// </returns>
/// <param name="roleName">The role to search in.</param><param name="usernameToMatch">The user name to search for.</param>
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets a list of users in the specified role for the configured applicationName.
/// </summary>
/// <returns>
/// A string array containing the names of all the users who are members of the specified role for the configured applicationName.
/// </returns>
/// <param name="roleName">The name of the role to get the list of users for.</param>
public override string[] GetUsersInRole(string roleName)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets a list of all the roles for the configured applicationName.
/// </summary>
/// <returns>
/// A string array containing the names of all the roles stored in the data source for the configured applicationName.
/// Gets a value indicating whether the specified user is in the specified role for the configured applicationName.
/// </summary>
/// <param name="username">The user name to search for.</param>
/// <param name="roleName">The role to search in.</param>
/// <returns>
/// true if the specified user is in the specified role for the configured applicationName; otherwise, false.
/// </returns>
public override bool IsUserInRole(string username, string roleName)
{
return true;
}
/// <summary>
/// Gets a list of the roles that a specified user is in for the configured applicationName.
/// </summary>
/// <returns>
/// A string array containing the names of all the roles that the specified user is in for the configured applicationName.
/// </returns>
/// <param name="username">The user to return a list of roles for.</param>
public override string[] GetRolesForUser(string username)
{
throw new NotImplementedException();
}
/// <summary>
/// Adds a new role to the data source for the configured applicationName.
/// </summary>
/// <param name="roleName">The name of the role to create.</param>
public override void CreateRole(string roleName)
{
throw new NotImplementedException();
}
/// <summary>
/// Removes a role from the data source for the configured applicationName.
/// </summary>
/// <returns>
/// true if the role was successfully deleted; otherwise, false.
/// </returns>
/// <param name="roleName">The name of the role to delete.</param><param name="throwOnPopulatedRole">If true, throw an exception if <paramref name="roleName"/> has one or more members and do not delete <paramref name="roleName"/>.</param>
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets a value indicating whether the specified role name already exists in the role data source for the configured applicationName.
/// </summary>
/// <returns>
/// true if the role name already exists in the data source for the configured applicationName; otherwise, false.
/// </returns>
/// <param name="roleName">The name of the role to search for in the data source.</param>
public override bool RoleExists(string roleName)
{
throw new NotImplementedException();
}
/// <summary>
/// Adds the specified user names to the specified roles for the configured applicationName.
/// </summary>
/// <param name="usernames">A string array of user names to be added to the specified roles. </param><param name="roleNames">A string array of the role names to add the specified user names to.</param>
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
/// <summary>
/// Removes the specified user names from the specified roles for the configured applicationName.
/// </summary>
/// <param name="usernames">A string array of user names to be removed from the specified roles. </param><param name="roleNames">A string array of role names to remove the specified user names from.</param>
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
In the Umbraco dashboard when I expand the Roles tree in Members section, it hits "GetAllRoles", but the front-end/published site never hits "IsUserInRole". I have breakpoints in every method body, but they are never hit on the front-end.
I'm really stuck here. If it isn't possible, can someone confirm this so I can move on to an alternative solution?
I'm not sure it is the reason you are having problems, but looking at my role provider code, I always override the Initialize method.
///
/// The overridden initialization method.
///
///Name of the role provider.
///Collection of configuration settings.
public override void Initialize(string name, NameValueCollection config)
{
// Verify that config isn't null
if (config == null)
throw new ArgumentNullException("config");
// Assign the provider a default name if it doesn't have one
if (String.IsNullOrEmpty(name))
name = "CustomSQLRoleProvider";
// Add a default "description" attribute to config if the
// attribute doesn’t exist or is empty
if (string.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Custom SQL role provider");
}
// Call the base class's Initialize method
base.Initialize(name, config);
// Read the role data source. NOTE: Unlike
// ReadOnlyXmlMembershipProvider, this provider can
// read the data source at this point because Read-
// RoleDataStore doesn't call into the role manager
ReadRoleDataStore();
}
I have used role providers based on Microsofts sample code successfully in many .NET applications, and Umbraco is just a .NET application, so it should be fine.
I've tried overriding the Initialize previously, but I just tried it again there and the same thing happens, however - it does call Initialize!
The first time the site loads, my Initialize method is called, it runs through fine and the home page loads. When I click on a role-secured page, it detects it's secured and that I'm not logged-in so it takes me to the log-in page. I log-in, I go back to my role-secured page and it takes me back to the log-in page. It doesn't hit the IsUserInRole method.
I'm going crazy here. I have my provider and I've set it in the web.config... I'm sure there's nothing else to do!
OK, I think I have this. I'm just working up a solution first before confirming it, but it looks like you can't implement your own role provider without also implementing a membership provider (which is something I was going to do, just later in the project).
I had a dig through the Umbraco source and library.cs => HasAccess calls CurrentMemberId() which attempts to load the user from the Member's database, which I'm not using.
So I'm just implementing a membership provider now and hopefully this will sort me out :)
Edit: Just to confirm, you cannot implement a custom role provider without also implementing a custom membership provider.
Ok, we had to implement a MembershipProvider and a RoleProvider as well. On top of that we had to comment out the UmbracoMembersMembershipProvider and UmbracoRoleProvider and give ours the same name.
In the back office this changes the look and feel of the Members section to now just show "All Members" and Member Groups (a member group is a role).
Forcing us to only be able to secure pages on Roles and not individual users (our users don't show up when using individual users).
It works, but is less than ideal... Eventually I'll try to come up with a way to completely replace umbracos user management and page access checking to support WIF and claims authentication.
Replacing the Umbraco Role Provider
Hi,
I need to replace the role provider in Umbraco with my own. This is due to me having to use an existing database of users/roles for a web application.
As far as my application is concerned I only need to override 2 methods in the RoleProvider: IsUserInRole and GetAllRoles.
I've implemented this and changed my web.config role providers section.
In the Umbraco backoffice, when I go to Members => Roles (it's no longer called Member Groups), GetAllRoles is called as it should be and I can list all my roles. I can also go to Content => Public access, choose role based protection and protect a page with one or all of my roles.
However, the problem is when the page is published and viewed. It doesn't seem to hit my custom role provider. I don't actually know where it's going, but it is recognising the page is protected and it's taking me to the log-in screen, but no matter what I do it doesn't ever let me see the protected page and it doesn't call my IsUserInRole method.
Has anyone any experience implementing a custom role provider?
I've tried implementing umbraco.providers.members.MembersRoleProvider and System.Web.Security.RoleProvider to no avail.
I hope it's possible to replace the role provider in Umbraco, otherwise I'm screwed :)
Thanks,
Greg.
Hi Greg,
I've replaced the role provider multiple times. Did you configure it in the web.config file?
Cheers,
Richard
Yes, like I said it works in the back office. My roles are being listed in the Member's section and I can see them when I protect a page in the Content section.
It's only when I actually view the site do I have a problem.
<roleManager enabled="true" defaultProvider="AbbottRoleProvider">
<providers>
<clear />
<!--<add name="UmbracoRoleProvider" type="umbraco.providers.members.UmbracoRoleProvider" />-->
<add name="AbbottRoleProvider" type="Abbott.Providers.AbbottRoleProvider" />
</providers>
</roleManager>
Hey,
I'm still struggling with this. I've basically stripped the role provider down to the bare minimum, so here it is:
namespace Abbott.PsoriASSESS.Web.code.Providers
{
using System;
using System.Web.Security;
public class AbbottRoleProvider : RoleProvider
{
/// <summary>
/// Gets the friendly name used to refer to the provider during configuration.
/// </summary>
/// <returns>The friendly name used to refer to the provider during configuration.</returns>
public override string Name
{
get
{
return "AbbottRoleProvider";
}
}
/// <summary>
/// Gets or sets the name of the application to store and retrieve role information for.
/// </summary>
/// <returns>
/// The name of the application to store and retrieve role information for.
/// </returns>
public override string ApplicationName { get; set; }
/// <summary>
/// Gets an array of user names in a role where the user name contains the specified user name to match.
/// </summary>
/// <returns>
/// A string array containing the names of all the users where the user name matches <paramref name="usernameToMatch"/> and the user is a member of the specified role.
/// </returns>
/// <param name="roleName">The role to search in.</param><param name="usernameToMatch">The user name to search for.</param>
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets a list of users in the specified role for the configured applicationName.
/// </summary>
/// <returns>
/// A string array containing the names of all the users who are members of the specified role for the configured applicationName.
/// </returns>
/// <param name="roleName">The name of the role to get the list of users for.</param>
public override string[] GetUsersInRole(string roleName)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets a list of all the roles for the configured applicationName.
/// </summary>
/// <returns>
/// A string array containing the names of all the roles stored in the data source for the configured applicationName.
/// </returns>
public override string[] GetAllRoles()
{
return new[] { "Patient", "HCP", "Admin", "SuperAdmin" };
}
/// <summary>
/// Gets a value indicating whether the specified user is in the specified role for the configured applicationName.
/// </summary>
/// <param name="username">The user name to search for.</param>
/// <param name="roleName">The role to search in.</param>
/// <returns>
/// true if the specified user is in the specified role for the configured applicationName; otherwise, false.
/// </returns>
public override bool IsUserInRole(string username, string roleName)
{
return true;
}
/// <summary>
/// Gets a list of the roles that a specified user is in for the configured applicationName.
/// </summary>
/// <returns>
/// A string array containing the names of all the roles that the specified user is in for the configured applicationName.
/// </returns>
/// <param name="username">The user to return a list of roles for.</param>
public override string[] GetRolesForUser(string username)
{
throw new NotImplementedException();
}
/// <summary>
/// Adds a new role to the data source for the configured applicationName.
/// </summary>
/// <param name="roleName">The name of the role to create.</param>
public override void CreateRole(string roleName)
{
throw new NotImplementedException();
}
/// <summary>
/// Removes a role from the data source for the configured applicationName.
/// </summary>
/// <returns>
/// true if the role was successfully deleted; otherwise, false.
/// </returns>
/// <param name="roleName">The name of the role to delete.</param><param name="throwOnPopulatedRole">If true, throw an exception if <paramref name="roleName"/> has one or more members and do not delete <paramref name="roleName"/>.</param>
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets a value indicating whether the specified role name already exists in the role data source for the configured applicationName.
/// </summary>
/// <returns>
/// true if the role name already exists in the data source for the configured applicationName; otherwise, false.
/// </returns>
/// <param name="roleName">The name of the role to search for in the data source.</param>
public override bool RoleExists(string roleName)
{
throw new NotImplementedException();
}
/// <summary>
/// Adds the specified user names to the specified roles for the configured applicationName.
/// </summary>
/// <param name="usernames">A string array of user names to be added to the specified roles. </param><param name="roleNames">A string array of the role names to add the specified user names to.</param>
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
/// <summary>
/// Removes the specified user names from the specified roles for the configured applicationName.
/// </summary>
/// <param name="usernames">A string array of user names to be removed from the specified roles. </param><param name="roleNames">A string array of role names to remove the specified user names from.</param>
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
}
}
And this is my web.config section:
<roleManager enabled="true" defaultProvider="AbbottRoleProvider">
<providers>
<clear />
<!--<add name="UmbracoRoleProvider" type="umbraco.providers.members.UmbracoRoleProvider" />-->
<add name="AbbottRoleProvider" type="Abbott.PsoriASSESS.Web.code.Providers.AbbottRoleProvider" />
</providers>
</roleManager>
In the Umbraco dashboard when I expand the Roles tree in Members section, it hits "GetAllRoles", but the front-end/published site never hits "IsUserInRole". I have breakpoints in every method body, but they are never hit on the front-end.
I'm really stuck here. If it isn't possible, can someone confirm this so I can move on to an alternative solution?
Thanks,
Greg.
I'm not sure it is the reason you are having problems, but looking at my role provider code, I always override the Initialize method.
Hi Dan,
I've tried overriding the Initialize previously, but I just tried it again there and the same thing happens, however - it does call Initialize!
The first time the site loads, my Initialize method is called, it runs through fine and the home page loads. When I click on a role-secured page, it detects it's secured and that I'm not logged-in so it takes me to the log-in page. I log-in, I go back to my role-secured page and it takes me back to the log-in page. It doesn't hit the IsUserInRole method.
I'm going crazy here. I have my provider and I've set it in the web.config... I'm sure there's nothing else to do!
Greg
OK, I think I have this. I'm just working up a solution first before confirming it, but it looks like you can't implement your own role provider without also implementing a membership provider (which is something I was going to do, just later in the project).
I had a dig through the Umbraco source and library.cs => HasAccess calls CurrentMemberId() which attempts to load the user from the Member's database, which I'm not using.
So I'm just implementing a membership provider now and hopefully this will sort me out :)
Edit: Just to confirm, you cannot implement a custom role provider without also implementing a custom membership provider.
Any questions, Tweet me @gfyans
Greg.
Hi Greg,
I ran into a same problem as you described,
I also implimented costum role provider, so I can see all roles from my external system in the umbraco admin
also I have implimented costum membership provider (with only the ValidateUser() function )
but still when user login to a secure page, though he is validated - he is always being redirected to the login page.
I am also trying to migrate Umbraco with Dynamic CRM , and want to pull the members and roles from the CRM -
without the need to store them twice (in Umbraco also) , and stil keep the ability of Umbraco - "Role based protection"
I will be gald to hear if it is posssible. and what is the solution you choose in the end.
I am realy stuck on this one and will really appreciate your help.
Regards
Erez
Hi Erez,
I think you may need more than ValidateUser.
Try overriding out the following methods as well, you could just return a new MembershipUser with example details filled out to test:
return new MembershipUser( ProviderName, patient.Username, patient.PatientId, patient.EmailAddress, null, null, patient.Active, false, patient.DateCreated, patient.LastLoginDate, DateTime.Now, DateTime.Now, DateTime.Now);
Hi Greg,
Thank you very much for your reply - I figured that out yesterday...
I have implimented those functions and it solved the problem.
Thanks again
Erez
I realize this thread is a bit old, but I'm stuck with the same exact problem! Does anyone have any documentation or an example of how to overcome it?
Robert
Erez- would you by chance please post your solution? We're looking to do what you did but with a netFORUM CRM. many, many thanks in advance!
Ok, we had to implement a MembershipProvider and a RoleProvider as well. On top of that we had to comment out the UmbracoMembersMembershipProvider and UmbracoRoleProvider and give ours the same name.
In the back office this changes the look and feel of the Members section to now just show "All Members" and Member Groups (a member group is a role).
Forcing us to only be able to secure pages on Roles and not individual users (our users don't show up when using individual users).
It works, but is less than ideal... Eventually I'll try to come up with a way to completely replace umbracos user management and page access checking to support WIF and claims authentication.
is working on a reply...