Passing Authentication to SSRS Report Viewer (.Net 5)

This is using the Radzen client.

The markup:

@page "/"
@page "/index"
@layout MainLayout
@inherits RadzenSsrs.Pages.IndexComponent

@using Radzen
@using Radzen.Blazor
<RadzenContent Container="main">
  <ChildContent>
    <RadzenHeading Size="H1" Text="Index">
    </RadzenHeading>
    <RadzenSSRSViewer ReportName="/Reports/myreport" 
                      ReportServer="http://0.0.0.0/ReportServer" 
                      style="height: 426.6000061035156px" UseProxy="true">
    </RadzenSSRSViewer>
  </ChildContent>
</RadzenContent>

I created a partial ReportController class:

using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace RadzenSsrs.Controllers
{
    public partial class ReportController 
    {
        partial void OnHttpClientHandlerCreate(ref HttpClientHandler handler)
        {
            //handler.UseDefaultCredentials = true;
            handler.PreAuthenticate = true;
            string ReportServerUserId = "username";
            string ReportServerPassword = "password";

            handler.Credentials = new NetworkCredential(ReportServerUserId, ReportServerPassword);
        }
    }
}

When running against a SSRS server Version 15.0.7243.37714

I get:

System.ComponentModel.Win32Exception (0x80090302): The function requested is not supported
at System.Net.NTAuthentication.GetOutgoingBlob(Byte[] incomingBlob, Boolean throwOnError, SecurityStatusPal& statusCode)
at System.Net.NTAuthentication.GetOutgoingBlob(String incomingBlob)
at System.Net.Http.AuthenticationHelper.SendWithNtAuthAsync(HttpRequestMessage request, Uri authUri, Boolean async, ICredentials credentials, Boolean isProxyAuth, HttpConnection connection, HttpConnectionPool connectionPool, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.AuthenticationHelper.SendWithAuthAsync(HttpRequestMessage request, Uri authUri, Boolean async, ICredentials credentials, Boolean preAuthenticate, Boolean isProxyAuth, Boolean doRequestAuth, HttpConnectionPool pool, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
at RadzenSsrs.Controllers.ReportController.ForwardRequest(HttpClient httpClient, HttpRequest currentReqest, String url) in C:\Users\Michael\Documents\Radzen\server\Controllers\ReportController.cs:line 129
at RadzenSsrs.Controllers.ReportController.Get(String url) in C:\Users\Michael\Documents\Radzen\server\Controllers\ReportController.cs:line 25
at lambda_method63(Closure , Object )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Hi @ADefWebserver,

I see that such issue was reported year ago unfortunately closed:

Maybe they will consider reviewing this time since you have a repro project.

1 Like

This error seems to be related to NTLM/Kerberos configuration on the server you are trying to connect to. I found the following resources:

https://support.bluemedora.com/s/article/Microsoft-SQL-Server-for-vROps-SSPI-handshake-failed-with-error-code-0x80090302
https://blog.hosebei.ch/2019/01/02/i-have-configured-network-security-restrict-ntlm-ntlm-authentication-in-this-domain-months-ago-here-is-why-it-catched-me/

You can check the event log of your Server to see if there is a more detailed error description.

1 Like

I will investigate.
Thank You!

Have you had any luck with this?

@lordrob1 - I have not had a chance to explore any of these solutions, and my current schedule does not seem to provide the time any time soon :frowning:

@lordrob1 @ADefWebserver,

I think the code generated in the ReportController does not do anything out of the ordinary. The problem is probably some NTLM/Kerberos configuration error but the error is too cryptic to determine that. The only thing we can suggest is checking the server event logs for anything suspicious.

Temp solution ... added WinHttpHandler nuget package and then replaced httpclienthandler with winhttphandler. I am now able to view reports in my .net 5 radzen app.

https://www.nuget.org/packages/System.Net.Http.WinHttpHandler/

2 Likes

@lordrob1 - Do you have a code sample you can share?

@ADefWebserver probably changing the following code in the ReportController:

private HttpClient CreateHttpClient()
{
     var httpClientHandler = new HttpClientHandler();

to

private HttpClient CreateHttpClient()
{
     var httpClientHandler = new System.Net.Http.WinHttpHandler();
1 Like

Yes, that is what I did.

Exclude reportcontroller.cs in radzen app.

Then modify CreateHttpClient method.

Unfortunately we were unable to use the Radzen report viewer with server authentication.

The alternative, so far, has been to make a call via JSRuntime.InvokeAsync ("open", <credentials @ server / report>, "_blank")

I am using RadzenSSRSViewer in Blazor server app.How can I pass the credential ?
I have created partial ReportController but not getting how it will hit/refer from my .razor page ? Giving me an error : No defining declaration found for implementing declaration of partial method ...