How to add a server side check that api is only called by tenant admin - authorization

My requirement is to add a check here that this API route/end point is only called by tenant admin.
AppController.cs
[Route("api/[controller]")]
[Authorize(Policy = "App.ReadWrite")]
[ApiController]
[Produces("application/json")]
public sealed class AppController : ControllerBase
{
[Route("apps/search")]
[HttpGet]
public async Task<IActionResult> SearchAppForUserAsync([FromQuery] string searchString, CancellationToken cancellationToken)
{
var user = this.GetUser();
var result = await this.appRepository.SearchAppForUserAsync(user, searchString, cancellationToken).ConfigureAwait(false);
return this.Ok(result);
}
}

Related

Blazor Webassembly - Putting/Posting to API Controller

I have a controller - roughed out below. And then you see the call I make from the client.
When I make the client call to post, it gives me a Bad Request error.
[ApiController]
[Route("[controller]")]
public class MainController : ControllerBase
{
[HttpPost]
public IActionResult Post(Policies policy)
{
myModelContext.Policies.Update(policy);
myModelContext.SaveChanges();
return Ok();
}
}
//client code
protected async void OnUpdating(GridCommandEventArgs editRow)
{
HttpResponseMessage httpResponseMessage = await httpClient.PostAsJsonAsync($"Main", (Policies)editRow.Item);
if (!httpResponseMessage.IsSuccessStatusCode)
{
toastService.ShowError(httpResponseMessage.ReasonPhrase);
}
}
I've tried everything

When send Parameter pagenumber to web api by post man action not working or recognize?

I work on .net core 6 web api I face issue when
send paramter pagenumber on url by post man
action not catched by break point debug .
so what is issue and How to solve It ?
i try with url
https://localhost:7235/api/items/pageNumber=1
[HttpGet("{pageNumber}")]
public async Task<IActionResult> GetAll(int pageNumber)
{
}
it return error 200 bad Request .
but i try with url below
https://localhost:7235/api/items/
[HttpGet]
[Route("")]
public async Task<IActionResult> GetAll(int pageNumber)
{
}
it working hit controller success and return data success fromitems controller action get all .
so What is issue please and How to solve it ?
Updated post not working
[HttpGet("{pageNumber}")]
public async Task<IActionResult> GetAll(int pageNumber)
{
}
for this action you need to use this url:
https://localhost:7235/api/items/1
not working and it give me error 500 internal server error
all controller items
using DomainModel.Entities;
using DomainModel.Pagination;
using DomainModel.ViewModel;
using k8s.Models;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Service.Contract;
using Service.Features.CustomerFeatures.Commands;
using Service.Features.CustomerFeatures.Queries;
namespace WebApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ItemsController : Controller
{
private readonly IitemService _iitem;
private readonly IPageHelper<ItemsViewModel> _pageHelper;
public ItemsController(IitemService iitem, IPageHelper<ItemsViewModel> pageHelper)
{
_iitem = iitem;
_pageHelper = pageHelper;
}
[HttpPost]
public async Task<IActionResult> Create(Items item)
{
await _iitem.AddAsync(item);
return Ok();
}
[HttpGet("{pageNumber}")]
public async Task<IActionResult> GetAll(int pageNumber)
{
var allitems = _iitem.GetAllItems();
var result = _pageHelper.GetPage(allitems.AsQueryable(), pageNumber);
var itemsdata = new ItemsPageViewModel
{
items = result.Items,
Pager = result.Pager
};
return Ok(itemsdata);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var details = await _iitem.GetByIdAsync(id);
return Ok(details);
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
await _iitem.DeleteAsync(id);
return Ok();
}
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, Items item)
{
if (id != item.Id)
{
return BadRequest();
}
await _iitem.UpdateAsync(id, item);
return Ok();
}
}
}
The error you are actually getting is
AmbiguousMatchException: The request matched multiple endpoints.
This is because you have two actions that have the same route:
// for this action you need to use this url:
// https://localhost:7235/api/items/1
[HttpGet("{pageNumber}")]
public async Task<IActionResult> GetAll(int pageNumber)
{
var allitems = _iitem.GetAllItems();
var result = _pageHelper.GetPage(allitems.AsQueryable(), pageNumber);
var itemsdata = new ItemsPageViewModel
{
items = result.Items,
Pager = result.Pager
};
return Ok(itemsdata);
}
// for this action you ALSO need to use this url:
// https://localhost:7235/api/items/1
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var details = await _iitem.GetByIdAsync(id);
return Ok(details);
}
Both actions are HttpGet and both use the same route:
https://localhost:7235/api/items/x
you need to change the route for one of them.
Routing to controller actions in ASP.NET Core

