This this a SimpleMembership implementation using MongoDB as the backing store that provides a custom Membership provider (ExtendedMembershipProvider to be exact) and Role provider.
For more information about SimpleMembership see this post by Jon Galloway : SimpleMembership, Membership Providers, Universal Providers and the new ASP.NET 4.5 Web Forms and ASP.NET MVC 4 templates
Available on NuGet:
PM> Install-Package LyphTEC.MongoSimpleMembership
You must complete the following steps after you have installed the NuGet package before your app will run:
Configure your data connection string to the MongoDB database
eg.
<connectionStrings>
<clear/>
<add name="MongoSimpleMembership" connectionString="mongodb://localhost/SimpleMembership?safe=true" />
</connectionStrings>
Note that the connection string must also include the database name. In the example above, this will use the database named "SimpleMembership".
Update the system.web/membership & system.web/roleManager sections to use the connection string name as defined above
Also make sure that the "defaultProvider" attributes are set to use the matching MongoSimpleMembership provider names.
eg.
<membership defaultProvider="MongoSimpleMembershipProvider">
<providers>
<clear />
<add name="MongoSimpleMembershipProvider" type="LyphTEC.MongoSimpleMembership.MongoSimpleMembershipProvider, LyphTEC.MongoSimpleMembership" connectionStringName="MongoSimpleMembership" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="MongoRoleProvider">
<providers>
<clear />
<add name="MongoRoleProvider" type="LyphTEC.MongoSimpleMembership.MongoRoleProvider, LyphTEC.MongoSimpleMembership" connectionStringName="MongoSimpleMembership" />
</providers>
</roleManager>
If you are using the default "ASP.NET MVC4 Internet" template. You must make some changes to AccountController:
Remove the [InitializeSimpleMembership]
attribute (the ActionFilterAttribute defined in Filters/InitializeSimpleMembershipAttribute.cs).
This is used by the default SimpleMembershipProvider that needs to initialize SQL Server.
Since we are not using SQL Server, this is no longer required.
Make changes to the ExternalLoginConfirmation() method to remove Entity Framework related hooks used by the default SimpleMembershipProvider.
Here's what it looks like before the change:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)
{
string provider = null;
string providerUserId = null;
if (User.Identity.IsAuthenticated || !OAuthWebSecurity.TryDeserializeProviderUserId(model.ExternalLoginData, out provider, out providerUserId))
{
return RedirectToAction("Manage");
}
if (ModelState.IsValid)
{
// Insert a new user into the database
using (UsersContext db = new UsersContext())
{
UserProfile user = db.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == model.UserName.ToLower());
// Check if user already exists
if (user == null)
{
// Insert name into the profile table
db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
db.SaveChanges();
OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("UserName", "User name already exists. Please enter a different user name.");
}
}
}
ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(provider).DisplayName;
ViewBag.ReturnUrl = returnUrl;
return View(model);
}
And here's what it should look like after the change:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)
{
string provider = null;
string providerUserId = null;
if (User.Identity.IsAuthenticated || !OAuthWebSecurity.TryDeserializeProviderUserId(model.ExternalLoginData, out provider, out providerUserId))
{
return RedirectToAction("Manage");
}
if (ModelState.IsValid)
{
// check if user exists
if (!WebSecurity.UserExists(model.UserName))
{
// TODO : Add custom user profile logic here
// this will create a non-local account
OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("UserName", "User name already exists. Please enter a different user name.");
}
}
ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(provider).DisplayName;
ViewBag.ReturnUrl = returnUrl;
return View(model);
}
See the sample MVC4 app for reference.
By default, the persisted entities are stored in collections with the following names:
This matches the table names used in the standard SQL Server based SimpleMembershipProvider.
If desired, you can change the default collection names by using the following appSettings:
<appSettings>
<add key="MongoSimpleMembership:MembershipAccountName" value="webpages_Membership" />
<add key="MongoSimpleMembership:OAuthMembershipName" value="webpages_OAuthMembership" />
<add key="MongoSimpleMembership:OAuthTokenName" value="webpages_OAuthToken" />
<add key="MongoSimpleMembership:RoleName" value="webpages_Role" />
</appSettings>