Security using the Membership provider that will support Active Directory and your own bespoke provider - active-directory

I have a task of dealing with security on my .Net web application, the way it is to work is that if the user is logged in to Active Directory and the users AD name is in a database then they will be let in.
On the same bases if the users AD name is not in the database then they will be asked to login, with a user name and password, held in the database.
So I need some kind of mix mode security login using the Membership and Role provider.
Where I am having trouble is where do you detect if a user can login using AD, so they get logged in automatically.

Sounds like you'll need to implement a custom MembershipProvider that inherits from ActiveDirectoryMembershipProvider.
At a minimum, you'll need to override ValidateUser so that if the base.ValidateUser returns false, you can attempt to validate the user in your SQL database. The following code sample works in my test application, however I did not implement the SQL method. That should be pretty straight forward for you.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Configuration;
using System.Configuration.Provider;
namespace Research.Web.Security
{
public class MixedMembershipProvider : ActiveDirectoryMembershipProvider
{
protected String SqlConnectionString { get; private set; }
private String GetConnectionString(String connectionStringName)
{
if (string.IsNullOrEmpty(connectionStringName))
throw new ProviderException("ConnectionStringName must be specified.");
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[connectionStringName];
if (settings == null)
{
throw new ProviderException(String.Format("Connection string {0} not found.", connectionStringName));
}
return settings.ConnectionString;
}
public override void Initialize(String name, System.Collections.Specialized.NameValueCollection config)
{
this.SqlConnectionString = GetConnectionString(config["sqlConnectionStringName"]);
config.Remove("sqlConnectionStringName");
base.Initialize(name, config);
}
public override Boolean ValidateUser(String username, String password)
{
if (!base.ValidateUser(username, password)) // validate using AD first
{
return ValidateUserSql(username, password); // if not in AD, check SQL
}
else
{
return true;
}
}
private Boolean ValidateUserSql(String username, String password)
{
// look up your account in SQL here
return true;
}
}
}
Your web config would look something like this:
<configuration>
<!-- usual config stuff omitted -->
<connectionStrings>
<add name="SqlDefault" connectionString="Server=localhost;database=mydatabase;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
<add name="ActiveDirectoryDefault" connectionString="LDAP://mydomain.com/DC=mydomain,DC=com" />
</connectionStrings>
<system.web>
<!-- usual config stuff omitted -->
<membership defaultProvider="Mixed">
<providers>
<clear/>
<add name="Mixed"
type="Research.Web.Security.MixedMembershipProvider, Research.Web"
applicationName="/"
connectionStringName="ActiveDirectoryDefault"
sqlConnectionStringName="SqlDefault"
connectionUsername="mydomain\myadmin"
connectionPassword="mypass"/>
</providers>
</membership>
<!--- usual config stuff omitted -->
</system.web>
</configuration>
The above code will work for basic authentication, but you may need to override some of the other methods to handle password resets, lookups, etc. for the eventuality that an account is in SQL and not AD.

Related

How to get C1 CMS username of current logged in user, not the windows user

