MembershipProvider

Topics: General
Apr 9, 2011 at 2:16 PM
Edited Apr 9, 2011 at 9:25 PM

How is a developer meant to either:

  • Custom MembershipProvider implementation defined in web.config to leverage the standard asp.net tools for user (not C1Console) calling into the C1 datastore via .Get<T>

Or

  • Use alternative C1 implementation for non Console users (i.e. user visits site, wants to access content that is restricted, setup in the console) - Sorry for being very vague I'm struggling to get my head round this at the moment and would like base steps (I just need start points and potential pitfalls not full code)

EDIT:

Only way to learn is to step the code I suppose... Just for others who are wondering about this heres what I've worked out so far:

Composite.Core.WebClient.HttpModules.AdministrativeAuthorizationHttpModule is calling into static methods in Composite.C1Console.Security.UserValidationFacade on a page by page basis (as with normal HttpModules as they are in the pipeline).

UserValidationFacade is public static, has enums for the standard MembershipProviders (Windows, Forms or None authentication types) and a few pub stat methods that are potentially of interest.

I also noted in earlier explorations that the HttpContext.Current.Session.SessionId is regenerated with every page request when using a c# function generated in the UI which seemed odd as it means standard session tracking wont work as expected

Thanks,

Paul

        public static bool FormValidateUserWithoutLogin(string userName, string password)
Apr 15, 2011 at 12:09 PM
Edited Apr 15, 2011 at 12:13 PM

I have a customer who has asked for possibility to use AD login with the C1 console... i would very much like to team up with you looking into creating custom MembershipProviders for use with the C1 console... we could try using a small csv-file as test case to start with and move on to ie AD authentication. And of course share the code, maybe through the CompositeC1Contrib project. What do you say?

Edit: blah... sorry, you want to of course use the existing user-base existing in C1 and expose it via a Membership provider. Well, i'm still up for it. Just remember, that members in C1 is defines through a facade where you can plugin your own providers, so you shouldn't rely on getting users through a normal Data Connection.

Apr 16, 2011 at 1:18 AM
burningice wrote:

I have a customer who has asked for possibility to use AD login with the C1 console... i would very much like to team up with you looking into creating custom MembershipProviders for use with the C1 console... we could try using a small csv-file as test case to start with and move on to ie AD authentication. And of course share the code, maybe through the CompositeC1Contrib project. What do you say?

I'm in :)

I know I'm a bit busy in general but I really would like to participate in this part.

Cheers

Apr 16, 2011 at 2:02 PM
burningice wrote:

I have a customer who has asked for possibility to use AD login with the C1 console... i would very much like to team up with you looking into creating custom MembershipProviders for use with the C1 console... we could try using a small csv-file as test case to start with and move on to ie AD authentication. And of course share the code, maybe through the CompositeC1Contrib project. What do you say?

Edit: blah... sorry, you want to of course use the existing user-base existing in C1 and expose it via a Membership provider. Well, i'm still up for it. Just remember, that members in C1 is defines through a facade where you can plugin your own providers, so you shouldn't rely on getting users through a normal Data Connection.

Yep it's the 'Edit' bit I was getting at. By default ASP.NET ships with the MembershipProvider which enables the use of all the standard asp Login, CreateUserWizard, and all the various APIs for CRUD etc... It seems to me that discarding all this default (and developer known) code would be a bit silly.

I am trying to understand what is deemed best C1 practise for meshing a provider into the system... Your advice/ideas on how to create a plugin so I could mesh in a MembershipProvider would be appreciated

Apr 16, 2011 at 8:18 PM
Edited Apr 17, 2011 at 3:47 PM

So, i've created a basic provider... Since the underlying system for C1 users/validation is very simple the Membership provider itself is very limited as well. This means ie. that

  • No search by email or user provided key, everything is based on username
  • Update/retrieval of password is only possible if the underlying provider supports it, this means that since only the DataBasedFormLoginProvider supports this so far, which is okay since its the default one, it will fail if validating against ie AD.
  • Creation of users is limited of the previous point as well.
  • Retrieval of all usernames and validating credentials works all the time.
  • We don't have support for password reset
  • No secret question, tracking of number of login-tries, activity windows etc.
  • Had to turn to reflection since not all of the necessary methods, classes and interface need for the LoginProvider-system in C1 are made public

I'm honestly a bit confused what the relation is between a IUser and a LoginProvider. IMO it makes sense that users HAS to be created in C1 and that only authentication/validation is delegated to a provider. But as i see it, with for instance ConfigBasedFormLoginProvider, a user is validated as long as the username/password match in the config-file, regardless of the user exists in C1 or not. I would say that is wrong, but its something i have to take up with the core team.

Anyway, the code can be found in the Contrib porject... it is based on that users HAS TO exist in C1. So even if we're validating against ie AD or something custom, usernames has to exist in C1 for retrieval of ie email.

http://compositec1contrib.codeplex.com/SourceControl/changeset/changes/65922

Apr 17, 2011 at 9:45 AM

That is exellent burningice -  the limitations of the IUser object are fineand am sure they can be worked around.

What .config modifications are required? Did you manage to dump i.e. a login control (in ascx) onto a c1 page?

Thanks

Apr 17, 2011 at 3:42 PM

yeah... its working fine with all the standard asp.net controls... login, loginstatus, loginname etc.

I've extended the code so it now supports activity tracking (lastlogin, last activity and so on). This is done by creating a new datatype in C1 called IMembershipUser that will hold these data. It's id will always be the same as the IUser that is the user its referring to. I've also included to code in my Contrib project, so the provider can be used just by adding this to web.config

<membership defaultProvider="C1ConsoleUsers">
      <providers>
        <add name="C1ConsoleUsers" type="CompositeC1Contrib.Web.Security.CompositeC1MembershipProvider, CompositeC1Contrib"/>
      </providers>
    </membership>

Ive tested it on a aspx page with this content

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <div>
        All users: <br />
        <% foreach (MembershipUser user in Membership.GetAllUsers())
           {
               Response.Write(String.Format("{0} ({1}), pwd: {2} <br />", user.UserName, user.Email, user.GetPassword()));
           } %>
    </div>

    <form runat="server">
        <asp:Login ID="login" runat="server" />

        <br /> <br />

        <asp:LoginStatus runat="server" />

        <br /> <br />

        <asp:LoginName runat="server" />
    </form>

    <br /> <br />

    <% if (User.Identity.IsAuthenticated) {
           Response.Write(Membership.GetUser().UserName + " last activity was " + Membership.GetUser().LastActivityDate + ", last logindate was " + Membership.GetUser().LastLoginDate);
           } %>

</body>
</html>

Apr 17, 2011 at 3:47 PM

ahha I thought I was missing a trick and you seem to have answerd my question in other forum - oddly I tried adding web.config membership providers and received error from deep within microsofts assemblies

Apr 17, 2011 at 3:55 PM

without posting the errors i can't really help you and can only blame the butler :)