I have a .NET 6.0 web application which is using Cookie based authentication for users.
Today I wanted to add an API controller with a really simple BASIC AUTHENTICATION mechanism.
Here is my controller:
public class DemaController : Controller
{
[HttpGet("test")]
[BasicAuthentication(username: "test", password: "abc")]
public bool Test()
{
return true;
}
}
and here is my super simple Basic Authentication attribute:
public class BasicAuthenticationAttribute : Attribute, IAuthorizationFilter
{
private readonly string _username;
private readonly string _password;
public BasicAuthenticationAttribute(string username, string password)
{
_username = username;
_password = password;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
try
{
var authorizationHeader = context.HttpContext.Request.Headers["Authorization"];
(string username, string password) = this.GetUsernameAndPassword(authorizationHeader: authorizationHeader);
if (username != null && password != null)
{
if (username == _username && password == _password)
return; // Grant access
}
}
catch (FormatException)
{
}
context.Result = new UnauthorizedResult();
}
static System.Text.Encoding ISO_8859_1_ENCODING = System.Text.Encoding.GetEncoding("ISO-8859-1");
private (string, string) GetUsernameAndPassword(string authorizationHeader)
{
if (authorizationHeader == null || !authorizationHeader.Contains("Basic "))
return (null, null);
string encodedUsernamePassword = authorizationHeader.Substring("Basic ".Length).Trim();
string usernamePassword = ISO_8859_1_ENCODING.GetString(Convert.FromBase64String(encodedUsernamePassword));
string username = usernamePassword.Split(':')[0];
string password = usernamePassword.Split(':')[1];
return (username, password);
}
}
When I run the application on my local machine (Visual Studio 2022 IIS Express) and use Postman to access the Api everything works just fine. The response is "true" as expected.
This is how I feed Postman:
- GET https://localhost:44360/test
- Authorization type: Basic Auth
- Username: test
- Password: abc
So my custom BasicAuthenticationAttribute seems to work. I can set break points (which are being hit) and any change to the Postman credentials returns an Http-401 error.
So far so good.
Now I published my application to my production server (IIS). In Postman, I replaced "localhost:44360" by my real production domain.
My problem: Sending the request to my production server returns a 401 (and a whole ASP.NET Core default error page).
I went a little further and setup the MS Visual Studio Remote Debugger on my server. Then I set a breakpoint inside my custom BasicAuthenticationAttribute. The breakpoint is never hit. In other words: the 401 does not come from inside my attribute. It seems like my BasicAuthenticationAttribute is not touched at all on my server (but it is touched for sure on my development machine as stated before).
Let me guess: I need to add or change something in my Startup.cs?
For what it's worth: I am aware that Basic Authentication is not really safe. But for my needs it's totally fine. In any case I want to get around complex Policies, OAuth etc.
Does anybody have an idea what I need to do?
CodePudding user response:
Now I published my application to my production server (IIS). In Postman, I replaced "localhost:44360" by my real production domain.
My problem: Sending the request to my production server returns a 401 (and a whole ASP.NET Core default error page).
Try to check if IIS had Basic authentication or Windows authentication.If so,disable them in IIS and try again.