122

I am looking to authenticate a user from a client application while using the ASP.NET Web API. I have watched all the videos on the site and also read this forum post.

Putting the [Authorize] attribute correctly returns a 401 Unauthorized status. However, I need to know how to allow a user to log in to the API.

I want to provide user credentials from an Android application to the API, get the user logged in, and then have all subsequent API calls pre-authenticated.

2
  • Hi Mujtaba. Were you able to implement this? Commented Aug 7, 2013 at 21:39
  • First use CORS to prevent unwanted hit from others domain. Then send a valid Forms Authentication cookie along with the request and finally authorize request by token. This combination always make your web api secure and optimized. Commented Jan 27, 2019 at 4:27

4 Answers 4

137

allow a user to log in to the API

You need to send a valid Forms Authentication cookie along with the request. This cookie is usually sent by the server when authenticating (LogOn action) by calling the [FormsAuthentication.SetAuthCookie method (see MSDN).

So the client needs to perform 2 steps:

  1. Send an HTTP request to a LogOn action by sending the username and password. In turns this action will call the FormsAuthentication.SetAuthCookie method (in case the credentials are valid) which in turn will set the forms authentication cookie in the response.
  2. Send an HTTP request to an [Authorize] protected action by sending along the forms authentication cookie it retrieved in the first request.

Let's take an example. Suppose that you have 2 API controllers defined in your web application:

The first one responsible for handling authentication:

public class AccountController : ApiController
{
    public bool Post(LogOnModel model)
    {
        if (model.Username == "john" && model.Password == "secret")
        {
            FormsAuthentication.SetAuthCookie(model.Username, false);
            return true;
        }

        return false;
    }
}

and the second one containing protected actions that only authorized users can see:

[Authorize]
public class UsersController : ApiController
{
    public string Get()
    {
        return "This is a top secret material that only authorized users can see";
    }
}

Now we could write a client application consuming this API. Here's a trivial console application example (make sure you have installed the Microsoft.AspNet.WebApi.Client and Microsoft.Net.Http NuGet packages):

using System;
using System.Net.Http;
using System.Threading;

class Program
{
    static void Main()
    {
        using (var httpClient = new HttpClient())
        {
            var response = httpClient.PostAsJsonAsync(
                "http://localhost:26845/api/account", 
                new { username = "john", password = "secret" }, 
                CancellationToken.None
            ).Result;
            response.EnsureSuccessStatusCode();

            bool success = response.Content.ReadAsAsync<bool>().Result;
            if (success)
            {
                var secret = httpClient.GetStringAsync("http://localhost:26845/api/users");
                Console.WriteLine(secret.Result);
            }
            else
            {
                Console.WriteLine("Sorry you provided wrong credentials");
            }
        }
    }
}

And here's how the 2 HTTP requests look on the wire:

Authentication request:

POST /api/account HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: localhost:26845
Content-Length: 39
Connection: Keep-Alive

{"username":"john","password":"secret"}

Authentication response:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 13 Jun 2012 13:24:41 GMT
X-AspNet-Version: 4.0.30319
Set-Cookie: .ASPXAUTH=REMOVED FOR BREVITY; path=/; HttpOnly
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/json; charset=utf-8
Content-Length: 4
Connection: Close

true

Request for protected data:

GET /api/users HTTP/1.1
Host: localhost:26845
Cookie: .ASPXAUTH=REMOVED FOR BREVITY

Response for protected data:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 13 Jun 2012 13:24:41 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/json; charset=utf-8
Content-Length: 66
Connection: Close

"This is a top secret material that only authorized users can see"
Sign up to request clarification or add additional context in comments.

13 Comments

Is it going to maintain a session for Android application?
Got the point but can you please post a sample code for the second point. Thanks for your answer.
Writing an Android HTTP client is a subject for another question. It is unrelated to ASP.NET MVC and ASP.NET MVC Web API which is what your question was about. I would recommend you start a new thread explicitly tagging with Java and Android in which you ask about how to write an HTTP client which sends requests using cookies.
Actually in literature of MVC4 WebApi they have written that WebAPI is target for third party clients specially mobile clients (and ofcourse it is). Lets say we have a desktop application client, can you post a simple code snippet please. Thanks
Also see this question (and answer) about using HTTP basic authentication: stackoverflow.com/questions/10987455/…
|
12

I take android as example.

public abstract class HttpHelper {

private final static String TAG = "HttpHelper";
private final static String API_URL = "http://your.url/api/";

private static CookieStore sCookieStore;

public static String invokePost(String action, List<NameValuePair> params) {
    try {
        String url = API_URL + action + "/";
        Log.d(TAG, "url is" + url);
        HttpPost httpPost = new HttpPost(url);
        if (params != null && params.size() > 0) {
            HttpEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
            httpPost.setEntity(entity);
        }
        return invoke(httpPost);
    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }

    return null;
}

public static String invokePost(String action) {
    return invokePost(action, null);
}

public static String invokeGet(String action, List<NameValuePair> params) {
    try {
        StringBuilder sb = new StringBuilder(API_URL);
        sb.append(action);
        if (params != null) {
            for (NameValuePair param : params) {
                sb.append("?");
                sb.append(param.getName());
                sb.append("=");
                sb.append(param.getValue());
            }
        }
        Log.d(TAG, "url is" + sb.toString());
        HttpGet httpGet = new HttpGet(sb.toString());
        return invoke(httpGet);
    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }

    return null;
}

public static String invokeGet(String action) {
    return invokeGet(action, null);
}

private static String invoke(HttpUriRequest request)
        throws ClientProtocolException, IOException {
    String result = null;
    DefaultHttpClient httpClient = new DefaultHttpClient();

    // restore cookie
    if (sCookieStore != null) {
        httpClient.setCookieStore(sCookieStore);
    }

    HttpResponse response = httpClient.execute(request);

    StringBuilder builder = new StringBuilder();
    BufferedReader reader = new BufferedReader(new InputStreamReader(
            response.getEntity().getContent()));
    for (String s = reader.readLine(); s != null; s = reader.readLine()) {
        builder.append(s);
    }
    result = builder.toString();
    Log.d(TAG, "result is ( " + result + " )");

    // store cookie
    sCookieStore = ((AbstractHttpClient) httpClient).getCookieStore();
    return result;
}

Attention please: i.localhost cannot be used. Android device look localhost as itself host. ii.If deploy the web API in IIS, the Form authentication must be opened.

Comments

0

Use this code and access database

[HttpPost]
[Route("login")]
public IHttpActionResult Login(LoginRequest request)
{
       CheckModelState();
       ApiResponse<LoginApiResponse> response = new ApiResponse<LoginApiResponse>();
       LoginResponse user;
       var count = 0;
       RoleName roleName = new RoleName();
       using (var authManager = InspectorBusinessFacade.GetAuthManagerInstance())
       {
           user = authManager.Authenticate(request); 
       } reponse(ok) 
}

Comments

0

Select Single user Authentication - this will create database of Authentication to create users in App_Data>*.mdf sql file The regsitered users are stored in this table dbo.AspNetUsers --> Please note that password is stored in hash format here in this table using this it will be useful to login in the website that is attributed with [Autorize] --> it will call the auto created page function ==> /api/account/register

The registration page script can be used as below $(document).ready(function () {

        $('#lnkClose').click(function () {
             $('#divErrorText').hide('fade');
        });

        $('#btnRegister').click(function () {
            $.ajax({
                url: '/api/account/register',
                method: 'POST',
                data: {
                    Email: $('#txtEmail').val(),
                    Password: $('#txtPassword').val(),
                    ConfirmPassword: $('#txtConfirmPassword').val()

                },
                success: function () {
                    $('#successModel').modal('show');
                },
                error: function (jqXHR) {
                    $('#divErrorText').text(jqXHR.responseText);
                    $('#divError').show('fade');
                    $('#divErrorText').show('fade');
                }
            })



        });
    });

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.