ASP.NET Core Dependency Injection: NullReferenceException trying to access concrete class member defined in its interface

this is getting weird as I've done it several times with no issues.
I'm using ASP.NET Core 3.1 for the record.
The problem is that I register a concrete type and its relative interface in the ConfigureServices Startup method:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("MyDatabase")
));
ProfileManager.RegisterMappingService(services);
services.AddScoped<IUserWorkerService, UserWorkerService>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddControllers();
I inject that dependency in the controller:
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
private readonly IUserWorkerService userWorkerService;
public UsersController(IUserWorkerService userWorkerService)
{
this.userWorkerService = userWorkerService ?? throw new ArgumentNullException(nameof(userWorkerService));
}
[AllowAnonymous]
[HttpPost("authenticate")]
public IActionResult Authenticate(string userName, string password)
{
var user = this.userWorkerService.Authenticate(userName.Trim(), password.Trim());
if (user == null)
return Unauthorized();
return Ok(System.Text.Json.JsonSerializer.Serialize(user));
}
}
This is the interface:
public interface IUserWorkerService
{
public UserDto Authenticate(string userName, string password);
}
And this is the concrete class:
public class UserWorkerService : IUserWorkerService
{
private readonly MyDbContext dbContext;
private readonly IMapper mapper;
public UserWorkerService(MyDbContext dbContext, IMapper mapper)
{
this.dbContext = dbContext;
this.mapper = mapper;
}
public UserDto Authenticate(string userName, string password)
{
*blah blah*
}
}
And when I make the POST request, I land correctly on the ActionResult of the controller but the UserWorkerService instance doesn't contain the member defined in its interface, just the injected members IMapper and MyDbContext.
Therefore, when code reaches Authenticate method invoke in the UsersController, debugger throws a NullReferenceException.
What am I missing here?

.Net Core 2.0 Web API controller not working and getting 404

I have something very very strange. I have 2 controllers. UploadController and AccountController. Theye were both working, and now when I try the AccountController it give error 404. ik don't get it.
This is how my AccountController looks like:
namespace CoreAngular.Controllers
{
//[Authorize]
[Produces("application/json")]
[Route("api/account")]
public class AccountController : Controller
{
private IRepository repository;
public AccountController(IDatabaseClient<DocumentClient> client)
: this ( new UserRepository(client))
{
}
public AccountController(IRepository repository)
{
this.repository = repository;
}
[HttpGet]
public async Task<ActionResult> Get(string id)
{
var start = DateTime.Now.TimeOfDay;
if (string.IsNullOrEmpty(id))
{
return BadRequest();
}
var user = await repository.GetAsync(id);
if (user == null)
{
return NotFound();
}
var userDTO = new UserGetDTO()
{
image = Convert.ToBase64String(user.image.image),
id = user.id,
time = DateTime.Now.Subtract(start).Millisecond
};
return Ok(userDTO);
}......
Do I miss something here? I know I comentet out the [Authorize], but i just wanted to try to connect.
You should specify route template in HttpGet attribute:
[HttpGet("{id}")]
public async Task<ActionResult> Get(string id)
{
// ...
}

add claims to windows identity

I am trying to assign roles as claims for Windows Authentication for Asp.net Core Webapi project. Below is my transform by adding a role claim current identity.
public class ClaimsTransformer : IClaimsTransformer
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
{
//add new claim
var ci = (ClaimsIdentity) context.Principal.Identity;
var c = new Claim(ClaimTypes.Role, "admin");
ci.AddClaim(c);
return Task.FromResult(context.Principal);
}
}
And this middleware is added to Startup.Configure:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(LogLevel.Debug);
loggerFactory.AddDebug();
app.UseClaimsTransformation(o => new ClaimsTransformer().TransformAsync(o));
app.UseStaticFiles();
app.UseMvc();
}
However role admin is not authorized in this method (403-Forbidden).
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values/5
[HttpGet("{id}")]
[Authorize(Roles = "admin")]
public string Get(int id)
{
return "value";
}
}
It is working properly if [Authorize] is used. Any missing?
Unfortunately User.IsInRole method doesn't work with ClaimsTransformer(if you add role with ClaimsTransformer, IsInRole will be false) so you can't use [Authorize(Roles = "")] with ClaimsTransformer. In this case you can use Claims Based Authorization to handle authotorization.
So add below code to ConfigureServices and use Authorize attribute:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddAuthorization(options =>
{
options.AddPolicy("admin", policy => policy.RequireClaim(ClaimTypes.Role, "admin"));
});
//...
}
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values/5
[HttpGet("{id}")]
[Authorize(Policy = "admin")]
public string Get(int id)
{
return "value";
}
}