1

I am trying to use UserSecret in Asp.net MVC with a .Net framework 4.8. I am having issues with accessing ConnectionString via UserSecret the reason is I am also using Membership provider and Entityframework edmx file. The following code I am using to access connectionstring

<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false" />
  </configSections>
  <configBuilders>
    <builders>
      <add name="Secrets" mode="Greedy" userSecretsId="b503099f-e1d9-4700-9e50-cf4081a700e3" type="Microsoft.Configuration.ConfigurationBuilders.UserSecretsConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.UserSecrets, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </builders>
  </configBuilders>

<connectionStrings configBuilders="Secrets">
    <remove name="LocalSqlServer" />
    <add name="LocalSqlServer" connectionString="" providerName="System.Data.SqlClient" />
    <add name="HIPAADbEntities" connectionString="" providerName="System.Data.EntityClient" />
  </connectionStrings>

after writing above code when I run the application I am having following errors

enter image description here

These are the line of code written in web.config which gives me error

<membership userIsOnlineTimeWindow="120">
      <providers>
        <remove name="AspNetSqlMembershipProvider" />
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="LocalSqlServer" enablePasswordRetrieval="true" enablePasswordReset="false" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEmail="false" passwordFormat="Encrypted" maxInvalidPasswordAttempts="25" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
        <add name="MyMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="LocalSqlServer" enablePasswordRetrieval="true" enablePasswordReset="false" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEmail="false" passwordFormat="Encrypted" maxInvalidPasswordAttempts="25" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
      </providers>
    </membership>

The UserSecret file is as follows

<?xml version="1.0" encoding="utf-8"?>
<root>
  <secrets ver="1.0">
    <secret name="LocalSqlServer" value="Data Source=.;Initial Catalog=TestDB;Integrated Security=True"></secret>
  </secrets>

</root>

How to access UserSecret in membership tag which have access to connectionstring? Without UserSecrets it works fine. But I need to make it work with Usersecret

Imre Pühvel
  • 4,468
  • 1
  • 34
  • 49
Haseeb Khan
  • 930
  • 3
  • 19
  • 41
  • Is the database attached to a SQL Server or are you using a local database which requires an mdf file? If the database is attached to a server than you cannot connect using a local database (the server owns the file). So the connection string must use the SQL Server name and instance. – jdweng Mar 09 '20 at 12:33
  • Yes database is attached and Yes I am using local DB. If I don't use UserSecret it works fine. The issue I am only facing with UserSecret – Haseeb Khan Mar 09 '20 at 13:09
  • What is the connection string (connectionStringName="LocalSqlServer")? The code is probably ignoring the Configuration file for localdB. Windows needs a credential and not a user name and password. If you login to database using SQL Server Management Studio does it say Windows Credential in login window. – jdweng Mar 09 '20 at 13:16
  • this is my connection string Data Source=.;Initial Catalog=TestDB;Integrated Security=True – Haseeb Khan Mar 09 '20 at 13:17
  • Then you don't need to encrypt the connection strings at all. There's no reason to use another `UserSecret` file. The connection is made using the application pool's Windows account – Panagiotis Kanavos Mar 09 '20 at 13:20
  • I need to implement UserSecret. ia m half way through. I am stuck while accessing membership provider. Rest all works fine – Haseeb Khan Mar 09 '20 at 13:26
  • No you don't - it doesn't offer any additional security. You already avoid storing credentials in the source code - that's it's only use. `UserSecrets` doesn't even encrypt its content. If you really wanted to encrypt sections of `web.config` you should use `aspnet_regiis` as shown in [Using Encryption to Protect Passwords](https://learn.microsoft.com/en-us/iis/manage/configuring-security/using-encryption-to-protect-passwords) BUT you don't have any passwords to protect – Panagiotis Kanavos Mar 09 '20 at 13:27
  • Integrated Security means you are using the Windows Credential of the user who is logged in so no username or password is required. When you setup a Windows Credential you usually create a group account in Windows. Then make the database use the Group account as the credentials. Then add users to the windows group account. – jdweng Mar 09 '20 at 13:38
  • In fact, `UserSecrets` *can weaken security in production* - if anyone forgets it's actually useless and tries to store a username/password in there, someone else could just read those unencrypted credentials. – Panagiotis Kanavos Mar 09 '20 at 13:39
  • Well I have read UserSecret is the most preferred way to store secrets like API keys , payment credentials etc. and It was introduced after 4.7.1 framework. – Haseeb Khan Mar 09 '20 at 14:35

1 Answers1

2

I faced similar issue trying to get connection string in the same way as is possible for AppSettings values using User Secrets functionality. The main problem is that connection strings values don't have the same structure as AppSettings so is not possible to populate them in the exactly same way.

Regarding documentation you have three modes to get values from UserSecrets.

image about three modes available

Strict and Greedy modes works well for AppSettings but no for connection strings.

The way I found to solve that is using Expand mode just for ConnectionStrings section. You should create two entries in builders, both pointing to the same file and the main difference will be its names and modes.

Here is an example of what I said.

Web.config file

...
<configBuilders>
<builders>
    <add name="AppSettings_Secrets" userSecretsId="STRING_UNIQUE_ID" type="Microsoft.Configuration.ConfigurationBuilders.UserSecretsConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.UserSecrets, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    <add name="ConnectionStrings_Secrets" mode="Expand" userSecretsId="STRING_UNIQUE_ID" type="Microsoft.Configuration.ConfigurationBuilders.UserSecretsConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.UserSecrets, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</builders>
</configBuilders>
<appSettings configBuilders="AppSettings_Secrets">
    <add key="MY_KEY_01" value="xxx" />
    <add key="MY_KEY_02" value="xxx" />
</appSettings>
<connectionStrings configBuilders="ConnectionStrings_Secrets">
    <add name="defaultConnection" connectionString="${CONNECTION_STRING}" />
</connectionStrings>
...

Take in mind that if you want to manage all secrets in the same file secrets.xml you must use the same value on userSecretsId="STRING_UNIQUE_ID" for both builders.

secrets.xml file

<?xml version="1.0" encoding="utf-8"?>
<root>
  <secrets ver="1.0">
    <secret name="MY_KEY_01" value="Key value 01" />
    <secret name="MY_KEY_02" value="Key value 02" />
    <secret name="CONNECTION_STRING" value="Connection string value" />
  </secrets>
</root>
gsubiran
  • 2,012
  • 1
  • 22
  • 33