I'm trying to filter records from a C1 CMS data folder in the Console as part of a staff profile system on my website. What I'd like to do is show a single profile record for the staff member who is logged into the C1 Console, so that they can only edit their own staff profile and nobody else's. To do this, I'd like to match up the username they logged in with with a field in the data folder for the profiles.
So far I've created the datatype BaileyWeb.University.People, some sample records, and have added tree file:
<?xml version="1.0" encoding="UTF-8"?>
<ElementStructure xmlns="http://www.composite.net/ns/management/trees/treemarkup/1.0" xmlns:f="http://www.composite.net/ns/function/1.0">
<ElementStructure.AutoAttachments>
<NamedParent Name="Content" Position="Bottom"/>
</ElementStructure.AutoAttachments>
<ElementRoot>
<Children>
<Element Label="My Profile Function" Id="MyProfileRoot" Icon="user-group">
<Children>
<DataElements Type="BaileyWeb.University.People" Label="${C1:Data:BaileyWeb.University.People:DisplayName}" Icon="user">
<Actions>
<EditDataAction Label="Edit My Profile" />
<DeleteDataAction Label="Delete My Profile" />
</Actions>
<Filters>
<FunctionFilter>
<f:function name="BaileyWeb.University.Data.MyProfile.MyFilter" xmlns:f="http://www.composite.net/ns/function/1.0" />
</FunctionFilter>
</Filters>
</DataElements>
</Children>
</Element>
</Children>
</ElementRoot>
</ElementStructure>
In my C# function, I do the filtering, as per the documentation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
namespace BaileyWeb.University.Data
{
public class MyProfile
{
public static Expression<Func<BaileyWeb.University.People, bool>> MyFilter()
{
Expression<Func<BaileyWeb.University.People, bool>> filter = f => f.UserId.Contains(System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString());
return filter;
}
}
}
Unfortunately, this doesn't work, and I'm not sure why.
I'm NOT using the Active Directory login add-on, so domain logins aren't being used here. I've tried swapping out System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString() for a simple string of "admin" (which is used as a UserID for one record in the datatype) to test it, but this also fails to return a result.
When I went back to the basic tree filtering:
<Filters>
<ParentIdFilter ParentType="BaileyWeb.University.People" ReferenceFieldName="UserId" />
<FieldFilter FieldName="UserId" FieldValue="admin"/>
</Filters>
... I got a result displayed, but this was for a static username value of "admin".
Can anyone help me solve this problem?
Did you ask for logged C1 username?
Composite.C1Console.Security.UserValidationFacade.GetUsername()

Error while creating context in Entity Framework

