10

Trying to secure my ASP.NET Web API-2 using Basic Authentication but it is always ending up with error:

401/Unauthorized
Authorization has been denied for this request.

Below are my controller and ajax request code snippet alongside the request and response headers.

BasicAuthenticationHandler.SendAsync always runs successfully up-till:

return base.SendAsync(request, cancellationToken);

Q: Then WHY it ends up as 401/unauthorized ?

If I remove [Authorize] from the controller action then it works but without any security.

Note: Because this is a cross-domain request so I have enabled CORS on server side.

My Authentication Handler

protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
    var principal = Thread.CurrentPrincipal;
    if (principal.Identity.IsAuthenticated)
    {
        return base.SendAsync(request, cancellationToken);
    }

    var encryptedTicket = ExtractToken(request.Headers.Authorization); // simply returns a string
    if (encryptedTicket != null)
    {
        var ticket = FormsAuthentication.Decrypt(encryptedTicket);
        var serializer = new JavaScriptSerializer();
        var user = serializer.Deserialize<UserInfoModel>(ticket.UserData);

        if (user != null)
        {
            var identity = new GenericIdentity(user.UserName, "Basic");
            Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[0]);
        }
    }

    // Code reaches here always successfully but after this line errors Unauthorized
    return base.SendAsync(request, cancellationToken);
}

My Controller

public class ProductController : ApiController
{

Product[] products = new Product[] 
{ 
    new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 } 
};

[Authorize]
[Route("test/products")]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public IEnumerable<Product> GetAllProducts()
{
    return products;
}
}

My AJAX Request

$.ajax({
    type: "GET",
    url: "http://webapi.server.com/test/products",
    crossDomain: true,
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    headers: { Authorization: "Basic 1234567890" },
    success: function (data) {
            alert(data);
    },
    error: function (err) {
            alert(err);
    }
});

Request Headers

Accept  application/json, text/javascript, */*; q=0.01
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Authorization   Basic 1234567890
Content-Type    application/json; charset=utf-8
Host    webapi.server.com
Origin  local-pc
Referer local-pc/Index.aspx
User-Agent  Mozilla/5.0 (Windows NT 6.2; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0

Response Headers

Access-Control-Allow-Orig...    *
Cache-Control   no-cache
Content-Length  61
Content-Type    application/json; charset=utf-8
Date    Thu, 07 Nov 2013 11:48:11 GMT
Expires -1
Pragma  no-cache
Server  Microsoft-IIS/8.0
X-AspNet-Version    4.0.30319
X-Powered-By    ASP.NET

3 Answers 3

13

Don't set the Principal on the Thread.CurrentPrinicipal any more. Use the Principal on the HttpRequestContext.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot Darrel. You have made my day :) (thumbs up). Fixed the problem by changing this to. request.GetRequestContext().Principal = new GenericPrincipal(identity, new string[0]);
Sir, you won the internet. I fought 1 week in order to solve this. Really thanks a lot, really
@Darrel Please can you update your answer to include the code which fix the problem
5

In my case, following Darrels approach, I commented out the below and used his approach. It work great!... saving me hours

// Thread.CurrentPrincipal = PrincipalProvider
//     .CreatePrincipal(parsedCredentials.Username, parsedCredentials.Password);


   request.GetRequestContext().Principal = PrincipalProvider
       .CreatePrincipal(parsedCredentials.Username, parsedCredentials.Password);

Comments

0

Add the following to rest/resource sever and authentication server web.config

You must generate your own keys using http://www.codeproject.com/Articles/221889/How-to-Generate-Machine-Key-in-IIS

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.