Home > database >  ASP.NET Core Web API - How to authorize my Web API Request with Basic Auth
ASP.NET Core Web API - How to authorize my Web API Request with Basic Auth

Time:10-09

In ASP.NET Core-6 Web API, this Basic Auth code to be used as an header for my POST, PUT and Get Requests:

--header 'Authorization: Basic GGATEIIIFFFF12234JJKKKKKFFFFFFFFFFFFFF'

In my appsettings.Json, I have the credential as shown below:

  "BasicCredentials": {
    "username": "Akwetey",
    "password": "#12345677**87" //Basic Auth
  },

Then I have this Get Request:

public IEnumerable<Employee> GetEmployees()
{
    List<Employee> employeelist = new List<Employee>();
    using (con = new SqlConnection(connection))
    {
        con.Open();
        command = new SqlCommand("sp_employees", con);
        command.CommandType = CommandType.StoredProcedure;
        dataReader = command.ExecuteReader();
        while (dataReader.Read())
        {
            Employee employee = new Employee();
            employee.EmployeeId = Convert.ToInt32(dataReader["EmployeeId"]);
            employee.Firstname = dataReader["Firstname"].ToString();
            employee.Lastname = dataReader["Lastname"].ToString();
            employee.Email = dataReader["Email"].ToString();
      employee.EmploymentDate = Convert.ToDateTime(dataReader["EmploymentDate"].ToString());

            employeelist.Add(employee);
        }
        con.Close();
    }
    return employeelist;
}

How do I authorise the Get Get Request code above using the Basic Auth Credentials as the header?

Thanks

CodePudding user response:

This is the BasicAuthenticationHandler implementation from dotnetthoughts modified to read the credentials from appsettings.json using IConfiguration:

public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    private readonly IConfiguration _configuration;

    public BasicAuthenticationHandler(
        IOptionsMonitor<AuthenticationSchemeOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock,
        IConfiguration configuration) : base(options, logger, encoder, clock)
    {
        _configuration = configuration;
    }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        var authHeader = Request.Headers["Authorization"].ToString();

        if (authHeader != null && authHeader.StartsWith("basic", StringComparison.OrdinalIgnoreCase))
        {
            var token = authHeader.Substring("Basic ".Length).Trim();
            Console.WriteLine(token);
            var credentialstring = Encoding.UTF8.GetString(Convert.FromBase64String(token));
            var credentials = credentialstring.Split(':');

            var username = _configuration["BasicCredentials:username"];
            var password = _configuration["BasicCredentials:password"];

            if (credentials[0] == username && credentials[1] == password)
            {
                var claims = new[] { new Claim("name", credentials[0]), new Claim(ClaimTypes.Role, "Admin") };
                var identity = new ClaimsIdentity(claims, "Basic");
                var claimsPrincipal = new ClaimsPrincipal(identity);

                return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, Scheme.Name)));
            }

            Response.StatusCode = 401;
            Response.Headers.Add("WWW-Authenticate", "Basic realm=\"dotnetthoughts.net\"");

            return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
        }
        else
        {
            Response.StatusCode = 401;
            Response.Headers.Add("WWW-Authenticate", "Basic realm=\"dotnetthoughts.net\"");

            return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
        }
    }
}

CodePudding user response:

You would need to add something along these lines

builder.Services.AddAuthentication()
    .AddScheme<MyAuthenticationOptions, MyAuthenticationHandler>(MyAuthenticationSchemeName, options => {});

Where:

public class MyAuthenticationOptions : AuthenticationSchemeOptions
    {}

and

public class MyAuthenticationHandler : AuthenticationHandler<MyAuthenticationOptions>
    {

        private IConfiguration Configuration;
        public MyAuthenticationHandler(
            IOptionsMonitor<MyAuthenticationOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock,
            IConfiguration configuration
        ) : base(options, logger, encoder, clock)
        {
            Configuration = configuration;
        }

        protected async override Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            // Get the header
            string authHeader = Request.Headers[HeaderNames.Authorization];
            // Parse config this way
            var pwd = Configuration.GetValue<string>("BasicCredentials:password")
            // Check if the header is valid comparing to your config
            // Create here your claims principal
            ClaimsPrincipal principal;
            //...//
            var ticket = new AuthenticationTicket(principal, Scheme.Name);
            return AuthenticateResult.Success(ticket);

            // Or otherwise
            return AuthenticateResult.Fail("Invalid secret.");
        }
    }

Then finally, you can have an authed controller like this

[Authorize]
[HttpGet("employees")]
public IEnumerable<Employee> GetEmployees()
{
    List<Employee> employeelist = new List<Employee>();
    using (con = new SqlConnection(connection))
    {
        con.Open();
        command = new SqlCommand("sp_employees", con);
        command.CommandType = CommandType.StoredProcedure;
        dataReader = command.ExecuteReader();
        while (dataReader.Read())
        {
            Employee employee = new Employee();
            employee.EmployeeId = Convert.ToInt32(dataReader["EmployeeId"]);
            employee.Firstname = dataReader["Firstname"].ToString();
            employee.Lastname = dataReader["Lastname"].ToString();
            employee.Email = dataReader["Email"].ToString();
      employee.EmploymentDate = Convert.ToDateTime(dataReader["EmploymentDate"].ToString());

            employeelist.Add(employee);
        }
        con.Close();
    }
    return employeelist;
}
  • Related