MonoX support board

Start the conversation, ask questions and share tips and solutions with fellow developers.

Non-registered users can only browse through our support boards. Please register now if you want to post your questions. It takes a second and it is completely free. Alternatively, you can log in without registration using your credentials at major sites such as Google, Microsoft Live, OpenId, Facebook, LinkedIn or Yahoo.

Error on changing passwordFormat to Hashed in webConfig  (Mono Support )

Viewed 26203 time(s), 14 post(s) 7/29/2013 10:36:41 AMby super
super

super

7/29/2013 10:36:44 AM
I have changed the password encryption in webconfig by passwordFormat="Hashed" instead of "Clear".

When I do this, and try to run monox, it gives me error

http://localhost:2464/MonoX/MonoX/Pages/MonoX/Error.aspx?aspxerrorpath=/MonoX/default.aspx

Server Error in '/MonoX' Application.
 
 
Runtime Error Description:
 
An exception occurred while processing your request. Additionally, another
 
exception occurred while executing the custom error page for the first
 
exception. The request has been terminated.


Here is my log file:

2013-07-26 10:21:46,475 [32] ERROR MonoX [BaseHttpApplication] - Application Error
System.Configuration.ConfigurationErrorsException:
Password format specified is invalid.
(C:\Users\Downloads\Projects\MonoX\web.config line 435) --->
System.Configuration.Provider.ProviderException: Password format
specified is invalid.
   at System.Web.Security.SqlMembershipProvider.Initialize(String name, NameValueCollection config)
   at System.Web.Configuration.ProvidersHelper.InstantiateProvider(ProviderSettings providerSettings, Type providerType)
   --- End of inner exception stack trace ---
   at System.Web.Security.Membership.Initialize()
   at System.Web.Security.Membership.get_Provider()
   at MonoSoftware.MonoX.Repositories.MembershipRepository.GetApplicationId(Boolean enableCache)
   at MonoSoftware.MonoX.Repositories.MembershipRepository.GetApplicationId()
   at MonoSoftware.MonoX.Utilities.PageUtility.GetPageProperties(String appRelativeCurrentExecutionFilePath)
   at MonoSoftware.MonoX.BasePage.GetPageProperties()
   at MonoSoftware.MonoX.BasePage.get_PageProperties()
   at MonoSoftware.MonoX.BasePage.OnPreInit(EventArgs e)
   at System.Web.UI.Page.PerformPreInit()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at ASP.monox_pages_monox_error_aspx.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)






This is my webconfig:


<membership defaultProvider="AspNetSqlMembershipProvider" hashAlgorithmType="SHA1">
      <providers>
        <remove name="AspNetSqlMembershipProvider" />
        <add connectionStringName="LocalSqlServer" enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="MonoX" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" name="AspNetSqlMembershipProvider" type="MonoSoftware.MonoX.MonoXMembershipProvider, MonoX" />
        <!-- <add name="ActiveDirectoryMembershipProvider" type="MonoSoftware.MonoX.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" applicationName="MonoX"
         connectionUsername="username@yourdomain"
         connectionPassword="pwd" /> -->
      </providers>
    </membership>

This content has not been rated yet. 
6018 Reputation 709 Total posts
mzilic

mzilic

7/29/2013 2:26:46 PM
Hello Super,

You cannot just switch to the encrypted password format as you appear to already have some users in the database that have unencrypted passwords. A solution would be to encrypt the existing user passwords, for example you can adapt the following code snippet for your own use:

internal void SwitchAllUserPasswordsToHashFormat()
        {
            UnitOfWork2 uow = new UnitOfWork2();
  
            EntityCollection<AspnetMembershipEntity> usersPass = new EntityCollection<AspnetMembershipEntity>();
            RelationPredicateBucket bucketPass = new RelationPredicateBucket();
            bucketPass.PredicateExpression.Add(AspnetMembershipFields.PasswordFormat == 0);
            PrefetchPath2 pp = new PrefetchPath2(EntityType.AspnetMembershipEntity);
            pp.Add(AspnetMembershipEntity.PrefetchPathAspnetUsers);
            FetchEntityCollection(usersPass, bucketPass, 0, null, pp);
            foreach (AspnetMembershipEntity user in usersPass)
            {
                if (string.IsNullOrEmpty(user.PasswordSalt))
                    user.PasswordSalt =CreateSalt();
                user.Password = EncodePassword(user.Password, user.PasswordSalt);
                user.PasswordFormat = 1;
                uow.AddForSave(user, true);
  
            }
            CommitUnitOfWork(uow, true);
        }
  
        internal string CreateSalt()
        {
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            byte[] buff = new byte[32];
            rng.GetBytes(buff);
            return Convert.ToBase64String(buff);
        }
  
        internal string EncodePassword(string pass, string saltBase64)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(pass);
            byte[] src = Convert.FromBase64String(saltBase64);
            byte[] dst = new byte[src.Length + bytes.Length];
            Buffer.BlockCopy(src, 0, dst, 0, src.Length);
            Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
            HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
            byte[] inArray = algorithm.ComputeHash(dst);
            return Convert.ToBase64String(inArray);
        }
