HttpRequestConfig error using API Key (Basic authentication) in ServiceStack 6.2.1

I need to use an API key (with Basic authentication values) when calling third-party APIs on another (internal) server.

With Net6, ServiceStack/6.1.0 and ServiceStack.HttpClient/6.1.0, the following works:

protected virtual string Send(string relativeUrl, string method, string? body, string? idempotencyKey)
{
    var url = _apiUrl.CombineWith(relativeUrl);
    var response = url.SendStringToUrl(method: method, requestBody: body, requestFilter: req =>
    {
        InitRequest(req, method);
    });

    return response;
}

protected virtual void InitRequest(HttpRequestMessage req, string method)
{
    req.Headers.Add("Accept", MimeTypes.Json);
    req.Headers.Authorization = new AuthenticationHeaderValue("Basic", "c2NcmlAYWxEtY2gtYWRmczpjaGVteUA2MzMz");

    if (method == HttpMethods.Post || method == HttpMethods.Put || method == HttpMethods.Patch)
    {
        req.Headers.Add("ContentType", MimeTypes.Json);
    }
}

In a new project with Net6, ServiceStack/6.2.1 and ServiceStack.HttpClient/6.2.1, I changed the above code, because HttpWebRequest is officially deprecated, to the code below. Unfortunately, it does not work, receiving 403 Forbidden responses.

protected virtual string Send(string relativeUrl, string method, string? body, string? idempotencyKey)
{
    var url = _apiUrl.CombineWith(relativeUrl);

    // This is not working with Net6 HttpClient, so use version below
    // var response = url.SendStringToUrl(method: method, requestBody: body, requestFilter: req =>
    // {
    //     InitRequest(req, method, idempotencyKey);
    // });


    // This works when API does not require Basic authentication
    //var response = url.SendStringToUrl(method: method, requestBody: body, contentType: MimeTypes.Json, accept: MimeTypes.Json);


    // This does not work when API requires Basic authentication
    var response = url.SendStringToUrl(method: method, contentType: MimeTypes.Json, accept: MimeTypes.Json,
        requestBody: body, requestFilter: req =>
            req.AddApiKeyAuth("Basic c2NcmlAYWxEtY2gtYWRmczpjaGVteUA2MzMz"); // test also failed
            req.With(c => ConfigHttpRequest(method))
    );

    return response;
}

protected virtual HttpRequestConfig ConfigHttpRequest(string method)
{
    HttpRequestConfig config = new();
    config.Accept = MimeTypes.Json;

    if (method == HttpMethods.Post || method == HttpMethods.Put || method == HttpMethods.Patch)
    {
        config.ContentType = MimeTypes.Json;
    }

    // Cannot use SetAuthBasic(), because value is only available as an encoded Base64 UTF8 string
    //config.SetAuthBasic("Basic", "c2NcmlAYWxEtY2gtYWRmczpjaGVteUA2MzMz");

    // This did not work
    config.Authorization = new NameValue(name: "Basic", value: "c2NcmlAYWxEtY2gtYWRmczpjaGVteUA2MzMz");

    // Neither did this work (similar to approach used in ServiceStack/6.1.0 project)
    var token = new AuthenticationHeaderValue("Basic", "c2NcmlAYWxEtY2gtYWRmczpjaGVteUA2MzMz");
    config.AddHeader("Authorization", token.ToString());

    return config;
}

I have tried tracing the execution, and the one thing I noticed is that in HttpUtils.HttpClient the httpReq object has a null value for Authorization.

For completeness:

Using curl, an example of a working query using Basic authentication is

curl -X GET "http://fx.data.local:8035/api/pricing/v1/latest" `
  -H "accept: */*" -H "Authorization: Basic c2NcmlAYWxEtY2gtYWRmczpjaGVteUA2MzMz"

In Postman, the following Auth settings work:

Type: API Key
Key: Authorization
Value: Basic c2NcmlAYWxEtY2gtYWRmczpjaGVteUA2MzMz
Add to: Header

Any ideas how to solve myproblem?

If it used to work with the HttpClient you should be able to use the new HTTP Client Utils impl, your first working example should look like:

url.SendStringToUrl(method: method, requestBody:body, requestFilter: req => {
    req.Headers.Authorization = new AuthenticationHeaderValue("Basic", "c2NcmlAYWxEtY2gtYWRmczpjaGVteUA2MzMz");
});

That worked, thank you!

Although, I thought I was doing effectively the same with my configuration method:

    // Neither did this work (similar to approach used in ServiceStack/6.1.0 project)
    var token = new AuthenticationHeaderValue("Basic", "c2NcmlAYWxEtY2gtYWRmczpjaGVteUA2MzMz");
    config.AddHeader("Authorization", token.ToString());

Now, I can start my weekend after your great support.

1 Like