title: Adding forms authentication (SimpleMembership) to webapi app
body: <p>I'm trying to add to a MVC4 webapi project the simple membership provider authentication mechanism found in a MVC 4 web application project, for a hybrid application serving its pages with a rich JS content, which uses AJAX calls to webapi actions to perform its tasks. I need the app users to authenticate before they can work with the apps provided in these pages, so I think I'll be fine with the forms authentication. I thus need to add it to the existing WebApi project and let my authorized-only actions return a 302 (redirect user to login page) rather than a 401.</p>
  
  <p>Anyway, I'm missing something because as soon as I try to use a WebSecurity method I get the following exception:</p>
  
  <p><code><pre>System.InvalidOperationException was caught
    Message=To call this method, the "Membership.Provider" property must be an instance of "ExtendedMembershipProvider".
    Source=WebMatrix.WebData
  </pre></code></p>
  
  <p>Could anyone suggest a fix? Here are the steps I took for adding authorization:</p>
  
  <p>1) Web.config: add to system.web:</p>
  
  <pre><code>&lt;authentication mode="Forms"&gt;
      &lt;forms loginUrl="~/Account/Login" timeout="2880" /&gt;
  &lt;/authentication&gt;
  </code></pre>
  
  <p>Add to appsettings (the 2nd entry is for replacing 401 with 302):</p>
  
  <pre><code>&lt;add key="enableSimpleMembership" value="true"/&gt;
  &lt;add key="webapi:EnableSuppressRedirect" value="false" /&gt;
  </code></pre>
  
  <p>Also remove profile, membership and rolemanager sections from the original template (they are not intended to be used with simple membership).</p>
  
  <p>2) add NuGet packages for OpenAuth (DotNetOpenAuth Core, DotNetOpenAuth ext for ASP.NET, DotNetOpenAuth 1.0(a) consumer, DotNetOpenAuth 1.0(a), DotNetOpenAuth OpenID Core, DotNetOpenAuth OpenID Relying Party).</p>
  
  <p>3) add InitializeSimpleMembership.cs to Filters (the code is pretty standard, see below).</p>
  
  <p>4) copy from an MVC web app project the models in AccountModels.cs, all the views in Views/Account, and the AccountController.cs.</p>
  
  <p>The InitializeSimpleMembership code is here:</p>
  
  <pre><code>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
  public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
  {
      private static SimpleMembershipInitializer _initializer;
      private static object _initializerLock = new object();
      private static bool _isInitialized;
  
      public override void OnActionExecuting(ActionExecutingContext filterContext)
      {
          LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
      }
  
      private class SimpleMembershipInitializer
      {
          private static void SeedData()
          {
              // seed data: users and roles
              if (!WebSecurity.UserExists("TheAdminGuyName"))
                  WebSecurity.CreateUserAndAccount("TheAdminGuyName", "password");
  
              if (!Roles.RoleExists("administrator")) Roles.CreateRole("administrator");
  
              if (!Roles.IsUserInRole("TheAdminGuyName", "administrator"))
                  Roles.AddUserToRole("TheAdminGuyName", "administrator");
          }
  
          public SimpleMembershipInitializer()
          {
              Database.SetInitializer&lt;UsersContext&gt;(null);
              try
              {
                  using (var context = new UsersContext())
                  {
                      if (!context.Database.Exists())
                      {
                          ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
                      }
                  }
                  WebSecurity.InitializeDatabaseConnection("DefaultConnection", "User", "UserId", "UserName", autoCreateTables: true);
                  SeedData();
              }
              catch (Exception ex)
              {
                  throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
              }
          }
      }
  }
  </code></pre>