Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Thomas Michael Koch 24 posts 96 karma points
    Apr 08, 2015 @ 00:17
    Thomas Michael Koch
    1

    Custom Member MembershipProvider apparently not possible

    I am migrating an old web-site to an umbraco 7.2.4 installation. Part of this migration caused some pain which I would like to share - hopefully it will lead to new insights for me and others.

    I use CMSImport to import my existing member base into the new installation along with custom fields containing existing password and password hashes.

    To provide a smooth transfer for the members I wanted to create my own Member-MembershipProvider, based on the one supplied by Umbraco. The reason being that I need to do custom validation of the password the first time the user logs in and custom validation of password retrieval answer, the first time it is used.

    I have gathered the code from the class hierarhy 

    MembersMembershipProvider : UmbracoMembershipProvider<T, TEntity> : UmbracoMembershipProviderBase : MembershipProviderBase 

    into a new "MyMembershipProvider" class, still with all the required interfaces etc. I register it within the web.config and it works on the public facing side.

    Pain points

    My problems start when I go into the backoffice.

    First problem is that if the provider name is not "UmbracoMembershipProvider" the backoffice crashes with an InvalidOperationException.

    Why not name it "DoNotChangeMyName .... Provider" ?

    Changing the name back to "UmbracoMembershipProvider" it refuses to load the "Member Types" node. The reason apparently being a check in the class "umbraco.loadMemberTypes" that my custom membership provider does not inherit from "UmbracoMembershipProviderBase".

    Creating my own version of "umbraco.loadMemberTypes" is apparently not possible either since properties in the umbraco supplied class XmlTreeNode are "internal" properties.

    Trying to inherit from the existing "MembershipProviderBase" is not an option either, since the very method "EncryptOrHashPassword" which I need to change, although it is protected, is also marked as "internal".

    Why this heavy use of "internal"?

    Conclusion

    Creating your own Member-MembershipProvider is simply not possible. There are simply too many built-in assumption in the code, and the heavy use of "internal" makes it impossible to implement your own, unless you also change the umbraco.dll, which I dont want to.

    Moreover, a class-hierarchy of no less that four classes on top of the existing MembershipProvider makes for a code-base that is almost impossible to understand. Two of these classes contain 800+ and 400+ lines of code.

    I am beginning to realize that maybe this part of Umbraco was never intended for custom-implementations, but I hope my experience will help others. :-)

    Kind regards

    Thomas

  • Jonas Eriksson 930 posts 1825 karma points
    May 08, 2015 @ 01:34
    Jonas Eriksson
    0

    Not much help - just wanted to say I got stuck on custom membership in 7.2.4 aswell - tried to move a custom membership provider from v6 to 7 but I cant get it to work in the new version. 

  • Thomas Michael Koch 24 posts 96 karma points
    May 08, 2015 @ 11:22
    Thomas Michael Koch
    0

    Hi Jonas - I have given up on creating a custom membership provider in Umbraco 7.

    Instead I have implemented my own surface controller, where I do the custom part of my authentication. After that I delegate to the Umbraco membership system.

    Thomas

     

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Sep 15, 2015 @ 08:47
    Shannon Deminick
    0

    Hi, sorry that you are having troubles with this. I'll try to answer all your questions below:

    Heavy use of Internal? = if we make everything public, then we cannot progress the codebase of Umbraco because everything is a breaking change. This has been discussed on several occasions and although it would seem great if we simply made everything public, it would mean that we cannot progress the core of Umbraco without breaking everyone's website on every release. We try to maintain a balance between public APIs and internal APIs so that the codebase can be progressed and changed without people having to rebuild and fix breaking changes on each release. If you want things exposed publicly, it's a simple matter of asking by either raising an issue on the issue tracker or discussing it on the mail list

    Class hierarchy? = ASP.Net membership providers are a mess to begin with. We are also dealing with the very slow migration of legacy Umbraco Core code to new core code and maintaining backwards compatibility... it's not pretty to do such a thing, it's something that we need to live with.

    Changing the provider name = you can't. This is by design so that Umbraco doesn't get in the way of other web code. The alternative is to make you specify the Umbraco membership provider to be the default... and that will surely anger someone else. So the answer is simply to make sure that the Umbraco membership provider name is "UmbracoMembershipProvider" - there shouldn't be any issues with that. The Exception thrown is fairly clear : "No membership provider found with name UmbracoMembershipProvider" though I guess we could make it more specific. I don't think changing the name to "DoNotChangeMyName .... Provider" is a real pretty solution ;)

    EncryptOrHashPassword as internal? = sure, we can make this public. The alternative for now is to override ValidateUser and re-implement the logic found there. I realize it's not the best solution but it will work until things you might require are public. It would be a matter of copy and pasting some code from our source. The best way forward would be to create an issue on the tracker and let us know what you would like to be public/protected/overridable.

    Creating your own Member-MembershipProvider is simply not possible? = it is possible, but I realize it's not perfect. Sounds like if you override ValidateUser and copy/paste the logic in there that you need until things are public, you will be fine.

  • Thomas Michael Koch 24 posts 96 karma points
    Sep 15, 2015 @ 09:00
    Thomas Michael Koch
    0

    Hi Shannon - thank you for your reply.

    My complaint about the provider name came after spending hours of work, only to discover that the name could not be changed. :-)

    I have solved the issue by explicitly handling a conversion when users log in the first time. That way, I can avoid dealing with the complexities of the internal working of the ASP.NET providers.

    Maybe with time we could have a simplified provider for membership that does not have all the historic bagage and thus would be easier to customize.

    Regards Thomas

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Sep 15, 2015 @ 09:12
    Shannon Deminick
    0

    Viva v8 :) The plan for v8 is to remove all the baggage... finally !

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Sep 15, 2015 @ 09:26
    Shannon Deminick
    0

    It's also worth noting that 7.3 is being shipped with ASP.Net Identity in place. MembershipProvider stuff is still supported/used as well but if you wanted to change the whole auth procedure, this is fully possible in 7.3 by customizing the Identity implementation

  • Jonas Eriksson 930 posts 1825 karma points
    Sep 15, 2015 @ 10:31
    Jonas Eriksson
    1

    We did get ours up and running after a while, not completely implemented - but we do have what we need including the possibility to choose member groups for permissions in the backend content tree.

    We inherited from

    Umbraco.Web.Security.Providers.RoleProvider

    and

    Umbraco.Web.Security.Providers.MembersMembershipProvider

    and used the name UmbracoMembershipProvider.

    In webconfig membership

    <add name="UmbracoMembershipProvider" type="TheCompany.TheMembershipProvider" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="SomeGroup" passwordFormat="Hashed" />
    

    and rolemanager

    <add name="UmbracoRoleProvider" type="TheCompany.TheRoleProvider" />
    

    and overriding most methods, for example:

        public override bool ValidateUser(string username, string password)
        {
            // compare with db stored custom hashed pwd
        }
    

    I got the final clues I needed from looking at the source + the name thing. I should've gotten back abt this earlier, sorry for the delay.

    Thank you Shannon for the update and for moving the membership provider forward !

  • Vijay Reddy 2 posts 71 karma points
    Dec 23, 2016 @ 08:31
    Vijay Reddy
    0

    Hi,

    I am trying to inherit the Umbraco.Web.Security.Providers.MembersMembershipProvider but I don't find the Umbraco.Web.dll in the binaries which I downloaded.

    For now, I am struck with the umbraco source code compilation. Where can I download the Umbraco.Web.dll

    -- Vijay

Please Sign in or register to post replies

Write your reply to:

Draft