Regards,
Mario
This content has not been rated yet. 
2218 Reputation 300 Total posts
super

super

7/29/2013 3:13:50 PM
Instead of doing it from the code, can I do it manually ?

1) I can delete the users from the database
2) Change webconfig to "Hashed"
3) now register a new user
4) Manually go in database and add that user as admin role ?

Is this approach correct ?
This content has not been rated yet. 
6018 Reputation 709 Total posts
mzilic

mzilic

7/29/2013 3:33:51 PM
Hello Super,

You need to ensure that your database doesn't have any users in the scenario you are suggesting. But yeah this approach should work in theory.

Regards,
Mario
This content has not been rated yet. 
2218 Reputation 300 Total posts
super

super

7/29/2013 5:05:12 PM
Mzilic,

1) How I will run the above code ? just create new page and add that code to it and run it ? I have no idea what to do with the above code

2) I am trying to install monox new installation and trying to change webconfig setting to hashed before I install the database but by that way I am not able to install the monox ? it is asking me to enter database credentials again and again even after providing all the details ?

Comments: I am finding it quite a complex task to change the password to hash, by default, the password should be hashed / encrypted and if they are not encrypted, the process should be user-friendly. It is quite complex right now. If according to development. team it is recommended to encryp the password before production, then the task must be user-friendly as each developer knowledge differ and you can't expect every one to perform such complex tasks just to change a simple but important setting.

Another reason to make this feature enable by default is if any admin forget to do this, it can lead to major security threat and privacy violation for users.
This content has not been rated yet. 
6018 Reputation 709 Total posts
khorvat

khorvat

7/30/2013 6:26:27 AM
Hi,

Comments: I am finding it quite a complex task to change the password to hash, by default, the password should be hashed / encrypted and if they are not encrypted, the process should be user-friendly. It is quite complex right now. If according to development. team it is recommended to encryp the password before production, then the task must be user-friendly as each developer knowledge differ and you can't expect every one to perform such complex tasks just to change a simple but important setting.
Process is user-friendly, you should have password format set to "Hashed" but in order for this to work you should change this setting "enablePasswordRetrieval="true"" to false. Because these two options are not compatible. 

I mentioned once why we keep the password format in MonoX Clear by default, so I don't to go into that again but it's important to know that you can have a mixin of password formats in your database so in the end you don't have to run the code above in order to convert clear passwords to hashed ones (although it's good practice to do so).

Let us know how would you like to proceed and get back to us on the error you get after you change the enablePasswordRetrieval to false.

Regards
This content has not been rated yet. 
15993 Reputation 2214 Total posts
mzilic

mzilic

7/30/2013 9:17:38 AM
Hello,

1) How I will run the above code ? just create new page and add that code to it and run it ? I have no idea what to do with the above code
You could create a new page and run the following code or create a console application and reference MonoX assemblies and run the code using that approach.

Regards,
Mario
This content has not been rated yet. 
2218 Reputation 300 Total posts
super

super

7/30/2013 11:19:25 AM
Process is user-friendly, you should have password format set to "Hashed" but in order for this to work you should change this setting "enablePasswordRetrieval="true"" to false. Because these two options are not compatible.
When I set password format to "Hashed" and "enablePasswordRetrieval="false", I don't get any error message and I can run the site and when I create a new user, the password does get saved as Hashed.


I mentioned once why we keep the password format in MonoX Clear by default, so I don't to go into that again
Yes, I understand the reason but I was saying that for majority of users, this Hashed feature should be set as default so that if any store admin forget to change this setting, the website data is still secured as this is an important thing.

For developers to customize the monox project, they should be able to change the setting to clear and enable password retrieval to true if they want to get the password for any other purpose. So, all I am saying is that it should be opposite of the current way of doing things. Hashed by default and option for making it unencrypted. I think that will make more sense rather than leaving the security option open by default.

This content has not been rated yet. 
6018 Reputation 709 Total posts
super

super

7/30/2013 11:22:44 AM
mzilic,

