In Asp Net Core, Do I have to put the Attribute of [Authorize] for both Get and Post Method? - asp.net-core

In the controller, normally we have a Get and a Post methods
for example:
[HttpGet]
[Authorize(Policy = "AdminMs")]
public async Task<IActionResult> MSCreate()
{
}
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Policy = "AdminMs")]
public async Task<IActionResult> MSCreate(empolyee)
{
}
Do I have to set the Authorize Attribute for both methods or only for HttpGet?

If you need only authorized access to any of the end points, you have to use [Authorize] on whichever method that corresponds to that endpoint. Having it on one method does not mean that it will restrict the other method even if they have similar method names.

Related

How can I add links to other controller methods in generated OpenAPI specs using attributes in ASP.NET Core?

I am using SwaggerGen to generate an OpenAPI spec for our API, and would like to add links between certain endpoints.
OpenAPI 3.0 Links
Is there a way to add an attribute to the controller method that links to another controller method?
For example, if I currently have something like
[HttpPost]
[Route("~/users")]
[ProducesResponseType(typeof(ResponseObject<UserId>), StatusCodes.Status200OK)]
public async Task<IActionResult> CreateUser(...)
{
// Create user
}
[HttpGet]
[Route("~/users/{userId}")]
[ProducesResponseType(typeof(ResponseObject<User>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetUser(...)
{
// Get newly created user
}
Could I somehow link them like
[HttpPost]
[Route("~/users")]
[ProducesResponseType(typeof(ResponseObject<UserId>), StatusCodes.Status200OK)]
[Link(nameof(GetUser), "UserId")]
public async Task<IActionResult> CreateUser(...)
{
// Create user
}
[HttpGet]
[Route("~/users/{userId}")]
[ProducesResponseType(typeof(ResponseObject<User>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetUser(...)
{
// Get newly created user
}
to generate the "links" field as shown in the OpenAPI 3.0 spec linked above?

Evaluate AuthorizeAttribute in action

One can authorize an action by using the [Authorize] attribute. But I want to only perform authorization on the action in specific conditions, so I cannot use this attribute. I don't think I am able to use IAuthorizationService.AuthorizeAsync as I don't have any policy names. Here's my service configuration in Startup.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration, "AzureAdB2C");
So my question is, how can I move the [Authorize] evaluation into the action code?
The AuthorizeAttribute will be converted (maybe with others) into an AuthorizeFilter and this filter will be executed with some code that is not equivalent to the simple IAuthorizationService.AuthorizeAsync. But if you want to use that anyway, we can get the default policy (which is used by [Authorize] without any policy specified) by using the IAuthorizationPolicyProvider.GetDefaultPolicyAsync. After that you can authorize the User to get an AuthorizationResult. It is succeeded if the property Succeeded is true. Otherwise, you can have the detailed failure in the property Failure (of type AuthorizationFailure). Here's the code:
public class TestController {
readonly IAuthorizationService _authorizationService;
readonly IAuthorizationPolicyProvider _authorizationPolicyProvider;
public TestController(IAuthorizationService authorizationService,
IAuthorizationPolicyProvider authorizationPolicyProvider){
_authorizationService = authorizationService;
_authorizationPolicyProvider = authorizationPolicyProvider;
}
public async Task<IActionResult> SomeAction(){
var defaultPolicy = await _authorizationPolicyProvider.GetDefaultPolicyAsync();
var authResult = await _authorizationService.AuthorizeAsync(User, defaultPolicy);
if(authResult.Succeeded){
//do something ...
}
}
}

How to remove value from route int .net core

I'm writing .net core mvc app. I have two methods
[HttpGet("{action}/{userId}")]
public async Task<IActionResult> ChangeUser(string userId)
{
var user = await _dbContext.Users.Where(x => x.Id == userId).FirstOrDefaultAsync();
...
return View(new ChangeUserVM());
}
[HttpPost("{action}/{userId}")]
public async Task<IActionResult> ChangeUser(ChangeUserVM user)
{
...
}
I need routing in the HttpGet method to get into the first method. But then i want to get from the html to the second method and i have to use routing again otherwise i get 405. How i can get rid of routing in the second method?
I can’t verify my suggestion right now, but over second method, try to remove from HttpPost attribute “userId”.
[HttpPost(“action”)]
public async Task<IActionResult> ChangeUser(ChangeUserVM user)

Apply [FromBody] attribute to all controller actions in .net core

Having a simple .NET Core API with your models posted as JSON in request body, how to have [FromBody] attribute applied to all controller methods?
[Route("api/simple")]
public class SimpleController : ControllerBase
{
[HttpPost]
public IActionResult Post([FromBody] MyRequest request)
{
return Ok();
}
}
If I remove the [FromBody] attribute, all model properties will be null.
If you POST your model inside the body with Content-Type: application/json then you have to tell the ModelBinder to read the model from body by applying [FromBody] attribute.
But adding [FromBody] to all of your API actions makes you feel bad.
Just apply the [ApiController] to your controller and then you don't need [FromBody] anymore.
Microsoft Doc definition of [ApiController]
Indicates that a type and all derived types are used to serve HTTP API responses.
Controllers decorated with this attribute are configured with features and behavior targeted at improving the developer experience for building APIs.
So this works without [FromBody] in ASP.NET Core 2.1 and above
[Route("api/simple")]
[ApiController]
public class SimpleController : ControllerBase
{
[HttpPost]
public IActionResult Post(OrderRequest request)
{
return Ok();
}
}

How to call controller method from async Task<IActionResult> method?

I want to call normal action method from my another method,but debugger does not go to that method.
[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
//Code Logic
return RedirectToAction("SecondMethod");
}
public IActionResult SecondMethod()
{
return View();
}
If you only want to redirect, this code will work.
[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
//Code Logic
return RedirectToAction("SecondMethod","YourControllerName");
}
public IActionResult SecondMethod()
{
return View();
}
Nothing special here, you just want to redirect to SecondMethod once the UploadFile is finished.
But you can't invoke it as a method since it uses IActionResult what IActionResult does is it defines a contract that represents the result of an action method.
RedirectToAction results in a redirect being sent to the client's browser, which then has to request the URI being redirected to.
So calling return RedirectToAction("SecondMethod"); will not invoke SecondMethod in and of itself, it depends on whether the client follows the redirect.