Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the authentication header from a request sent to an ASP.NET core 2.0 API controller action

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);

    }
like image 556
EiEiGuy Avatar asked Jan 06 '18 02:01

EiEiGuy


People also ask

How do you pass basic authentication in header .NET Core?

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.

Is Authorization header automatically sent?

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.

Where is Authorization header in URL?

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.


1 Answers

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.

like image 111
Todd Menier Avatar answered Sep 24 '22 02:09

Todd Menier