I created a page called "RunCode.aspx".

Here is my code and I am getting errors:

RunCode.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="RunCode.aspx.cs" Inherits="RunCode" %>
 
<!DOCTYPE html>
 
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
     
    </div>
    </form>
</body>
</html>

RunCode.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MonoSoftware.MonoX.Extensions;
using System.Security.Cryptography;
using SD.LLBLGen.Pro.ORMSupportClasses;
using MonoSoftware.MonoX.DAL.HelperClasses;
using MonoSoftware.MonoX.DAL.EntityClasses;
using MonoSoftware.MonoX.DAL;
 
namespace MonoSoftware.MonoX.Pages
{
 
    public partial class RunCode : BasePage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
 
        }
        internal void SwitchAllUserPasswordsToHashFormat()
        {
            UnitOfWork2 uow = new UnitOfWork2();
 
            EntityCollection<AspnetMembershipEntity> usersPass = new EntityCollection<AspnetMembershipEntity>();
            RelationPredicateBucket bucketPass = new RelationPredicateBucket();
            bucketPass.PredicateExpression.Add(AspnetMembershipFields.PasswordFormat == 0);
            PrefetchPath2 pp = new PrefetchPath2(EntityType.AspnetMembershipEntity);
            pp.Add(AspnetMembershipEntity.PrefetchPathAspnetUsers);
            FetchEntityCollection(usersPass, bucketPass, 0, null, pp);
            foreach (AspnetMembershipEntity user in usersPass)
            {
                if (string.IsNullOrEmpty(user.PasswordSalt))
                    user.PasswordSalt = CreateSalt();
                user.Password = EncodePassword(user.Password, user.PasswordSalt);
                user.PasswordFormat = 1;
                uow.AddForSave(user, true);
 
            }
            CommitUnitOfWork(uow, true);
        }
 
        internal string CreateSalt()
        {
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            byte[] buff = new byte[32];
            rng.GetBytes(buff);
            return Convert.ToBase64String(buff);
        }
 
        internal string EncodePassword(string pass, string saltBase64)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(pass);
            byte[] src = Convert.FromBase64String(saltBase64);
            byte[] dst = new byte[src.Length + bytes.Length];
            Buffer.BlockCopy(src, 0, dst, 0, src.Length);
            Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
            HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
            byte[] inArray = algorithm.ComputeHash(dst);
            return Convert.ToBase64String(inArray);
        }
    }
}


Errors:

Error   104 The name 'FetchEntityCollection' does not exist in the current context  C:\Users\Downloads\Projects\MonoX\RunCode.aspx.cs   32  13  C:\...\MonoX\
Error   105 The name 'CommitUnitOfWork' does not exist in the current context   C:\Users\Downloads\Projects\MonoX\RunCode.aspx.cs   42  13  C:\...\MonoX\
Error   106 The name 'Encoding' does not exist in the current context   C:\Users\Downloads\Projects\MonoX\RunCode.aspx.cs   55  28  C:\...\MonoX\
Error   107 'bool' does not contain a definition for 'BlockCopy' and no extension method 'BlockCopy' accepting a first argument of type 'bool' could be found (are you missing a using directive or an assembly reference?) C:\Users\Downloads\Projects\MonoX\RunCode.aspx.cs   58  20  C:\...\MonoX\
Error   108 'bool' does not contain a definition for 'BlockCopy' and no extension method 'BlockCopy' accepting a first argument of type 'bool' could be found (are you missing a using directive or an assembly reference?) C:\Users\Downloads\Projects\MonoX\RunCode.aspx.cs   59  20  C:\...\MonoX\
This content has not been rated yet. 
6018 Reputation 709 Total posts
mzilic

mzilic

7/30/2013 11:57:35 AM
Hello super,

This is just a code snippet which you need to adapt for your own purpose. If you are using your own custom DAL you will need to create a repository instance of your own BaseRepository otherwise you can use MonoX's.

You can read more on this topic over here:
http://www.mono-software.com/Blog/post/Mono/11/Data-access-layer-in-MonoX/
http://www.mono-software.com/Blog/post/Mono/102/MonoX-API/
http://www.mono-software.com/Blog/post/Mono/129/MonoX-architecture-explained-the-UI/
This article contains a few useful links:
http://www.mono-software.com/Blog/post/Mono/214/MonoX-on-GitHub/

For the BlockCopy you can view more information here: http://msdn.microsoft.com/en-us/library/system.buffer.blockcopy.aspx

Regards,
Mario
This content has not been rated yet. 
2218 Reputation 300 Total posts
1 2