More in this section

Forums / Developing with Sitefinity / Sitefinity 4.3 broke custom MembershipProvider

Sitefinity 4.3 broke custom MembershipProvider

14 posts, 1 answered
  1. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    15 Nov 2011
    Link to this post
    Hi,

    We have a custom membership provider that used to work fine so far (up to Sitefinity 4.2 SP1), but which doesn't work anymore since we updated to Sitefinity 4.3. When trying to log into the backend, we now get the following error message: "Incorrect Username/Password Combination".

    I don't know what's wrong. The GetUser method still works and returns the right result, but the ValidateUser method is never called.

    Is this a known issue?
    What can I do to solve or debug this?

    Thanks.
  2. Svetoslav Petsov
    Svetoslav Petsov avatar
    456 posts
    Registered:
    24 Sep 2012
    18 Nov 2011
    Link to this post
    Hello Thomas,

     Is your membership provider inheriting from OpenAccessMembershipProvider? It's possible that the project didn't properly upgrade, so can you try upgrading it again, if you have a backup?
    Also, can you try restarting the server, maybe this could help.

    Best wishes,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    18 Nov 2011
    Link to this post
    Hi Svetoslav,

    I've encounter same problem on my custom membership provider but I solve it.
    It's not a migration problem my custom membership inherit of MembershipDataProvider.

    Previously when we are log-in for access to backend it's ValidateUser(string username, string password) method who was called. And now in SF4.3 it's ValidateUser(User user, string password) method.

    If you just override ValidateUser(String username, String password), the problem will appear. It's probably due to an evolution on log-in system process.

    Regards,
    Nicolas
    Answered
  4. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    21 Nov 2011
    Link to this post
    So, basically, the MembershipDataProvider API changed between 4.2 SP1 and 4.3.
    Did I miss a footnote mentioning this API breakage?
  5. Svetoslav Petsov
    Svetoslav Petsov avatar
    456 posts
    Registered:
    24 Sep 2012
    21 Nov 2011
    Link to this post
    Hello Thomas,

     This was an omission in our release notes and we apologize for that, I myself wasn't aware of it until a day ago.
    Again, accept our apologies for the discomfort, I'm glad that your issue got resolved.
    Let me know if I can help you with something else. 

    Best wishes,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  6. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    30 Nov 2011
    Link to this post
    Hi Svetoslav,
    This new feature have a bigger impact than I think at first time.
    My custom membership can create users when they tried to login with check-in an other reference table.

    But with this new feature only users already created can login...
    Others are blocked on login page with no hope to enter.

    Regards,
    Nicolas
  7. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    30 Nov 2011
    Link to this post
    Hi,

    Indeed, as Nicolas said, Sitefinity 4.3 also broke our code to create users.
    This is a showstopper for us. We were supposed to release our sites early next month, but if we can't fix this issue by then, we'll have to cancel these releases.

    We'd appreciate it if you could help us ASAP.

    Thanks.
  8. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    30 Nov 2011
    Link to this post
    Hi,
    I created a bypassing but it's really a hack....
    When you logged in on site the SecurityManager, now in 4.3, call ValidateUser(User user, string password) during AuthenticateUser method.
    But for call this method it use GetUser(String userName) and obtains object User.

    So in my override method GetUser(String userName) I created a hack to recover user password (with HttpContext.Instance.Request.Params).
    With couple userName/password, I called my override method ValidateUser(String userName, String password) and I can create dynamically users.

    This solution is not long-lasting. Could administrators help us?

    Regards,
    Nicolas
  9. Svetoslav Petsov
    Svetoslav Petsov avatar
    456 posts
    Registered:
    24 Sep 2012
    01 Dec 2011
    Link to this post
    Hello guys,

     Indeed, the method was changed for performance optimizations (not a change in the API). However, I cannot exactly understand what issues this could cause to your custom membership providers. Can you open support tickets and send us the implementations of your providers, so we can get a better picture of  the problem?
    Thank you for the understanding.

    All the best,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  10. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    01 Dec 2011
    Link to this post
    Hi Svetoslav,

    The problem are I have a custom membership provider who inherit MembershipDataProvider, this provider can create user dynamically when somebody try to logon onto the site.
    My provider checked user's existance and roles reading from another database.
    If this user doesn't exist in Sitefinity and has roles in the other database, then the provider creates it and assigns it roles.
    If user exist, provider just synchronises roles (ie: Sitefinity roles are updated using the other DB data).

    Now in Sitefinity 4.3 if user doesn't exist none of ValidateUser methods are called, making it so the user will never be created automatically..... And That's the problem.

    Before 4.3 :
    SecurityManager methods called ValidateUser(String userName, String password) of membership provider. The user was created in the ValidateUser method if it didn't exist.
    public static UserLoggingReason AuthenticateUser(string membershipProviderName, string userName, string password, bool persistent, out User user)
            {
                UserLoggingReason result;
                var manager = UserManager.GetManager(membershipProviderName, SecurityManager.authTranName);
                manager.Provider.SuppressSecurityChecks = true;
     
                if (manager.ValidateUser(userName, password))
                {
                    user = manager.GetUser(userName);
                    // This exception should be impossible, but just in case.
                    if (user == null)
                        throw new ArgumentException("Invalid user name.");
     
                    result = AuthenticateUser(user, manager, persistent);
                }
                else
                {
                    result = UserLoggingReason.Unknown;
                    user = null;
                }
     
                manager.Provider.SuppressSecurityChecks = false;
                return result;
            }

    Now in 4.3 :
    SecurityManager methods calls GetUser(String userName) of membership provider, but doesn't enter the ValidateUser method (unlike before), making it so the user isn't created if it needs to be created.

    public static UserLoggingReason AuthenticateUser(string membershipProviderName, string userName, string password, bool persistent, out User user)
    {
        UserLoggingReason result;
        var manager = UserManager.GetManager(membershipProviderName, SecurityManager.authTranName);
        using (new ElevatedModeRegion(manager))
        {
            user = manager.GetUser(userName);
            if (user == null)
                return UserLoggingReason.Unknown;
     
            if (manager.ValidateUser(user, password))
            {
                result = AuthenticateUser(user, manager, persistent);
            }
            else
            {
                result = UserLoggingReason.Unknown;
                user = null;
            }
            TransactionManager.CommitTransaction(SecurityManager.authTranName);
        }
        return result;
    }


    Regards,
    Nicolas

  11. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    01 Dec 2011
    Link to this post
    Hi,

    So, to sum things up:

    We used to be able to create users in the ValidateUser method (if the user doesn't exist yet).
    We can't do this anymore since Sitefinity 4.3, because ValidateUser is no longer called when the user is null. This is another breaking change in the API (I'm surprised you do not have unit tests to prevent things like this from happening...).

    It was convenient to do this in the ValidateUser method, as it has the password as parameter, and we need the password to create the user. Now that we no longer enter the ValidateUser method when the user hasn't been created yet, we came up with a hack to retrieve the password ourselves (from HttpContext), then manually call ValidateUser, which is dirty.

    Please suggest a better way to do this, which won't break in the future.

    Thanks.
  12. Svetoslav Petsov
    Svetoslav Petsov avatar
    456 posts
    Registered:
    24 Sep 2012
    05 Dec 2011
    Link to this post
    Hello Thomas,

     I am not aware of your whole case, which means that I cannot suggest something which should be case-specific - there is no "general" best method for that. However, creating users on ValidateUser is not a good practice.

    Regards,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  13. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    05 Dec 2011
    Link to this post
    Hi Svetoslav,

    You do not need to know the whole case, just that: we have some kind of user database for all of the apps of our company (let's call it UserDB). All applications must use UserDB to identify users (through API or membership provider). This is mandatory.
    For Sitefinity sites, our strategy was that when a user logs in, check if the login / password couple exists in UserDB. If it does, check if the user exists in Sitefinity. If it doesn't exist in Sitefinity, automatically create it. Then synchronize user permissions (update Sitefinity user info from UserDB info, so that if the user rights were changed in UserDB, this is reflected on Sitefinity). Then finally log the user.

    We cannot manually create all users in Sitefinity beforehand, because there are thousands of them. That's why we wanted to have an automatic creation during login. Besides, not all users may want to use these sites, so we shouldn't needlessly create Sitefinity user accounts.

    Can you think of a better way to do something like this?

    Thanks.
  14. Svetoslav Petsov
    Svetoslav Petsov avatar
    456 posts
    Registered:
    24 Sep 2012
    07 Dec 2011
    Link to this post
    Hi Thomas,

     Ok, I understand the scenario right now. Indeed - the method is not called if a user is not found in the database (when null is returned by GetUser, you enter the if check and never get to the ValidateUser method). We will inspect the code and see if we can find another suitable place where you can create the users. 
    However, in 4.4 SP1, which will be released soon after 4.4, all of these methods (AuthenticateUser, ValidateUser and so on) will be obsolete and Single Sign On will be available out-of-the-box, so you won't need to implement your own providers in order to use a single user database for all your websites. 
    We will need some time to investigate the code and see if there is a way to put the create user code in a good place. I will get back to you with the results, when we are ready.

    Greetings,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
14 posts, 1 answered