We have seen multiple customers with issues when customizing the Security Extension Sample (2005, 2008) that is available on http://www.codeplex.com/. This is the sample that demonstrates how to create a Forms Authentication solution with SQL Server Reporting Services.

There are two scenarios which are the primary sources of the problems:

Scenario 1: “Anonymous” access

Many custom security extension authors want to allow ‘anonymous’ access – where users do not need to login, or to allow all users some basic level of permission without needing to login explicitly. In order to do this, they change the sample code’s implementation of AuthenticationExtension.GetUserInfo to return a NULL for out IIdentity userIdentity.

However, this approach breaks the contract SSRS has with the Security Extension. SSRS in all versions (2000, 2005, and 2008) require that Custom Security Extensions specify a user name for all requests and the IIdentity returned by GetUserInfo must not be NULL.

Scenario 2: Unexpected error in Authentication Extension

The implementation of AuthenticationExtension.GetUserInfo could throw an unexpected error.

Typically this happens when the cookie returned to the extension is not found or incorrectly processed. This can be a tricky area to get right and requires some iteration.

Solutions:

Key thing for Authentication extension authors is that the error messages are hard to diagnose. We’d recommend that in your extension you fail authentication on errors and use a try-catch block to log the error message to your own log file specific to your authentication extension so that you can diagnose the state of the system when the failure occurred.

In the implementation of AuthenticationExtension.GetUserInfo, ensure you are returning a non-null IIdentity object and that UserName has a value.

Diagnosis:

In RS 2008:

We changed the error message we return to:

rsAuthenticationExtensionError - The Authentication Extension threw an unexpected exception or returned a value that is not valid: <value>.

When the authentication extension returns a null identity <value> will be “identity==null”.

If the authentication extension returns an error message from the AuthenticationExtension.GetUserInfo method then <value> will be the name of the exception.

In RS 2005 and before:

The challenge to diagnose this issue is that the call stacks can vary depending on the call being made to the SSRS server. However, these typically will include an InternalCatalogException and in the call stack you’ll see ASSERT or NullReferenceException.

If AuthenticationExtension.GetUserInfo method throws an error, an InternalCatalogException or a NullReferenceException will be in the SSRS trace log file.

If UserName is NULL, you’re going to get an ASSERT on the server side and an error will be returned to the user.

Here are a couple of examples:

Example 1: ASSERT

w3wp!library!5!2/4/2009-14:31:47:: e ERROR: Throwing Microsoft.ReportingServices.Diagnostics.Utilities.InternalCatalogException: An internal error occurred on the report server. See the error log for more details., un-named assertion fired for component library;
Info: Microsoft.ReportingServices.Diagnostics.Utilities.InternalCatalogException: An internal error occurred on the report server. See the error log for more details.
w3wp!library!1!2/4/2009-14:32:10:: i INFO: Call to RenderFirst( '/VP Reports/Client/Generic/AdvFinChargesByAccount' )
w3wp!library!1!2/4/2009-14:32:11:: a ASSERT: Assertion failed! Call stack:

Example 2: NullReferenceException

w3wp!library!8!06/21/2007-14:52:09:: e ERROR: Throwing Microsoft.ReportingServices.Diagnostics.Utilities.InternalCatalogException: An internal error occurred on the report server. See the error log for more details., ;
Info: Microsoft.ReportingServices.Diagnostics.Utilities.InternalCatalogException: An internal error occurred on the report server. See the error log for more details. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.ReportingServices.WebServer.WebServiceHelper.ConstructRSServiceObjectFromSecurityExtension()
at Microsoft.ReportingServices.WebServer.Global.ConstructRSServiceFromRequest(String item)
at Microsoft.ReportingServices.WebServer.Global.get_Service()
at Microsoft.ReportingServices.WebServer.Global.DispatchRequest(Boolean& transferedToViewerPage)
at Microsoft.ReportingServices.WebServer.Global.Application_AuthenticateRequest(Object sender, EventArgs e)

 

Take care and good luck,

-Lukasz