I am developing a WPF application that uses Entity Framework v.6 with the approach Code First to build and manage a local database which is created on the client computer itself.
When I install the application on a client computer and launch it, I receive the following error when the context tries to create the database:
Expansion of |DataDirectory| failed while processing the connection string. Ensure that |DataDirectory| is set to a valid fully-qualified path.
In app.config I have set the following configuration of Entity Framework:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb"/>
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
</providers>
</entityFramework>
My context class contains the following code:
class EntityContext : DbContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<Trip> Trips { get; set; }
public DbSet<Volunteer> Volunteers { get; set; }
public DbSet<Motivation> Motivations { get; set; }
public DbSet<PaymentType> PaymentTypes { get; set; }
public EntityContext() : base("StaccoDataBase")
{
System.Data.Entity.Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>());
}
}
I have tried to fix the problem setting the |DataDirectory| in the App.xaml.cs as follows:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.SetData("DataDirectory", Directories.DBDirectory);
}
But the issue still persists.
I would really appreciate if someone can help me.
Just a wild guess - what if you used this connection string:
Data Source=(LocalDb)\\MSSQLLocalDB; AttachDBFilename=|DataDirectory|StaccoDataBase.mdf; integrated security=SSPI
First of all, use the |DataDirectory| directly in your connection string (don't "inject" it via that string.Format() call), and secondly, add the .mdf extension to the database file you want to attach.
Also, I'd store this connection string in the app.config - don't create it at runtime, because the constructor call here:
public EntityContext() : base("StaccoDataBase")
will try to find StaccoDataBase as a connection string name in your config file.
So use this:
app.config:
<configuration>
.....
<connectionStrings>
<add name="StaccoDataBase"
connectionString="Data Source=(LocalDb)\\MSSQLLocalDB;AttachDBFilename=|DataDirectory|StaccoDataBase.mdf; integrated security=SSPI"
providerName="System.Data.SqlClient" />
<connectionStrings>
.....
</configuration>

Encrypting username token with apache cxf

Greetings good people.
I have a soap web service that I want to consume.I have created a small project to simulate what is required in the actual project especially on the username token encryption.
There are steps provided on how to encrypt the password on the client side as listed below:
Write the unencrypted password value.
Then, encrypt the block of data created in step 1 with the public portion of the password key certificate. Use the RSA algorithm, and use PKCS #1.5 padding (not OAEP), and add the result to the encrypted stream – this becomes the encrypted password which is submitted via the API.
Convert the resulting encrypted byte array into a string using base64 encoding. Present this base64 encoded string in the API request as the initiator SecurityCredential value.
Password to be encrypted with a public key from an X509 certificate issued to the Initiator specifically for this purpose.
So far I have been able to create a client and the server and I'm able to send a request and get a response.
I'm also able to secure the web service by passing a username token with password as plain text in the ClientPasswordCallback class and checking these credentails in the ServerPasswordCallback class.
I have gone further and in a seperate request encrypted the body part of the message using wss4j, RSA, X509 whereby I have public key stored in the clientKey.jks and a private key stored in privateKey.jks and by providing appropriate passwords in client and server password call back handlers I have been able to encrypt the body part at the client and decrypt it at the server.
The Challenge: The main challenge I'm experiencing is combining the two steps above in a single request such that using the public key, I'm able to encrypt the password in the username token and decrypt the same at the server side using the private key.
NB I have generated the keys for testing using keygen tool that comes with the jdk.
I'm imagining that there will be two passwords in the ClientPasswordCallback class, one for the clientKey.jks keystore and the other other password that needs to be encrypted.
This is what I have been able to archive so far:
Client side
TestMathUtility class
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
// Use the URL defined in the soap address portion of the WSDL
factory.setAddress("http://localhost:8080/MathUtility/services/MathUtilityPort");
// Utilize the class which was auto-generated by Apache CXF wsdl2java
factory.setServiceClass(MathUtility.class);
Object client = factory.create();
// Adding Logging Interceptors
LoggingOutInterceptor loggingOutInterceptor = new LoggingOutInterceptor();
loggingOutInterceptor.setPrettyLogging(true);
ClientProxy.getClient(client).getOutInterceptors().add(loggingOutInterceptor);
LoggingInInterceptor loggingInInterceptor = new LoggingInInterceptor();
loggingInInterceptor.setPrettyLogging(true);
ClientProxy.getClient(client).getInInterceptors().add(loggingInInterceptor);
// Set up WS-Security Encryption
// Reference: https://ws.apache.org/wss4j/using.html
Map<String, Object> props = new HashMap<String, Object>();
props.put(WSHandlerConstants.USER, "testkey");
props.put(WSHandlerConstants.ACTION, WSHandlerConstants.ENCRYPT);
props.put(WSHandlerConstants.PASSWORD_TYPE, "PasswordText");
props.put(WSHandlerConstants.ENC_PROP_FILE, "clientKeystore.properties");
props.put(WSHandlerConstants.ENCRYPTION_PARTS, "{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body");
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());
WSS4JOutInterceptor wss4jOut = new WSS4JOutInterceptor(props);
ClientProxy.getClient(client).getOutInterceptors().add(wss4jOut);
try {
// Call the Web Service to perform an operation
int response = ((MathUtility)client).addIntegers(5, 10);
System.out.println("Response we've got ========= "+response);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
ClientPasswordCallback class
public class ClientPasswordCallback implements CallbackHandler {
#Override
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
// set the password for our message.
pc.setPassword("clientstorepass");
}
}
Server side
MathUtility class
#WebService(targetNamespace = "http://utility.math.com/", portName = "MathUtilityPort", serviceName = "MathUtilityService")
public class MathUtility {
public int addIntegers(int firstNum, int secondNum) {
return firstNum + secondNum;
}
public int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result = result * i;
}
return result;
}
}
ServerPasswordCallback class
public class ServerPasswordCallback implements CallbackHandler {
#Override
public void handle(Callback[] arg0) throws IOException,
UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) arg0[0];
// set the password for our message.
pc.setPassword("storepass");
}
}
cxf-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<bean id="myPasswordCallback" class="com.math.utility.security.ServerPasswordCallback"/>
<jaxws:endpoint xmlns:tns="http://utility.math.com/" id="mathutility"
implementor="com.math.utility.MathUtility" wsdlLocation="wsdl/mathutility.wsdl"
endpointName="tns:MathUtilityPort" serviceName="tns:MathUtilityService"
address="/MathUtilityPort">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
<jaxws:inInterceptors>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="user" value="testkey"/>
<entry key="action" value="Encrypt"/>
<entry key="passwordType" value="PasswordText"/>
<entry key="decryptionParts" value="{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body"/>
<entry key="decryptionPropFile" value="serverKeystore.properties"/>
<entry key="passwordCallbackRef">
<ref bean="myPasswordCallback"/>
</entry>
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
</jaxws:endpoint>
clientKeyStore.properties file the same structure is used on the server side
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.file=clientkeystore.jks
org.apache.ws.security.crypto.merlin.keystore.password=clientstorepass
org.apache.ws.security.crypto.merlin.keystore.type=jks
The .jks files used have not been provided
NB I'm not using spring.
If you want to have a custom digest you could override the method verifyCustomPassword(UsernameToken usernameToken,
RequestData data) in UsernameTokenValidator
To hook it up to your webservice have a look at my answer to another SO-question. The essentials of this answers are:
<property name="wssConfig">
<ref bean="usernameTokenWssConfig"/>
</property>
And add the referenced class to your codebase:
#Component("usernameTokenWssConfig")
public class UsernameTokenWssConfig extends WSSConfig {
public UsernameTokenWssConfig() {
setValidator(WSSecurityEngine.USERNAME_TOKEN, new CustomUsernameTokenValidator());
setRequiredPasswordType(WSConstants.CUSTOM_TOKEN );
}
}
This is how I did the encryption Of UT using encryption parts
outProps.put(
WSHandlerConstants.ENCRYPTION_PARTS,
"{Content}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken"
);
In order to encrypt the username token with the encryption parts . Add the SOAP header namespace inside the second curly braces
I got an encrypted UT like below(I only encrypted the content only you can do the element if you want)
<wsse:UsernameToken wsu:Id="UsernameToken-99bea96d-c6ef-444c-aa8a-ec807f58aa0c">
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="ED-59f84d2b-3195-436f-b8f4-513fea23c00a" Type="http://www.w3.org/2001/04/xmlenc#Content">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey">
<wsse:Reference URI="#EK-748c3d27-f6be-4b81-b864-87bc6457e247" />
</wsse:SecurityTokenReference>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>wSZsu9LR6q9fpUPYYF5GSA7T/3iZWMd0cB/80Z33DThzCB0kqnupGETVmGfVQheGUc3O+/B4X7i70aMTyOo5u0fIqa4kwrlKZBe9he359mpgakKgC4wOb65sDThT1fH4PvY6TSBjIOJ0T5jIyt1pGwacRLzmvFxxHxr3qfAOf27LLGJ0P0eAKchE19nAkfP+Tc2GbAkcxi/4SDQ7bBWVaveRgSET0dpheooBGORtt4VJ/dyMwogupAyJKoiqe3RFRCvsmK/UtkVGQYh/W14ei/s7G3mVAch8fQZXCS8jcEaqzkDaNzrZo8+IjJFgrPQY23g3fp57QXIDB84NNUhsm7NHXMNfAq7x97kng+Qwke6uqHcMPjGI9boKw/wZmhipYstFzUpOpF86W9FwcJPyTFR58jvdnX5OGJ1wFbFdI9cAjWdncIEmnOTl69pKRmGmbJYj7Ie43q+eNH/1+2RawBRhZG43VLZL5C7ydFu0xJ2DsD4nacvDfH0i8tcMCHyHkWf2po9Y/dBtS2kWAxfNxWQNvI1BceumsMvpSzK7WjXPJ/vaKlMoSQJtsBxg9RhA
</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</wsse:UsernameToken>

