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

1

14

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

    }
Radium answered 6/1, 2018 at 2:56 Comment(0)
A
37

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.

Amend answered 7/1, 2018 at 17:34 Comment(5)
Thanks Todd. That is what I was looking for.Radium
exactly what I wantedHen
Good answer. Thanks a lot.Sankaran
I tried the same in my application but I'm unable to read the Authentication header from the request using Request.Headers.TryGetValue("Authorization", out StringValues authToken). Is it necessary to do some initialization of the app or of the services?Razzia
Is it a considered a bad practice to fetch and authorize header in the controller API sitting in a DMZ?Sewer

© 2022 - 2024 — McMap. All rights reserved.