Reputation: 3826
I have a Asp.NET Core MVC application that Controller
always gets invoked from the View
. I am now extending the application by exposing new API endpoint which can be called from outside like Postman.
I am facing an issue of getting 405 - Method Not Allowed
when I put [Authorize]
attribute on top of my controller. without this attribute I can hit the endpoint and the Model gets bounded with the values I provided from postman as expected.
Below is how my controller looks like:
[Authorize]
[Route("api/v1/auth")]
public class ApiAuthController : Controller
{
[HttpPost("changePassword")]
public async Task<IActionResult> ChangePassword([FromBody] ChangePasswordModel model)
{
return null;
}
}
It might worth to mention that, this application is the same application that provides the Bearer token which I later use in the postman.
In my Startup.cs
file I have the following settings related to IdentityServer
and Authorization
:
services
.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddSigningCredential(cert)
.AddAspNetIdentity<IdentityUser>()
.AddAuthentication()
Upvotes: 2
Views: 3062
Reputation: 2666
It appears that you are not authenticated and IdentityServer is trying to redirect you either to login page or access denied page, hence the 302 response. Meanwhile Postman handles 302 in a way that is different from most web browsers, which is following the redirect but preserving the POST method (instead of changing to GET). This leads to a POST request to the login page that finally results in a 405 Method Not Allowed response.
This should not happen in most web browsers as they would change the HTTP method to GET upon receiving a 302 response. But to work around this issue for browsers or user agents that don't do this, you can try:
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToAccessDenied =
options.Events.OnRedirectToLogin = context =>
{
if (context.Request.Method != "GET")
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.FromResult<object>(null);
}
context.Response.Redirect(context.RedirectUri);
return Task.FromResult<object>(null);
};
});
This should send a 401 Unauthorized response instead of a 302 response when the method is not GET.
Upvotes: 7