0

The IReportServerCredentials approach with the ReportViewer control is working fine within a domain, but I get a 401 not authorized error for a Web IIS server trying to call a SSRS server in another domain. I've see plenty of helpful postings on the use of IReportServerCredentials but nothing that provides suggestions for this cross domain issue.

Using VS 2008 VB.NET web app with ReportViewer control Version=8.0.0.0.

Outside domainA Web Server IIS 8. OS = Windows NT 6.2;

Inside domainA Windows 7 desktop; Inside domainA Windows Server 2003

SSRS using windows authentication and on SQL Server 2012. OS = Windows NT 6.2

The processing described below successfully produces a report when the web server app runs on a machine in the same domain as the SSRS server. For the "same domain" web app, both Win 7 desktop VS 2008 development server and Windows 2003 IIS 6 have been tested successfully.

The report fails with error "The request failed with HTTP status 401: not authorized " when the web app is run from a windows IIS 8 machine (outward or Internet facing web server) that is not in the domain of the SSRS server. The ReportViewer control credentials (provided by IReportServerCredentials and taken from the web.config file) match a domain account in the same domain as the SSRS server and one that has browser permission on the report folder. The same credentials are used successfully for reports requested from within the SSRS domain.

One interesting thing is that on the Internet facing web server, I can access the report via a browser request. So it is possible to have a user request coming from the Internet facing machine get through the SSRS windows authentication. Just does not work for the ReportViewer.

Using IReportServerCredentials interface per example provided by Microsoft.

IReportServerCredentials would appear to be a good approach because it can pass credentials of a windows account known to the SSRS server, but not known to the client machine. By the way, database calls to SQL Server in domainA using a SQL Server native login account work fine. So the network supports communication to a domain that the web server does not belong to.

<Serializable()> _
Public NotInheritable Class MyReportServerCredentials
    Implements IReportServerCredentials

    Public ReadOnly Property ImpersonationUser() As System.Security.Principal.WindowsIdentity _
        Implements IReportServerCredentials.ImpersonationUser
        Get
            'Use the default windows user.  Credentials will be
            'provided by the NetworkCredentials property.
            Return Nothing
        End Get
    End Property

    Public ReadOnly Property NetworkCredentials() As ICredentials _
            Implements IReportServerCredentials.NetworkCredentials

        Get

            'Read the user information from the web.config file.  
            'By reading the information on demand instead of storing 
            'it, the credentials will not be stored in session, 
            'reducing the vulnerable surface area to the web.config 
            'file, which can be secured with an ACL.

            'User name
            Dim userName As String = _
                ConfigurationManager.AppSettings("MyReportViewerUser")

            If (String.IsNullOrEmpty(userName)) Then
                Throw New Exception("Missing user name from web.config file")
            End If

            'Password
            Dim password As String = _
                ConfigurationManager.AppSettings("MyReportViewerPassword")

            If (String.IsNullOrEmpty(password)) Then
                Throw New Exception("Missing password from web.config file")
            End If

            'Domain
            Dim domain As String = _
                ConfigurationManager.AppSettings("MyReportViewerDomain")

            If (String.IsNullOrEmpty(domain)) Then
                Throw New Exception("Missing domain from web.config file")
            End If

            Return New NetworkCredential(userName, password, domain)

        End Get
    End Property

    Public Function GetFormsCredentials(ByRef authCookie As Cookie, _
                   ByRef userName As String, _
                   ByRef password As String, _
                   ByRef authority As String) As Boolean _
        Implements IReportServerCredentials.GetFormsCredentials
        authCookie = Nothing
        userName = Nothing
        password = Nothing
        authority = Nothing

        'Not using form credentials
        Return False

    End Function
End Class

'Set the ReportViewer values and retrieve the report from the SSRS server into a pdf file on the client machine.

ProposalRptViewer.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Remote

' Set the ReportViewer ReportServerCredentials from the MyReportServerCredentials Class.
' Note the credentials are for a domain account defined in the same domain that the SSRS server belongs to and one that has browser permission on the report folder. 

ProposalRptViewer.ServerReport.ReportServerCredentials = _
     New MyReportServerCredentials()

ProposalRptViewer.ServerReport.ReportServerUrl = New Uri(System.Configuration.ConfigurationManager.AppSettings(Web.[Global].CfgKeyReportServerURL))
ProposalRptViewer.ServerReport.ReportPath = System.Configuration.ConfigurationManager.AppSettings(Web.[Global].CfgKeyReportPathProposal)
ProposalRptViewer.ShowCredentialPrompts = False     ' disable prompting for data source credentials 

