Skip to content

.NET SDK Bug: CredentialsMethod.ApiToken throw duplicate authorization header error #471

@alovera

Description

@alovera

Checklist

  • I have looked into the README and have not found a suitable solution or answer.
  • I have looked into the documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have searched the Slack Community and have not found a suitable solution or answer.
  • I agree to the terms within the OpenFGA Code of Conduct.

Description

There is a bug in the .NET OpenFga.Sdk in the ApiClient class when you configure the client to use ClientCredentialsMethod.ApiToken. The setup in our application is the following:

appSettings.json

{
  "OpenFGAConfiguration": {
    "ApiUrl": "https://localhost:8102",
    "StoreId": "01JJ2AKYJX4KXKF59JAVXMTAZ2",
    "ApiToken": "f54daf80-fcfd-47c4-886f-98804fcc9279"
  }
}

Program.cs

var openFgaConfig = builder.Configuration
    .GetSection("OpenFGAConfiguration")
    .Get<ClientConfiguration>()!;

var apiToken = builder.Configuration
    .GetSection("OpenFGAConfiguration")
    .GetValue<string>("ApiToken")

// No way to currently set this directly via .NET config because of ICredentialsConfig interface
openFgaConfig.Credentials = new Credentials
{
    Method = CredentialsMethod.ApiToken,
    Config = new CredentialsConfig { ApiToken = apiToken }
};

services.AddSingleton<ClientConfiguration>(openFgaConfig);
services.AddHttpClient<OpenFgaClient>();

Using the setup above, we receive the following error any time we try to use the OpenFgaClient in code:

System.FormatException
  HResult=0x80131537
  Message=Cannot add value because header 'Authorization' does not support multiple values.
  Source=System.Net.Http
  StackTrace:
   at System.Net.Http.Headers.HttpHeaders.ParseAndAddValue(HeaderDescriptor descriptor, HeaderStoreItemInfo info, String value)

After debugging the source code, we found the cause of the error. When the OpenFgaClient is instantiated, it creates an internal OpenFgaApi object (see here) passing in the ClientConfiguration from the DI container and the HttpClient created by the HttpClientFactory. The OpenFgaApi then creates an internal ApiClient, again passing down the configuration and http client (see here). This ApiClient is where the problematic code begins.

The ApiClient starts by initializing a BaseClient using the configuration and client (see here) and then it initializes the BaseClient again when it detects that the credential method is ApiToken (see here). Both of these calls use the same configuration and client.

These calls work fine the first time the HttpClient is initialized. The client default headers are added as expected in the BaseClient class (see here). However, it fails the second time the class is initialized because the HttpClientFactory reuses the same HttpClient which already has the default headers configured. When this occurs, you get the exception above when a second "Authorization" header is added to the DefaultRequestHeaders collection.

Expectation

The code above should work as configured, specifically when using the HttpClientFactory registration method. The BaseClient constructor should check to see if the default header(s) already exist before adding additional headers.

Reproduction

Given you configure the OpenFgaClient with the services.AddHttpClient<OpenFgaClient>() method
When you configure the OpenFgaClient to use ApiToken authentication
Then you receive the error "Cannot add value because header 'Authorization' does not support multiple values."

SDK Checklist

  • JS SDK
  • Go SDK
  • .NET SDK
  • Python SDK
  • Java SDK

OpenFGA SDK version

0.5.1

OpenFGA version

latest

SDK Configuration

Via appSettings.json configuration

Logs

No response

References

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions