Benjamin
Benjamin

Reputation: 3826

.Net Core API returns 405:Method not allowed when having Authorize attribute

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.

Below is the postman: enter image description here

enter image description here

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

Answers (1)

scharnyw
scharnyw

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

Related Questions