Impersonating another user with the Web Form Report Viewer control and SQL Server Reporting Services 2005

I covered how to do impersonation with the Winform ReportViewer control a few weeks ago, so here’s how to do it with the WebForm version.

The first thing to keep in mind is that by default the WebForm ReportViewer will run under the security context of your application’s AppPool identity. So, depending on the identity of the AppPool your app is running under, it’s not unlikely that the control won’t work at all (authorization-wise) when you first use it.

The easiest way to get impersonation working is to simply use web.config and set identity impersonate to true — and optionally plug in a specific user / password, etc. etc.

See the following “how to” article if this stuff doesn’t sound familiar:

306158 How to implement impersonation in an ASP.NET application

The most interesting scenario is around how to dynamically swap the identity that the ReportViewer uses. This takes a bit more work.

First, you have to implement IReportServerCredentials. The two key things that we do are:

  • Retrieve the user credentials we want to use for impersonation (check out the overloaded properties where we set this stuff)

  • Use the credentials to create and return a WindowsIdentity object (examine the ImpersonationUser member)

namespace x
    public class ReportViewerCredentials : IReportServerCredentials
        [DllImport(“advapi32.dll”, SetLastError = true)]
        public extern static bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        [DllImport(“kernel32.dll”, CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        [DllImport(“advapi32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
            int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
        public ReportViewerCredentials()

        public ReportViewerCredentials(string username)
            this.Username = username;

        public ReportViewerCredentials(string username, string password)
            this.Username = username;
            this.Password = password;

        public ReportViewerCredentials(string username, string password, string domain)
            this.Username = username;
            this.Password = password;
            this.Domain = domain;

        public string Username
                return this.username;
                string username = value;
                if (username.Contains(“\\”))
                    this.domain = username.Substring(0, username.IndexOf(“\\”));
                    this.username = username.Substring(username.IndexOf(“\\”) + 1);
                    this.username = username;
        private string username;


        public string Password
                return this.password;
                this.password = value;
        private string password;

        public string Domain
                return this.domain;
                this.domain = value;
        private string domain;


        #region IReportServerCredentials Members

        public bool GetBasicCredentials(out string basicUser, out string basicPassword, out string basicDomain)
            basicUser = username;
            basicPassword = password;
            basicDomain = domain;
            return username != null && password != null && domain != null;

        public bool GetFormsCredentials(out string formsUser, out string formsPassword, out string formsAuthority)
            formsUser = username;
            formsPassword = password;
            formsAuthority = domain;
            return username != null && password != null && domain != null;


        public bool GetFormsCredentials(out Cookie authCookie,
      out string user, out string password, out string authority)
            authCookie = null;
            user = password = authority = null;
            return false;  // Not implemented

        public WindowsIdentity ImpersonationUser

                string[] args = new string[3] { this.Domain.ToString(), this.Username.ToString(), this.Password.ToString() };
                IntPtr tokenHandle = new IntPtr(0);
                IntPtr dupeTokenHandle = new IntPtr(0);

                 const int LOGON32_PROVIDER_DEFAULT = 0;
        //This parameter causes LogonUser to create a primary token.
        const int LOGON32_LOGON_INTERACTIVE = 2;
        const int SecurityImpersonation = 2;

        tokenHandle = IntPtr.Zero;
        dupeTokenHandle = IntPtr.Zero;
            // Call LogonUser to obtain an handle to an access token.
            bool returnValue = LogonUser(args[1], args[0], args[2],
                ref tokenHandle);

            if (false == returnValue)
                Console.WriteLine(“LogonUser failed with error code : {0}”,
                return null;

            // Check the identity.
            System.Diagnostics.Trace.WriteLine(“Before impersonation: “
                + WindowsIdentity.GetCurrent().Name);

            bool retVal = DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle);
            if (false == retVal)
                Console.WriteLine(“Exception in token duplication.”);
                return null;

            // The token that is passed to the following constructor must
            // be a primary token to impersonate.
            WindowsIdentity newId = new WindowsIdentity(dupeTokenHandle);
            WindowsImpersonationContext impersonatedUser = newId.Impersonate();

            // Free the tokens.
            if (tokenHandle != IntPtr.Zero)
            if (dupeTokenHandle != IntPtr.Zero)

            // Check the identity.
            System.Diagnostics.Trace.WriteLine(“After impersonation: “
                + WindowsIdentity.GetCurrent().Name);

            return newId;

        catch (Exception ex)
            Console.WriteLine(“Exception occurred. ” + ex.Message);
                return null;

        public ICredentials NetworkCredentials
                return null;  // Not using NetworkCredentials to authenticate.


OK, now that we’ve implemented IReportServerCredentials, all that’s left is to use the implementation by creating an instance of ReportViewerCredentials, and then assigning this to the reportViewer1.ServerReport.ReportServerCredentials property.

//I have this in Page_Load, assuming that the other properties of the control have already been set:

x.ReportViewerCredentials rvwCreds = new x.ReportViewerCredentials(“UserName”, “Password”, “Domain”);
reportViewer1.ServerReport.ReportServerCredentials =  rvwCreds;


Comments (45)

  1. Raghu says:

    I have used the above code to impersonate a specific user and can view the reports. But, I get an error when I click on Page Navigation, Refresh or any of the buttons on the Report Viewer Toolbar. Can you please help.

    When I click on the page navigation button, the error that is displayed is:

    "Page navigation is out of range "

    Clicking on any other button will result in the error – "Execution session has expired"

    The Report Server and the server hosting web application is on different servers.

  2. Raghu, I’m only aware of this error in conjunction with viewing a LINKED report inside the report viewer control..

    Did you check your event log to see if the app pool or aspnet_wp is recycling? Try to narrow things down by running a report in LOCAL mode to see if it really is a problem with SSRS, the ReportViewer control, or the ASP.NET app hosting the control.

  3. vamsi says:

    This worked fot me. The only change I am forced to make this work is changing the web app session state to InProc.



  4. nic says:

    Hello Russell, I’ve implemented your ReportViewerCredentials class into my web app, now everything works fine except that sometimes when I try to change the ServerURL or ReportPath properties of the ReportViewer, I get an "Operation is not valid due to the current state of the object" error. I’ve tested this on many reports and found that the error only occurs when the report I’m viewing is a linked report (i.e. the property IsDrillthroughReport==true). You mentioned in your earlier comment "error in conjunction with viewing a LINKED report inside the report viewer control", so I wonder if my problem has to do with the impersonation and if so, is there any way to solve this?



  5. nic, I see what you are talking about. There are a few reports of this behavior, and if you were using the WebForm ReportViewer, all you’d need to do is call ReportViewer.Reset(), and you’d probably be in good shape…however we don’t have this method in the web reportviewer. I’ll poke around and see if I can find an equivalent technique.

  6. Trish says:

    We have implemented the above code.  Everything was working fine until we had two users attempt to get to SRSS at the same time.  

    We are using the web reportviewer and always using the credentials of one windows users (ReportViewer).  

    The error we are getting is "Unhandled exception was caught: System.Web.HttpException: An error occurred while attempting to impersonate.  Execution of this request cannot continue."  

    One user is able to view the report but the others get the above error message.

    Any ideas?

  7. Trish says:

    It looks like the problem doesn’t occur under Windows XP…but when we push it out to our build server that is Windows 2003 we start getting the messages.

  8. Trish says:

    Here is the applicaton error log message:

    Event code: 3005

    Event message: An unhandled exception has occurred.

    Event time: 3/30/2006 10:39:10 AM

    Event time (UTC): 3/30/2006 4:39:10 PM

    Event ID: cf181f6f9e4f4460a6e0828711ba51e9

    Event sequence: 6267

    Event occurrence: 12

    Event detail code: 0

    Application information:

       Application domain: /LM/W3SVC/52577887/root/ReportServer-2-127881193422582207

       Trust level: RosettaSrv

       Application Virtual Path: /ReportServer

       Application Path: C:Program FilesMicrosoft SQL ServerMSSQL.2Reporting ServicesReportServer

       Machine name: BUILD

    Process information:

       Process ID: 4500

       Process name: w3wp.exe


    In our XP environment we are using ASPNET…in the windows 2003 environment it is using the NETWORK SERVICE.

  9. Trish says:

    Ok, we resolved it.  We commented out the code in ImpersonateUser and just had it return null.  That made it return the GetBasicCredentials that worked.

    We figured we could eventually get the ImpersonateUser to work but this is much cleaner because we aren’t having to use unsafe code.  We also don’t need to impersonate.  The user we are passing in the the user we want…so we don’t see why it would need to impersonate.

  10. Hi,

    I am using the above code but I need to connect to reportserver on the same domain(network). The way I did this is I return null from the ImpersonationUser method but now my NetworkCredentials property looks like the following:

         public ICredentials NetworkCredentials


               ///Comment out for basic security

               //// Comment out for basic security



                   CredentialCache cc = new CredentialCache();

                   cc.Add(new Uri(ConfigurationManager.AppSettings["ReportServerEndPoint"]), "Basic", new NetworkCredential(this.Username.ToString(), this.Password.ToString()));

                   return cc;  // Not using NetworkCredentials to authenticate.



    Is this the right way?. Does the user need to be a local user on the machine that has the report server?


  11. Luis says:

    I have  a problem with this, I have some reports that have multiple dropdownlist, when you select one dropdownlist it must refresh another dropdownlist, it works if you navigate to the report with reportmanager, but not with reportviewer, after refreshing one dropdowncontrol I got the same 401 unauthorized error.

    Any help

  12. Leon says:

    I also got the same issue as Trish "Unhandled exception was caught: System.Web.HttpException: An error occurred while attempting to impersonate.  Execution of this request cannot continue".  

    I am not sure whether Trish is using the same way as me, but I just create a seperate application pool and use the local account user to run my application (which only enable user to look at the reports right now).  Then without using the Impersonation, I got the application running.  

    However, I am not sure what is the security impact of running my application by using a local account with much higher level permissions or how much is different than impersonation for security concern, anybody have a good idea?  Thanks.

  13. Asaf says:

    When trying to view the report I am receiving the error:

    The request failed with HTTP status 401: Unauthorized.

    * same user and password works fine on windows application

    Also I have tried Administrator user.

    My code for the report viewer is:

    rvBlackListReport.ProcessingMode = ProcessingMode.Remote;

    rvBlackListReport.ServerReport.ReportServerUrl = new


    rvBlackListReport.ServerReport.ReportPath = "/MyReports/TestReport";

    ReportViewerCredentials rvc = new

    ReportViewerCredentials("TestUser", "TestPassword", "");

    rvBlackListReport.ServerReport.ReportServerCredentials = rvc;



  14. furmangg says:

    I’ve reported a bug regarding using the credentials code seen above… apparently the keepalive code ReportViewer uses doesn’t pay attention to it, so the session in ReportServerTempDB gets dumped after 10 mins instead of being kept alive:

    Please see the workaround I posted there (changing the app pool identity)… and post a workaround yourself if you’ve figured out a better way around this problem.

  15. BradB says:

    For the page navigation problem, page navigation is a postback.  Look at what you are doing in the PageLoad when IsPostBack == true.

  16. Raquel says:

    Hi Russel,

    You just had a training in our site a couple of weeks ago and you gave you C# script for Impersonation but I got the script from the web below.

    My question is, Using the script below How do I clean up the Impersonation?  otherwise Is the user is still logged in using the Impersonated Account?

    Thanks, hope to hear from you.


    Imports Microsoft.Reporting.WebForms

    Imports System.web.Security

    Imports Microsoft.VisualBasic

    Imports System.Net

    Public Class ReportServerCredentials

       Implements IReportServerCredentials

       Private _userName As String

       Private _password As String

       Private _domain As String

       Public Sub New(ByVal userName As String, ByVal password As String, ByVal domain As String)

           _userName = userName

           _password = password

           _domain = domain

       End Sub

       Public ReadOnly Property ImpersonationUser() As System.Security.Principal.WindowsIdentity Implements Microsoft.Reporting.WebForms.IReportServerCredentials.ImpersonationUser


               Return Nothing

           End Get

       End Property

       Public ReadOnly Property NetworkCredentials() As ICredentials Implements Microsoft.Reporting.WebForms.IReportServerCredentials.NetworkCredentials


               Return New NetworkCredential(_userName, _password, _domain)

           End Get

       End Property

       Public Function GetFormsCredentials(ByRef authCookie As System.Net.Cookie, ByRef userName As String, ByRef password As String, ByRef authority As String) As Boolean Implements Microsoft.Reporting.WebForms.IReportServerCredentials.GetFormsCredentials

           userName = _userName

           password = _password

           authority = _domain

           Return Nothing

       End Function

    End Class

  17. Hi Raquel —

    It looks like you’re trying to do two things at the same time here — Get Forms Auth credentials, and then turn around and do Windows Impersonation…Is this correct?

  18. Henry says:


    I had developed a reporting service home page for our intranet . And I deployed this home page at "domain.server1" (for example) and my sql server database  and reporting service is at another server "domain.server2"(for example). on the "domain.server1" , the Authentication methods is Integrated windows authentication. and on the "domain.server2" , with the reportingservice server properites and home folder, in the "permissions" tab, I had add the "domain.server1$" as system user role. so I can view my report via my home page and it works fine. If I remove the  "domain.server1$" from the reporting service, there could be encountered an error "The permissions granted to user ‘domain.server1$’ are insufficient for performing this operation".

    I used

              rService.Credentials = System.Net.CredentialCache.DefaultCredentials;

    in my home page to list the reports. But this function return nothing.I think this must be a problem, so I change this code as

               System.Net.NetworkCredential myCreds = new System.Net.NetworkCredential();

               myCreds.Domain = "domain";

               myCreds.UserName = "UserName";

               myCreds.Password = "Password";

               rService.Credentials = myCreds;

    and add this "UserName" to a local group "group1" on "domain.server2" , and grant this group "group1" to access the reporting service server. It works fine.

    Because I need to access my home page and reporting service as the same Integrated windows authentication.I do not need the user to type in the user name and password again and again. So if they login the window system and then they can access their own home page functions and their groups own report server folders.

    But now , I’m confused how to get the user’s information .I can get the user domain and username by HttpContext,but I can not get the password infomation , even though encrypted.

    Do I can get the user’s password information from the AD or there is another choice for this condition?

    could you give me some suggestion?



  19. Hi Henry — I’m a tiny bit unclear on how you are displaying the report in your homepage (inside an IFrame? Using the Report Viewer control?), but this shouldn’t be too difficult.

    If you modify web.config on your homepage to use Impersonation, then display reports through the Report Viewer control, this should happen:

    1. User hits the homepage, and logs in if necessary (as domainuser1, lets say)

    2. From now on, everything they do happens under this security context.

    3. They run your report through the Report Viewer, and the Report Viewer picks up the credentials of the user (domainuser1) automatically, passing them along to domainserver2, where SSRS lives.

  20. Henry says:


      Thank your for your suggestion.

      I had fixed this issue a few day ago.

      I used a IFrame in my homepage and also use a report viewer control to display my report.

      May be I had not described clearly.:( I don’t want the user type in the password when they hits the homepage, so I integrated the windows authentication. And this security context can not access to SSRS server before.

     I had configurated the domain.server1 as a trusted machine and use the Kerberos authentication and it work fine.

     Anyway, thanks a lot!:)


  21. Mike says:

    Trying to access a remote server with ReportViewer and was getting the 401 error.  I tried your impersonation suggestion below but get the following message:

    "For security reasons DTD is prohibited in this XML document. To enable DTD processing set the ProhibitDtd property on XmlReaderSettings to false and pass the settings into XmlReader.Create method. "  

    I searched the web far and wide but could not find a reasonable solution.  There are no errors in my event log.

    I am using 2 machines on a peer to peer windows network (no domain).

    Any clues?


  22. Aaron says:

    Hi Russch,

    I am unclear on why you need to impersonate a Windows user. The documentation I have read online talks about having the ImpersonationUser return null and instead implement the GetFormsCredentials function.

    Have you implemented forms authentication for ReportViewer using the function GetFormsCredentials() before?

    I am having an awful time getting this set-up. Here is the url for the sample code I downloaded:

    I followed the steps they gave on setting up the report but for some reason I get this error: The request failed with the error message: — <html><head><title>Object moved</title></head><body> <h2>Object moved to <a href="/ReportServer/logon.aspx?ReturnUrl=%2fReportServer%2fReportExecution2005.asmx">here</a>.</h2> </body></html> –.

    I’m sure that I’m close to figuring out this problem but I’m unable to figure out what the missing piece is. Could you please help me out?

  23. Farshid says:

    Use following credential and specify "NTLM"

    CredentialCache cc = new CredentialCache();

                   cc.Add(uri, "NTLM", new NetworkCredential("administrator", "sierra", "dev3.agi"));

                   _reportViewer.ServerReport.ReportServerCredentials.NetworkCredentials = cc;

  24. Doug S says:

    Do you have this code in VB?

    Do you have to do something similar to this in reporting services prior to 2005?

  25. Rich says:

    I was having a problem with one of my Report Servers and could not recall what I did to fix it in the past.  I googled my problem and found this page but I remembered it was much easier than what is presented in this article.  I asked myself why go through all this when you need to properly configure SSRS to fix this issue.  I skimmed through the comments and did not see what I was looking for.  Later it came to me that I needed to create a role for the user. Once I did that on my server it worked fine.

    The problem I was having is that "NT AUTHORITYNETWORK SERVICE" was not trusted to execute a report.  To fix the issue I needed to go to the report server web interface http://<server>/Reports click the "Properties" tab, click the "New Role Assignment" button.  In the "Group or user name:" text box I added "NT AUTHORITYNETWORK SERVICE" and checked the "Browser" Role check box and clicked the "OK" button.

    Hopefully this will help someone out.

  26. Avoiding the ‘401 Unauthorized’ Error when Using the ReportViewer in Your Web Application

  27. Oggi mi sono trovato nella necessità di impersonare un utente per accedere a dei report tramite il ReportViewer

  28. John says:

    Hi there

    Which username and password is passed into the ‘ReportViewerCredentials’ method on your report viewer page? Is it the specific users account info or another account that has to be set up separately. If the latter, where does this account have to be set up?

    I tried the code, passing in my own windows account username and password but just got an access denied error.

    Also, in which web.config file do you set <identity impersonate="true"/> ? The one in your application or the one in the report server virtual directory (as it is in there by default)?

    Many thanks


  29. Shehzad Sheikh says:

    Hi Russch,

    I have been trying to search on Impersonation of through the report viewer control. I read your arctile and it was a help to some extent. I understand that we have implemented  IReportServerCredentials interface. it is working fine when i hard code my username, password and domain while instantiating the class, but what if i have to impersonate dynamically with the logged on user windows credientials so that my code access the report server with the current user’s credentials. For that matter i have failed so far finding a way to get the password for the current user. I can just use the User.Identity property on the page to get username and domain but not the password and hence cannot successfully impersonate the current user. Do you or anybody have any thoughts how can i overcome this problem??

  30. Mridu says:


    I am also facing the problem with the error – — <html><head><title>Object moved</title></head><body> <h2>Object moved to <a href="/ReportServer/logon.aspx?ReturnUrl=%2fReportServer%2fReportExecution2005.asmx">here</a>.</h2> </body></html> –.

    This is quite because in forms authentication, a cookie is required but with the authentication we are providing , the cookie is still not passed along, so that’s the reason SSRS authorization cancel’s out the SOAP call and redirects us back to the ReturnURL.

    I am figuring out the problem but solution is to no avail.

    Please let me know if anyone comes across a solution for the same.

    Thanks in advance.

    • Mridu.
  31. fredarwin says:


    I have a report in rpviewer in remote mode,inside my report i am using drillthrogh subreports and the navigation through it work fine, but, when i am in the subreport and after to choose export or print when i press the go parent button i haver a error:

    Call back drilltroght

    What can i do 4 resolve this issue?

  32. fredarwin says:


    I have a report in rpviewer in remote mode,inside my report i am using drillthrogh subreports and the navigation through it work fine, but, when i am in the subreport and after to choose export or print when i press the go back to the parent report button i haver a error:

    Back Call without drillthrough report.

    I think is the sessionalive problem but how can solve this

  33. KV says:

    I tried with the ImpersonationUser returning null and  public ICredentials NetworkCredentials




                   //return null;  // Not using NetworkCredentials to authenticate.

                  CredentialCache cc = new CredentialCache();

                  cc.Add(new Uri("http://svr-devstation1/reportserver&quot;),"Basic",

                      new NetworkCredential( "kviswanathan", "Pranav0206","Federation"));

                  return cc;  // Not using NetworkCredentials to authenticate.



    i get HTTP 401 not authorized error.

    When i step through, i could see the correct domain,username and password in the ReportServerCredentials.

    Any help is greatly appreciated.



  34. kanch_v says:

    I forgot to mention that i use NT authentication.



  35. Mark says:

    This example doesn’t work with nested master pages. It says:"HTTP status 401: Unauthorized"?

    I am working under Windows XP, SqlServer 2005.

    Help please

  36. Mark says:

    It’s ok now, my domain name was wrong.

    Thank you very much for this solution!!!

  37. BS says:

    Is there any way to give the current user to the report? I can fix it to some user, but it should return user-specific data and thus send the windows user to the server. It works for local IIS to server Reporting Server, but not for server IIS to server Reporting Server. Everyone has the rights to run the report and it works from the reporting server.

  38. Tom says:

    Using info from the support page you linked to, I was able to access the report viewer perfectly when I added this to my web.config

    <identity impersonate="true" userName="accountname" password="password" />

    Using the code

    Label1.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

    I can see I am logged into <machine><user> and it passed in all my parameters correctly.

    However, when I tried using your credentials code, the the page crashes when setting parameters and gives the error:

       * The request failed with HTTP status 401: Unauthorized.

    If I comment that out then the report viewer itself gives the same error. Note that with your code it logs me in as "NT AUTHORITYNETWORK SERVICE" which I have given Browser rights.

    Any clue on what is going wrong here?

  39. danny says:

    ReportServerCredentials is a ReadOnly Property, how can you assign to it ??? I am using WinForms…

  40. Kay says:

    Nice work, do you have a solution for and SQL Server Reporting Services 2008 ?

  41. Kay says:

    Nice work, do you have a solution for  ReportViewer control version and SQL Server Reporting Services 2008?

    I have the same issue as danny, the ReportServerCredentials property is read only.

  42. david longstreth says:

    ( after all this time ).

    Does anyone know how to use the Property ImpersonationUser() As WindowsIdentity to get the current logged on Active Directory account so that I can then pass that credential to the report server?