C# Connection String

I am using the following connection string within the <configuration> node. But somehow, it seems that it is not saving. Every time I use
System.Configuration.ConfigurationManager.ConnectionStrings["myDB"].ConnectionString
it has a null value, and when I check the index "0" it points to .\SQLEXPRESS.
<connectionStrings>
<clear/>
<add name="myDB"
providerName="System.Data.SqlClient"
connectionString="Server=Server\Instance;Database=anydb;User Id=***; Password=***;" />
</connectionStrings>
The projects is an ASP.NET MVC 2 project.
I really need this to work, since I am learning the code-first Entity Framework. Is there any suggestions?
Things to trouble-shoot on this :
Ensure that EF is configured to use your connection string. You can do this in you DbContext class by passing the connection string name into the base constructor :
public class YourContext : DbContext
{
public YourContext()
: base("myDB")
{
}
}
Ensure that the connection string is the correct web.config (ie in the main root not in Views)
Check that the connection string is not being overridden in the web.debug.config (or web.release.config) if it is being

MVC 4 - after seeding database webpages_Roles is still empty

So I have basic MVC 4 Internet application project with Entity Framework 5.
I have configured WebSecurity that uses my table for users.
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "Email", autoCreateTables: true);
Then in my migration configuration class I seed DB with new roles and add users to them.
internal sealed class Configuration : DbMigrationsConfiguration<Infrastructure.KlepecV2Db>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(Infrastructure.KlepecV2Db context)
{
if(!Roles.RoleExists("Admin"))
{
Roles.CreateRole("Admin");
}
if (!Roles.RoleExists("Test1"))
{
Roles.CreateRole("Test1");
}
if(Membership.GetUser("user1") != null)
{
if(!Roles.IsUserInRole("user1","Admin"))
{
Roles.AddUserToRole("user1", "Admin");
}
}
if (Membership.GetUser("user2") != null)
{
if (!Roles.IsUserInRole("user2", "Admin"))
{
Roles.AddUserToRole("user2", "Admin");
}
}
}
}
So when I type "update-database" in NuGet console everything gets executed without errors. But if I look into webpages_Roles table its empty. Also webpages_UsersInRoles is empty.
For testing I have removed Role.RoleExists() calls and updating database fails, becouse roles already exists.
What am I missing here? Where are this roles stored?
I came across into an error The Role Manager feature has not been enabled mentioned by #Magnus. Hope this probably related to your roles issue in which the default role provider is unknown.
The error The Role Manager feature has not been enabled happened when I move the WebSecurity.InitializeDatabaseConnection method from MVC project into a class library (data access) for code first migration seed.
The point is App.config need to be configured for Package Manager Update-Database command to be run just like when Web.config exist.
Below is my App.config and Seed. Note that
I add "DefaultConnection" connection string *
Add system.web->roleManager to set the enable="true"
Add runtime->assemblyBinding->qualifyAssembly to give hint to compiler where is WebMatrix.WebData by giving the full assembly name.
App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<!--<add name="DefaultConnection" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Db;Persist Security Info=True;User=user;Password=pass" providerName="System.Data.SqlClient" />-->
</connectionStrings>
<system.web>
<roleManager enabled="true" defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
<membership defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
</system.web>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<qualifyAssembly partialName="WebMatrix.WebData" fullName="WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
</configuration>
Seed Method:
protected override void Seed(DatabaseContext context)
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "Email", autoCreateTables: true);
if(!Roles.RoleExists("Admin"))
{
Roles.CreateRole("Admin");
}
if (!Roles.RoleExists("Test1"))
{
Roles.CreateRole("Test1");
}
if(Membership.GetUser("user1") != null)
{
if(!Roles.IsUserInRole("user1","Admin"))
{
Roles.AddUserToRole("user1", "Admin");
}
}
if (Membership.GetUser("user2") != null)
{
if (!Roles.IsUserInRole("user2", "Admin"))
{
Roles.AddUserToRole("user2", "Admin");
}
}
}
Hope this will help anyone with The Role Manager feature has not been enabled issue when using code first migration seed in a class library.
Update
* EF5 will read the connection string in Web.config of Mvc project but not in the App.config of the project with EF Migrations. However the membership and roleManager settings is still required in the EF Migration project.
Wanted to add my $0.02 to the conversation. I have a similar setup to CallMeLaNN, but was still getting the error. My solution was to set my "Data" project to a StartUp project. After that, my app.config file started getting picked up, and I can now seed my users from the Update-Database command.

Resources