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
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.
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?
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
Please get back to us if you have further queries.
Regards,
Vignesh Natarajan
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
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()
...
...
Hi Wuss,
Thanks for the suggestion.
Regards,
Getsy