Web API cookie authntication fails in Blazor server SFGrid with ODataV4Adapter

How can I use Cookie authentication with the ODataV4Adapter?

I have a Blazor Server .Net 7 application using cookie authentication and the Syncfusion Blazor controls version 24.1.41:

builder.Services.AddAuthentication()
 .AddCookie();

I require authorization on all of my Web API controllers:

app.MapControllers()
    .RequireAuthorization();

I have a Web API controller that is setup to support OData

[EnableQuery(PageSize = 12)]
[HttpGet]
public IQueryable<WebhookEvent> Get()
{
    return db.WebhookEvents.AsQueryable();
}

I have a page with an SfGrid that is using an SfDataManager with the ODataV4Adapter adapter.

<SfDataManager Url="odata/WebhookEvents" Adaptor="Adaptors.ODataV4Adaptor" />

If I add the [AllowAnonymous] attribute to my web API controller, the page works great.  As soon as I remove the [AllowAnonymous] attribute, I get an error from the SfGrid.  It looks like the HttpClient used by the ODataV4Adapter isn't including the authentication cookies in the call to odata/WebhookEvents.

I tried injecting IHttpClientFactory into my page, creating an instance of HttpClient and assigning it to the HttpClientInstance property of the SfDataManager but it still didn't work. 

Note: This is the error from the exception in the SfGrid ActionFailure event: 

'<' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.

 Thanks for any help you can provide.

Craig


6 Replies

CB Craig Boucher December 21, 2023 11:26 PM UTC

Quick update: I added a custom middleware class so I could inspect the HttpContext.Request object and all calls to the odata endpoint don't contain any cookies.  All of the other HttpContext request objects that pass through the middleware do contain the ".AspNetCore.Cookies" cookie.



CB Craig Boucher December 21, 2023 11:53 PM UTC

Another update, I got it to work by doing the following:

I added the following at startup:

builder.Services.AddHttpContextAccessor();
builder.Services.AddHttpClient();


Then add the following into my page:

[Inject] IHttpClientFactory httpClientFactory { get; set; } = default!;
[Inject] IHttpContextAccessor httpContextAccessor { get; set; } = default!;
private HttpClient httpClient = default!;


With the following code in the OnInitializedAsync method:

httpClient = httpClientFactory.CreateClient();
if (httpContextAccessor.HttpContext.Request.Headers.TryGetValue("Cookie", out var cookies))
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Cookie", cookies.ToList());


And set HttpClientInstance to httpClient in the SfDataManager

    <SfDataManager Url="odata/WebhookEvents"
                   Adaptor="Adaptors.ODataV4Adaptor"
                   HttpClientInstance="@httpClient" />

Is this the correct way or is there a better way?



VN Vignesh Natarajan Syncfusion Team December 26, 2023 04:29 AM UTC

Hi Craig,


Thanks for contacting Syncfusion support.


Query: “Is this the correct way or is there a better way?


We are glad to hear that you have achieved your requirement on your own. We have also provided support to authenticate the SfDataManager and discussed related this topic in our UG documentation. Kindly refer to the below documentation link for your reference.


https://blazor.syncfusion.com/documentation/datagrid/data-binding#authorization-and-authentication

https://blazor.syncfusion.com/documentation/datagrid/data-binding#setting-custom-headers

https://blazor.syncfusion.com/documentation/datagrid/data-binding#sending-additional-parameters-to-the-server


Please get back to us if you have further queries.


Regards,

Vignesh Natarajan





NI Nicola replied to Craig Boucher January 4, 2024 02:24 PM UTC

Thanks a lot Craig,

your solution is the best one.

Using a base class for the razor pages where I need to call OData resolve any issue.


Thanks again




WW Wuss Wuzz April 27, 2024 01:09 PM UTC

if using blazor .net8 or greater , I did this


...
...


builder.Services.AddHttpClient(
    "MyApp",
    client => client.BaseAddress = new Uri(builder.Configuration.GetSection("AppUrls")["BaseApiUrl"]!)
).AddHeaderPropagation() // <--- THIS LINE MUST BE ADDED

.ConfigurePrimaryHttpMessageHandler(() =>
{
    // !!! DISABLE IN PROD. THIS IS TO BYPASS CHECKING SSL CERT AUTH FOR DEV PURPOSES !!!
    var handler = new HttpClientHandler
    {
        ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
    };


    return handler;
});
builder.Services.AddHeaderPropagation(options => // <-- THIS BLOCK MUST BE ADDED

{
    options.Headers.Add("Cookie");  <--- THE HEADER FOR ME WAS "Cookie"

});


...
...


app.UseHttpsRedirection();
app.UseHeaderPropagation(); //<--- MUST BE ADDED, place after app.UseHttpsRedirection()


...
...


GE Getsy Edwin Syncfusion Team April 29, 2024 09:25 AM UTC

Hi Wuss,

Thanks for the suggestion.

Regards,

Getsy


Loader.
Up arrow icon