Dim paramList As New Generic.List(Of ReportParameter)
Dim pInfo As ReportParameterInfoCollection
pInfo = ProposalRptViewer.ServerReport.GetParameters()
paramList.Add(New ReportParameter("ProposalID", ProposalID, True))paramList.Add(New ReportParameter("Entity", Entity, True))
paramList.Add(New ReportParameter("intRatesPage", intRatesPage1, True))
ProposalRptViewer.ServerReport.SetParameters(paramList)

' Process and render the report 
ProposalRptViewer.ServerReport.Refresh()

Dim mimeType As String = Nothing
Dim encoding As String = Nothing
Dim streams As String() = Nothing
Dim extension As String = Nothing
Dim warnings As Microsoft.Reporting.WebForms.Warning() = Nothing
Dim returnValue As Byte()

' Render the proposal Rate Page 1 report to a Byte Array output in pdf file format.
returnValue = ProposalRptViewer.ServerReport.Render("PDF", Nothing, mimeType, encoding, extension, streams, warnings)

Error only occurs for web server not in domain of SSRS Server:

The request failed with HTTP status 401: Unauthorized. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Net.WebException: The request failed with HTTP status 401: Unauthorized.

Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace:

[WebException: The request failed with HTTP status 401: Unauthorized.] Microsoft.SqlServer.ReportingServices2005.Execution.RSExecutionConnection.GetSecureMethods() +236 Microsoft.SqlServer.ReportingServices2005.Execution.RSExecutionConnection.IsSecureMethod(String methodname) +58 Microsoft.SqlServer.ReportingServices2005.Execution.RSExecutionConnection.SetConnectionSSLForMethod(String methodname) +16 Microsoft.SqlServer.ReportingServices2005.Execution.RSExecutionConnection.LoadReport(String Report, String HistoryID) +226 Microsoft.Reporting.WebForms.ServerReport.GetExecutionInfo() +192 Microsoft.Reporting.WebForms.ServerReport.SetParameters(IEnumerable`1 parameters) +136 DeltaRater.Web.ViewRates.btnCreateProposal_Click(Object sender, EventArgs e) in C:\alex\~~_____Rapid_Rater\SourceDir_VS2008_Jan17_2014\DRR\ViewRates.aspx.vb:911 System.Web.UI.WebControls.Button.OnClick(EventArgs e) +115 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +140 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +29 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2981 ________________________________________ Version Information: Microsoft .NET Framework Version:2.0.50727.8009; ASP.NET Version:2.0.50727.8010

Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
Bob14460
  • 3
  • 1
  • 2

1 Answers1

0

I answered a similar question here -> The request failed with HTTP status 401: Unauthorized. SSRS.

Have you made sure that there is a local account created for your report user?

Community
  • 1
  • 1
Ross Bush
  • 14,648
  • 2
  • 32
  • 55
  • Thanks for your suggestion. I've requested that change to the SSRS owner. When I pass the credentials, what should I specify for the domain since the local account will not be a domain user? – Bob14460 Feb 04 '15 at 15:59
  • If you are using a domain controller then that should work. If you are going to run from a local account on each server then you can pass in nullor "" for the domain. – Ross Bush Feb 04 '15 at 18:35
  • Previously I was attempting to use a domain account on the SSRS server. This worked as long as the web server was in the same domain. It failed for web server outside the domain. Per your suggestion I got a local account defined on the SSRS server. I used IReportServerCredentials to pass the user, pass, and domain as the name of the SSRS server. This approach worked for web server in SSRS domain, but failed with 401 Unauthorized for web server outside the SSRS domain. I will now to pass empty string "" for the domain name. Thanks. – Bob14460 Feb 05 '15 at 17:30
  • I just tried passing "" as the domain. Again this works for web server in the same domain as SSRS. But I get the 401 Unauthorized error when the web server is outside the domain. Any ideas on something else that could be causing the error? Thanks. – Bob14460 Feb 05 '15 at 17:51
  • An additional piece was required for the report request to work across domains. The default user did not have authority to send the request and/or receive the report. Adding the following in section of web.config file was needed. I never needed this extra piece when the web server ran in the same domain as the SSRS server. I thank Irb for making me go through the details of additional tests because that is how I stumbled across an identity comment and ultimately got things working. – Bob14460 Feb 05 '15 at 22:42