Home > database >  How to make HTTP requests to an API controller with AuthorizedAttribute?
How to make HTTP requests to an API controller with AuthorizedAttribute?

Time:04-24

Short story

I have a Web API. I want to prevent unauthorized requests so I added [Authorize(Roles = "admin")] attribute to my ApiController.

How can I make requests to my own API from different apps in C# (from desktop app for example)?

Long story

I have a simple web app solution which contains 2 projects.

In project1 users can sign in via username and password and do stuff. Code for signing users is as shown here:

if (ModelState.IsValid)
{
    var user = await _userManager.GetFromModelAsync(model); // just get user from DB
    var claims = new List<Claim>
    {
        new Claim(ClaimsIdentity.DefaultNameClaimType, user.Code),
        new Claim(ClaimsIdentity.DefaultRoleClaimType, user.Role?.Name)
    };
        
    var id = new ClaimsIdentity(
        claims, "ApplicationCookie",
        ClaimsIdentity.DefaultNameClaimType,
        ClaimsIdentity.DefaultRoleClaimType);

    await _httpContextAccessor.HttpContext.SignInAsync(
        CookieAuthenticationDefaults.AuthenticationScheme,
        new ClaimsPrincipal(id)); // I use httpContextAccessor cause I have this code not in controller
}

With this authentication, the user can easily access to any controller with attribute [Authorize(Roles = "user")].

In Project2, I have Admin Web API which can change stuff that users did. I want to call this API from a desktop C# app and I also want that API to have an authorization requirement ([Authorize(Roles = "admin")] in my case).

For example, it looks something like this:

[Authorize(Roles = "user")]
public class AdminApiController : Controller
{
    public async Task<IActionResult> Index()
    {
        return Ok("Ok");
    }
}

And the question is: with such an authentication mechanism how should I make HTTP requests to such an API with HttpClient? The only way I know is to use WebClient and emulate authorization with UploadValues to special authorization form.

P.S. I tried setting HTTP Authorization header but it didn't work. Maybe the point is to use separate authentication mechanism for users and admins?

Any help on this is highly appreciated.

CodePudding user response:

I think you can follow the authentication mechanism JWT(JSON web Token) instead of cookies as the desktop app is a different environment that not use a web browser

User authentication scenario

  1. the desktop app login to web API by userName and password param
  2. if passed generate a token for the authenticated user and back it in response
  3. when desktop app hit API action decorated by authorizing role via token

For a full example check this Url

Here is an example code in desktop app:

using Newtonsoft.Json;
...

var client = new HttpClient();

var httpRequestMessage = new HttpRequestMessage
    {
        Method = HttpMethod.Post,
        RequestUri = new Uri("https://api.domain.com/action"),
        Headers = { 
            { HttpRequestHeader.Authorization.ToString(), "Bearer xxxxxxxxxxxxxxxxxxx" },
            { HttpRequestHeader.Accept.ToString(), "application/json" },
            { "X-Version", "1" }
        },
        Content = new StringContent(JsonConvert.SerializeObject(svm))
    };

var response = client.SendAsync(httpRequestMessage).Result;
  • Related