0

I have implemented the custom security on my reporting services 2016 and it displays the login page once the URL for reporting services is typed on browser URL bar (either reports or reportserver)

I am using the following code to pass the Credentials when i use the code WITHOUT my security extension it works and looks like this

ICredentials _executionCredentials;

CredentialCache myCache = new CredentialCache();
Uri reportServerUri = new Uri(ReportServerUrl);
myCache.Add(new Uri(reportServerUri.GetLeftPart(UriPartial.Authority)),
                 "NTLM", new NetworkCredential(MyUserName, MyUserPassword));
_executionCredentials = myCache;

when i use the code WITH the security extension it doesnt work and looks like this

ICredentials _executionCredentials;
CredentialCache myCache = new CredentialCache();
Uri reportServerUri = new Uri(ReportServerUrl);

myCache.Add(new Uri(reportServerUri.GetLeftPart(UriPartial.Authority)),
                "Basic", new NetworkCredential(MyUserName, MyUserPassword));
_executionCredentials = myCache;

and i get an Exception saying "The response to this POST request did not contain a 'location' header. That is not supported by this client." when i actually use this credentials

Is "basic" the wrong option ?

Have anyone done this ?


Update 1 Well it turns out that my SSRS is expecting an Authorisation cookie which i am unable to pass (according to fiddler, there is no cookie)

HttpWebRequest request;
request = (HttpWebRequest)HttpWebRequest.Create("http://mylocalcomputerwithRS/Reports_SQL2016/api/v1.0");
CookieContainer cookieJar = new CookieContainer();
request.CookieContainer = cookieJar;
Cookie authCookie =  new Cookie("sqlAuthCookie", "username:password");
authCookie.Domain = ".mydomain.mylocalcomputerwithRS";
if (authCookie != null)
    request.CookieContainer.Add(authCookie);
request.Timeout = -1;

HttpWebResponse myHttpWebResponse = (HttpWebResponse)request.GetResponse();
  • Is that users credentials defined in your custom security repository? – Ross Bush Apr 17 '18 at 17:11
  • the credential are on Db securely stored – user3292410 Apr 18 '18 at 10:44
  • I don't think the response above is coming indication of a problem with anything related to authentication or authorization within ssrs. This is more of a rest api protocol problem. This article suggests adding the location header programmatically. -->https://d-fens.ch/2014/08/08/webapi-and-the-response-to-this-post-request-did-not-contain-a-location-header-that-is-not-supported-by-this-client/ – Ross Bush Apr 18 '18 at 12:25
  • I saw thanks , I tried to implemented, but the location property is readonly. – user3292410 Apr 19 '18 at 13:36
  • I have checked the communication with fiddler , and it does required a cookie to pass the authentication. so now I need to learn how to pass it ... – user3292410 Apr 19 '18 at 13:39
  • Added an update – user3292410 Apr 19 '18 at 16:27
  • I am a bit confused. Are you interfacing with the rs web portion?I am not sure why an api would require a client to supply this cookie. It looks a lot like a forms ticket issued during a response from an app using forms security, such as the reports manager or rs web. – Ross Bush Apr 19 '18 at 16:54
  • Yes Ross that is precisely what i want to interface with all the API rest from Reporting services 2016, to create datasources and upload reports, but to do that, i first need to authenticate with a cookie :( – user3292410 Apr 20 '18 at 11:02

2 Answers2

2

That's how I got it (SSRS 2017; api v2.0). I took the value for the "body" from Fiddler:

    var handler = new HttpClientHandler();
    var httpClient = new HttpClient(handler);

    Assert.AreEqual(0, handler.CookieContainer.Count);

    // Create a login form
    var body = new Dictionary<string, string>()
    {
        {"__VIEWSTATE", "9cZYKBmLKR3EbLhJvaf1JI7LZ4cc0244Hpcpzt/2MsDy+ccwNaw9hswvzwepb4InPxvrgR0FJ/TpZWbLZGNEIuD/dmmqy0qXNm5/6VMn9eV+SBbdAhSupsEhmbuTTrg7sjtRig==" },
        {"__VIEWSTATEGENERATOR", "480DEEB3"},
        { "__EVENTVALIDATION", "IS0IRlkvSTMCa7SfuB/lrh9f5TpFSB2wpqBZGzpoT/aKGsI5zSjooNO9QvxIh+QIvcbPFDOqTD7R0VDOH8CWkX4T4Fs29e6IL92qPik3euu5QpidxJB14t/WSqBywIMEWXy6lfVTsTWAkkMJRX8DX7OwIhSWZAEbWZUyJRSpXZK5k74jl4x85OZJ19hyfE9qwatskQ=="},
        {"txtUserName",  "User"},
        {"txtPassword", "1"},
        {"btnLogin","Войти"}
    };
    var content = new FormUrlEncodedContent(body);

    // POST to login form
    var response = await httpClient.PostAsync("http://127.0.0.1:777/ReportServer/Logon.aspx", content);

    // Check the cookies created by server
    Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
    var cookies = handler.CookieContainer.GetCookies(new Uri("http://127.0.0.1:777/ReportServer"));
    Assert.AreEqual("sqlAuthCookie", cookies[0].Name);

    // Make new request to secured resource
    var myresponse = await httpClient.GetAsync("http://127.0.0.1:777/Reports/api/v2.0/Folders");

    var stringContent = await myresponse.Content.ReadAsStringAsync();
    Console.Write(stringContent);
  • Spasibo Dimitri! it did work! , now... that leads me to the next question, how to implement this properly, as the view state info is related to each instance of the reporting services .. is i want to log in to different servers, but that is another question... This you have answer – user3292410 Jul 17 '18 at 16:25
0

As an alternative you can customize SSRS Custom Security Sample quite a bit.

I forked Microsoft's Custom Security Sample to do just what you are describing (needed the functionality at a client long ago and reimplemented as a shareable project on GitHub).

https://github.com/sonrai-LLC/ExtRSAuth

I created a YouTube walkthrough as well to show how one can extend and debug SSRS security with this ExtRSAuth SSRS security assembly https://www.youtube.com/watch?v=sJUwOrcD90I

TL; DR; https://www.youtube.com/watch?v=BRO_1_WRsKI -- just bypass the Microsoft example auth check in Login.aspx.cs and put your auth in Page_Load() or Page_Init() event of Login.aspx.cs- wherever you want to perform some custom logging check- and then immediately redirect auth'd user to their requested URI.

cfitzg
  • 43
  • 10