I am working on an ASP.NET Core 2.0 RESTful API. I have a scenario where I need to use an HTTPGet method to call an action on my API controller and I need to extract a username and password value that will be used to call another 3rd party API. The username and password are not related to the current logged in user Identity, they are just values I want to send to another API from within my own API, but I do not want to just pass them in a query string.
Can I use basic authentication in the client to add the username and password to the HttpRequestMessage authentication header and then extract that header in my ASP.NET Core 2.0 API controller action?
My client wold have something like this in the code that will call the API
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, relativeUrl);
var byteArray = new UTF8Encoding().GetBytes(string.Format($"username:password"));
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
and, my API controller action would start something like this;
[HttpGet()]
public IActionResult GetUploadedFileList([FromQuery]int pageNumber, [FromQuery]int pageSize)
{
//Extract Authentication header values for username and password
}
Can anyone provide an example of how to get the Authorization header from the HTTPGet request
I realize I can easily do this with an HTTPPost [FromBody] but my use case calls for this method to be an HTTGet.
Thanks in advance for any help.
EDIT 1 - SOLUTION
I was able to get the code below to work, thanks to some hints from this link. Although this seems like a lot of work, so if anyone has a better or cleaner solution, please post your example.
[HttpGet()]
public IActionResult GetUploadedFiles([FromQuery]int pageNumber, [FromQuery]int pageSize)
{
string username = string.Empty;
string password = string.Empty;
if (Request.Headers.TryGetValue("Authorization", out StringValues authToken))
{
string authHeader = authToken.First();
string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));
int seperatorIndex = usernamePassword.IndexOf(':');
username = usernamePassword.Substring(0, seperatorIndex);
password = usernamePassword.Substring(seperatorIndex + 1);
}
else
{
return BadRequest("Missing Authorization Header.");
}
//Build FilesUploadedListRequest
FilesUploadedListRequest filesUploadedListRequest = new FilesUploadedListRequest
{
Username = username,
Password = password,
PageNumber = pageNumber,
PageSize = pageSize
};
//Call GetUploadedFilesList
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = cancellationTokenSource.Token;
Task<FilesUploadedListResponse> FilesUploadedListResponse = _clientService.GetListOfUploadedFilesAsync(filesUploadedListRequest, cancellationToken);
//Return results
if (filesUploadedListResponse.Result.Success)
{
return Ok(filesUploadedListResponse.Result);
}
return StatusCode(filesUploadedListResponse.Result.StatusCode, filesUploadedListResponse.Result.Reason);
}
Basic Authentication works by adding an Authorization header into a HTTP request. The value of the Authorization header must be Basic, followed by a space, followed by the username and password separated by a colon. The username and password are encoded using Base64.
The Authorization header is usually, but not always, sent after the user agent first attempts to request a protected resource without credentials. The server responds with a 401 Unauthorized message that includes at least one WWW-Authenticate header.
It is indeed not possible to pass the username and password via query parameters in standard HTTP auth. Instead, you use a special URL format, like this: http://username:[email protected]/ -- this sends the credentials in the standard HTTP "Authorization" header.
ASP.NET Core supports a [FromHeader]
attribute for action parameters, similar to [FromBody]
and [FromQuery]
. So adding a [FromHeader]string authorization
arg to your action will shave a couple lines off your solution, as well as make the method more testable since you can avoid accessing the Request
object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With