ASP.NET MVC 4 Web API Authentication Using a Membership Provider

I have an ASP.NET MVC 4 project using web API. On the controller, I set the authorization requirement for the class using the [Authorize] attribute. For authentication, I use the ASP.NET Membership Provider and set that my Web.Config uses "Forms" authentication. This is where I am stuck:

Everything works fine until I finish testing the API and I want to protect the controller with the [Authorize] attribute so that I can start testing the authentication against users of my membership provider. So I run Fiddler and make the same call, adding the Authorization: Basic attribute along with the username: password from my membership provider as follows:

enter image description here

The answer I get is unauthorized 401, and in the "Auth" section I get "No WWW-Authenticate Header." Then I understand that the API is looking for the SHA1 encoded key. Therefore, I start the SHA1 generator from the search and get a hash for my username: password and update my request header as follows:

enter image description here

This also does not work, and I get the same results. Also, I obviously need some kind of โ€œshared secret keyโ€ to use with the server to decode my username / password.

So my questions are:

  • How to get this key from the server (or in this case Virtual IIS is running VS 2012).
  • How to do this to make authenticated calls in Fiddler using usernames / passwords from an ASP.NET membership provider.
  • How will I use this in my client application to make the same calls (C # WPF App).
  • Is this best combined with SSL on my HTTP calls? If not, then what?

Thanks in advance!

+43
asp.net-mvc asp.net-web-api forms-authentication fiddler asp.net-membership
Jul 18 2018-12-18T00:
source share
1 answer

You can use basic authentication with SSL. On the server side, we could write a custom delegation handler that will verify credentials by requesting a registered memebership provider, and if valid, get the roles and set the current principal:

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); } } 

Then we register this handler in Application_Start :

 GlobalConfiguration.Configuration.MessageHandlers.Add( new BasicAuthenticationMessageHandler() ); 

Now we can have an Api controller, which will be decorated with the [Authorize] attribute to ensure that only authenticated users can access their actions:

 [Authorize] public class ValuesController : ApiController { public string Get() { return string.Format("Hello {0}", User.Identity.Name); } } 

Ok, now let's look at a client example:

 using System; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Text; class Program { static void Main() { // since for testing purposes I am using IIS Express // with an invalid SSL certificate I need to desactivate // the check for this certificate. ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; using (var client = new HttpClient()) { var buffer = Encoding.ASCII.GetBytes("john:secret"); var authHeader = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(buffer)); client.DefaultRequestHeaders.Authorization = authHeader; var task = client.GetAsync("https://localhost:44300/api/values"); if (task.Result.StatusCode == HttpStatusCode.Unauthorized) { Console.WriteLine("wrong credentials"); } else { task.Result.EnsureSuccessStatusCode(); Console.WriteLine(task.Result.Content.ReadAsAsync<string>().Result); } } } } 
+67
Jul 18 '12 at 7:29
source share
โ€” -



All Articles