0
votes

I'm new to web development and particular to web API (rest service) development. I've studied how to develop MVC projects using entity framework and membership. When I needed to use authentication and authorization I simply added the AUTHORIZE attribute to the controller/action. In order to add user, I've used the Register action on the Account controller.

Now I have a new project which is a web API project in MVC 5 (Visual studio 2013). I've added a new user using the default api action - Register (using fidler). Now, I'm trying to simply use a get method to read some data, but when adding the AUTHORIZE attribute and also add the correct user name and password I'm keep getting 401 (unauthorized) response. And then I've founded this thread:

ASP.NET MVC 4 Web API Authentication with Membership Provider

Bur now, the method Membership.ValidateUser(username, password) always returning false, I'm assuming I have to define the membership database, where do I do it?

Here is the full code:

using System;
using System.Net.Http;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Security;


public class BasicAuthenticationMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage>         SendAsync(HttpRequestMessage     request, CancellationToken cancellationToken)
{
    var authHeader = request.Headers.Authorization;

    if (authHeader == null)
    {
        return base.SendAsync(request, cancellationToken);
    }

    if (authHeader.Scheme != "Basic")
    {
        return base.SendAsync(request, cancellationToken);
    }

    var encodedUserPass = authHeader.Parameter.Trim();
    var userPass = Encoding.ASCII.GetString(Convert.FromBase64String(encodedUserPass));
    var parts = userPass.Split(":".ToCharArray());
    var username = parts[0];
    var password = parts[1];

    if (!Membership.ValidateUser(username, password))
    {
        return base.SendAsync(request, cancellationToken);
    }

    var identity = new GenericIdentity(username, "Basic");
    string[] roles = Roles.Provider.GetRolesForUser(username);
    var principal = new GenericPrincipal(identity, roles);
    Thread.CurrentPrincipal = principal;
    if (HttpContext.Current != null)
    {
        HttpContext.Current.User = principal;
    }

    return base.SendAsync(request, cancellationToken);
}
}

Here is where I've added the handler:

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        GlobalConfiguration.Configuration.MessageHandlers.Add(
new BasicAuthenticationMessageHandler()
);
    }
}

Thanks in advance, Shaul

2
If that is WebAPI project - check IdentityConfig in app_start and StartUp.csDavid Abaev
It is a webAPI project, check for what?Shaul Zuarets
What you set in context, what is your ApplicationManager, and check what you use in your controller. I will can write in few hours, if you will still need helpDavid Abaev

2 Answers

1
votes

Define the Membership database in the Web.Config as follows :

<connectionStrings>
<add name="test_connStr" connectionString="" />
</connectionStrings>

<system.web>
<membership defaultProvider="test_provider">
      <providers>
        <clear />
        <add name="test_provider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="test_connStr" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" passwordAttemptWindow="10" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="0" applicationName="/" />
      </providers>
    </membership>
</system.web>

Set the connectionString to Membership database connection string. And the connectionStringName should be the name of the connection string defined.

EDIT :

Sorry I am a bit late on this. Check the contents of aspnet_SchemaVersions table. It should contain the following :

common              1   True
health monitoring   1   True
membership          1   True
personalization     1   True
profile             1   True
role manager        1   True

As shown in this answer.

0
votes

In order to use simple membership provider I've used this simple tutorial: http://monox.mono-software.com/blog/post/Mono/226/Adding-ASP-NET-SimpleMembership-to-an-existing-MVC-4-application/ But it still had a simple bug which was solved by adding the Nuget package: Microsoft.AspNet.WebHelpers.

That's all.