Using Forms Authentication with the Report Viewer control and SQL Server Reporting Services 2005
I've been playing around with using different forms of authentication / impersonation with the Report Viewer controls, and I thought I'd post the fruits of my efforts. Here we go:
Using Forms Authentication with the Winform Report Viewer control is easy -- Just pass in the creds and you're all done:
reportViewer1.ServerReport.ReportServerCredentials.SetFormsCredentials(null, "userName", "password", "domainName");
this.reportViewer1.RefreshReport();
Doing the same thing with the Webform Report Viewer control is kind of a pain in the tail. You actually have to implement an interface called IReportServerCredentials and write/borrow another subclass that handles all the cookie related stuff when dealing with Forms Auth.
I took most of the following code from the following help topic, btw:
https://msdn2.microsoft.com/en-us/library/microsoft.reporting.webforms.ireportservercredentials.aspx
Anyway, first create the code for your Forms Auth Login page:
MyReportingService svc = new MyReportingService();
svc.Url = "https://myServer/reportserver/reportexecution2005.asmx";
try
{
svc.LogonUser("myUserName", "MyPassword", null);
Cookie myAuthCookie = svc.AuthCookie;
if (myAuthCookie == null)
{
Message.Text = "Logon failed";
}
else
{
HttpCookie cookie = new HttpCookie(myAuthCookie.Name, myAuthCookie.Value);
Response.Cookies.Add(cookie);
string returnUrl = Request.QueryString["ReturnUrl"];
if (returnUrl == null || !returnUrl.StartsWith("/"))
Message.Text = "Return url is missing or invalid!";
else
Response.Redirect("https://myServer/appFolder/default.aspx");
}
}
catch (Exception ex)
{
Message.Text = "Logon failed: " + ex.Message;
}
The code above calls LogonUser() against the SSRS web service so that we can get the Forms Auth cookie back from SSRS itself. Then, we stick the cookie into Response.Cookies, and forward the user to a page which has a ReportViewer control on it (in this case, https://myServer/appFolder/default.aspx)
OK, so now we're sitting on the page which has the Report Viewer control itself.
In Page_Load, we first see if the previous cookie exists...if it doesn't, we send you right back to the logon form:
HttpCookie cookie = Request.Cookies["sqlAuthCookie"];
if (cookie == null)
{
Response.Redirect("/appFolder/logon.aspx?ReturnUrl=" + HttpUtility.UrlEncode(Request.RawUrl));
}
else
{
ReportViewer1.ProcessingMode = ProcessingMode.Remote;
ReportViewer1.ServerReport.ReportServerUrl = new Uri("https://myServer/reportserver");
ReportViewer1.ServerReport.ReportPath = "/Report Project2/Report1";
Cookie authCookie = new Cookie(cookie.Name, cookie.Value);
authCookie.Domain = "myServer";
ReportViewer1.ServerReport.ReportServerCredentials =
new MyReportServerCredentials(authCookie);
}
If the cookie IS there, we set a few properties on the Report Viewer control, then set the ReportServerCredentials property of the control equal to our authCookie. Here is where the implementation of IReportServerCredentials and that other "cookie-handling class" come in.
First, here's the implementation of IReportServerCredentials. It allows us to create a MyReportServerCredentials object:
class MyReportServerCredentials : IReportServerCredentials
{
private Cookie m_authCookie;
public MyReportServerCredentials(Cookie authCookie)
{
m_authCookie = authCookie;
}
public WindowsIdentity ImpersonationUser
{
get
{
return null; // Use default identity.
}
}
public ICredentials NetworkCredentials
{
get
{
return null; // Not using NetworkCredentials to authenticate.
}
}
public bool GetFormsCredentials(out Cookie authCookie,
out string user, out string password, out string authority)
{
authCookie = m_authCookie;
user = password = authority = null;
return true; // Use forms credentials to authenticate.
}
}
As I mentioned earlier, we also have to subclass the myServer.ReportExecutionService class and override a few methods in order to do the cookie-related work:
public class MyReportingService : myServer.ReportExecutionService
{
private Cookie m_authCookie;
public Cookie AuthCookie
{
get
{
return m_authCookie;
}
}
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Credentials = base.Credentials;
request.CookieContainer = new CookieContainer();
if (m_authCookie != null)
request.CookieContainer.Add(m_authCookie);
return request;
}
protected override WebResponse GetWebResponse(WebRequest request)
{
WebResponse response = base.GetWebResponse(request);
string cookieName = response.Headers["RSAuthenticationHeader"];
if (cookieName != null)
{
HttpWebResponse webResponse = (HttpWebResponse)response;
m_authCookie = webResponse.Cookies[cookieName];
}
return response;
}
}
...and that's it. You may actually have better luck using the URL at the top of the page for your code copying and pasting as it contains HTML you can use for you logon page, too.
My biggest problem with this whole scenario was actually *finding* the help topic I needed...It would have nice if I could have searched on "forms authentication report viewer control" and been directed to the topic in question (grump, grump).
Comments
Anonymous
November 30, 2005
I did almost that exact search and it sent me here. Thanks for doing the legwork.Anonymous
January 23, 2006
The comment has been removedAnonymous
April 11, 2006
This is the closest I found to solving this issue. There is no equivalent in VB to the 'out' statement and I'm getting also sorts of grief with the interface.
Do you know or can you direct me to how this code might work in VB?
Cheers,
KarinAnonymous
April 17, 2006
I think ByRef is the closest you can get to out in VB -- it is not the exact same thing, but I think it carries out the same function...Anonymous
April 17, 2006
The comment has been removedAnonymous
April 18, 2006
The comment has been removedAnonymous
May 02, 2006
An eclectic bunch of (mostly techie) bits that don't really deserve a post each:
Here's a really useful...Anonymous
May 24, 2006
I have anonnymous access but keep on getting this error when using your code even though I'm logging in as admin. Anyone has any idea why?
{"System.Web.Services.Protocols.SoapException: Logon failed. ---> Microsoft.ReportingServices.Diagnostics.Utilities.LogonFailedException: Logon failed.n at Microsoft.ReportingServices.WebServer.RSCustomAuthentication.LogonUser(String userName, String password, String authority)n at Microsoft.ReportingServices.WebServer.ReportingService.LogonUser(String userName, String password, String authority)n --- End of inner exception stack trace ---n at Microsoft.ReportingServices.WebServer.ReportingService.LogonUser(String userName, String password, String authority)"}Anonymous
September 25, 2006
The comment has been removedAnonymous
November 03, 2006
Great article and I've almost got it working, however the authcookie is null and the service is returning a SoapException at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(). When I step through the code, the m_authCookie is always null.Anonymous
November 12, 2006
I used the code above, but I always receive the following error message:"The type or namespace name 'ReportExecutionService' could not be found (are you missing a using directive or an assembly reference?)"What using reference do I need? Or how can I solve this problem?thxAnonymous
November 13, 2006
Dear Russell,I also used this code...but the following error message appear: "The server committed a protocol violation. Section=ResponseStatusLine"I tried to use the the cod ein my web.config, but the error is still there:<system.net> <settings> <httpWebRequest UnsafeHeaderParsing "true" /> </settings> </system.net> Does anybody have the same problem or does anybody know how I can handle this?Anonymous
January 03, 2007
Can you please send me the Details of how to over come this problem Im having the Same Problemhere is my errorSystem.Web.Services.Protocols.SoapException: System.Web.Services.Protocols.SoapException: Logon failed. ---> Microsoft.ReportingServices.Diagnostics.Utilities.LogonFailedException: Logon failed. at Microsoft.ReportingServices.WebServer.RSCustomAuthentication.LogonUser(String userName, String password, String authority) at Microsoft.ReportingServices.WebServer.ReportingService.LogonUser(String userName, String password, String authority) --- End of inner exception stack trace --- at .................Please help meAnonymous
January 03, 2007
Russel this authentication is helpful if u render the report using report viewer control but what I want is to render the rdl file. is there any way to do that also?Thanks in advanceSudhaAnonymous
March 06, 2007
Stiamo in questi giorni migrando una applicazione di un nostro cliente ad una nuova infrastruttura HWAnonymous
March 06, 2007
Stiamo in questi giorni migrando una applicazione di un nostro cliente ad una nuova infrastruttura HWAnonymous
March 24, 2007
I am also getting The type or namespace name 'ReportingService' could not be found (are you missing a using directive or an assembly reference?)Something is not installed perhaps a Reportservices SDK?msrspbs.20.zdux0012 (at) xoxy.netAnonymous
March 27, 2007
I just have my brain bursted:Is there a way to have an indirection between an WinForm aplication and Reporting Services?I mean, on client side there's a Winform Report Viewer embed into an application; client of a custom webservice. Is there a way to have Report Viewer to not refer directly the Reporting Services WebSites/Services, but through some kind of custom webservice indirection????Something like:[ReportViewer] Get Report -> [Custom WebService] grab the request, process something, forward it to -> [Reporting Services] produces report -> [Custom WebService] grab the response, process something, return it to -> [ReportViewer] renderAnonymous
March 27, 2007
Horatui -- No, there is no way to do this. If you want to approximate the same thing, you could go into local mode and populate your dataset via another webservice, then bind it to the control.Anonymous
April 01, 2007
Actually, we quite did it...But this is a workaround to avoid Forms Authentication of WinForm.ReportViewer.The main problem is that we have a custom authentication for a larger app (windows clients/web serviced), which contains reports. We don't want new pop-ups or whatever for further authentications, once someone is logged in the application it should be able to view the reports.Is there a way to obtain a RS Form Authentication authCookie from a Windows app and use it instead of passing usr/pwd?Anonymous
May 24, 2007
I am getting rsLogonfailed doing the same thingb.o.o.h.o.o.:(Anonymous
June 04, 2007
To pass the autenticated user from ASP.NET 2005 to the SQL Report Server 2005 without passing in the user name and password try....ReportViewer reportViewer = new ReportViewer(); ReportViewerCredentials rvc = new ReportViewerCredentials((WindowsIdentity)Page.User.Identity); reportViewer.ServerReport.ReportServerCredentials = rvc;public class ReportViewerCredentials : IReportServerCredentials{ WindowsIdentity _userToken; public ReportViewerCredentials(WindowsIdentity userToken) { _userToken = userToken; } #region IReportServerCredentials Members public WindowsIdentity ImpersonationUser { get { return _userToken; } } public ICredentials NetworkCredentials { get { return null; // Not using NetworkCredentials to authenticate. } } #endregion #region IReportServerCredentials Members public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority) { authCookie = null; userName = null; password = null; authority = null; return false;// throw new Exception("The method or operation is not implemented."); } #endregion}Anonymous
July 18, 2007
Hi Russell,When i try running the report in ReportViewer control dragged on one of my webpage, i get the following error:Client found response content type of '', but expected 'text/xml'. The request failed with an empty response.(Please note: SSRS works in Forms mode of authentication)Can you please suggest me the solution for this problem?Any help would be much appreciated.Thanks,DSAnonymous
July 18, 2007
Ignore my previous query. I got resolved it. ReportServerUrl was not set correctly. I had 'localhost' mentioned in it instead of <machinename>Thanks,DSAnonymous
November 13, 2007
Hi,I've just recently been messing around with this stuff and can't understand something and thought you can shed some light on it.I have a network structure where the report server resides on some internal network segment (not internet facing) and my ASP.NET app that needs to serves reports to the clients; the ASP is internet facing.When I tried to use the ReportViewer control in my app there were a few things that I noticed that didn't make much sense to me.PROBLE: When the authentication issued a ticket it needed to translate the Cookie object into HttpCookie object; in the sample code it translated that cookie. In so doing I copied all attributes including the Cookie.Domain object into the HttpCookie (in Login.aspx).When I did this, the redirect form (Default.aspx) did not contain the cookie in the Request.Cookies collection. When I didn't set this in Login.aspx and set it in Default.aspx it seem to render the report fine. Why does this domain setting remove the cookie from the cookiejar?Thanks,Jay.Anonymous
January 31, 2008
This is a really useful article. Found it after a long search.Anonymous
March 18, 2008
EXCELLENT article. Thanks!-KripAnonymous
July 01, 2008
Forms Authentication does not work with Report Viewer. I get Object moved to here error. HelpAnonymous
July 09, 2008
Are you pointing to the real name of your server, or using http://localhost instead. Make sure not to use localhost.Anonymous
August 01, 2008
PingBack from http://brodie.freevideonewsservice.info/usingformsauthentication.htmlAnonymous
August 27, 2008
The comment has been removedAnonymous
October 28, 2008
I am trying to find out how to get GetUserId function in Report Models to work. It was broken by the Custom Security Extension, like everything else, and I need a fix for it.Anonymous
November 13, 2008
This worked well....thanks for posting!Anonymous
March 30, 2009
Actually we are trying to develop a asp.net app in C# for displaying the the ssrs reports. We want to use a tree view and pass the node url's through the database. WE tried using Report viewer but we were unsuccessful. Can any one help us to find a right way to reach the goal.Anonymous
June 01, 2009
PingBack from http://paidsurveyshub.info/story.php?id=76199Anonymous
June 15, 2009
PingBack from http://debtsolutionsnow.info/story.php?id=1318Anonymous
January 16, 2010
Did the same work with little bit changes to the same post. http://praveenbattula.blogspot.com/2010/01/report-viewer-control-authentication_16.htmlAnonymous
January 28, 2010
Thank you very much for the post. It helped me a lotAnonymous
August 17, 2015
I use ReportService http://DEVRPS/ReportServer/ReportService2005.asmx?WSDL I use powershell script por deploy RDL files in SSRS 2008 server and I get error Message: Exception calling "DeleteItem" with "1" argument(s): "The request failed with HTTP status 401: Unauthorized." With the same credential, in IE is ok http://DEVRPS/ReportServer/ReportService2005.asmx?WSDL In Report Services 2008 by default it uses its own built-in server, not IIS. You'll need to check in the reporting services directory on your server (its in the usual MSSQL directory in Program Files) to see the configuration files and make changes (you can also make some through reporting services configuration manager). Microsoft does not recommend installing IIS on the reporting services server. SSRS 2008 doesn't use IIS troubleshoot IIS and 401 not useful then for me support.microsoft.com/.../907273 Any suggestions ?