Sitefinity 4.3 broke custom MembershipProvider

Posted by Community Admin on 04-Aug-2018 14:06

Sitefinity 4.3 broke custom MembershipProvider

All Replies

Posted by Community Admin on 15-Nov-2011 00:00

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.

Posted by Community Admin on 18-Nov-2011 00:00

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

Posted by Community Admin on 18-Nov-2011 00:00

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

Posted by Community Admin on 21-Nov-2011 00:00

So, basically, the MembershipDataProvider API changed between 4.2 SP1 and 4.3.
Did I miss a footnote mentioning this API breakage?

Posted by Community Admin on 21-Nov-2011 00:00

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

Posted by Community Admin on 30-Nov-2011 00:00

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

Posted by Community Admin on 30-Nov-2011 00:00

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.

Posted by Community Admin on 30-Nov-2011 00:00

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

Posted by Community Admin on 01-Dec-2011 00:00

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

Posted by Community Admin on 01-Dec-2011 00:00

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

Posted by Community Admin on 01-Dec-2011 00:00

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.

Posted by Community Admin on 05-Dec-2011 00:00

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

Posted by Community Admin on 05-Dec-2011 00:00

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.

Posted by Community Admin on 07-Dec-2011 00:00

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

This thread is closed