10

I am creating an windows forms app, where I have a webbrowser control.

After user logs in with the webbrowser, I want to log in also with same account with Microsoft.Http.HttpClient or HttpWebRequest or similar, it should be similar to cURL from PHP.

Problem is that the webpage allows only single sign on per account and if I sign with HttpClient, it will kick the webbrowser out.

What I want to know, if it is possible to hijack webbrowser session or get the cookies and use it in my HttpClient or similar api.

I can use webbrowser.Cookie to get some data, but how to push it to HttpClient?

Is that kind of thing even possible, that I can just take the cookies and use the same session? If so, how?

John Saunders
  • 157,405
  • 24
  • 229
  • 388
Jaanus
  • 15,013
  • 43
  • 137
  • 193
  • If the cookies are HttpOnly cookies then the webbrowser will not store them. See [IEGetProtectedModeCookie](https://msdn.microsoft.com/en-us/library/cc196998(v=vs.85).aspx) – Jason Harrison Apr 13 '16 at 18:31

4 Answers4

18

Got help from here:

Is it possible to transfer authentication from Webbrowser to WebRequest

Alkampfer posted solution. This is exactly what I needed and it worked.

This solution also takes Http only cookies.

You can call the GetUriCookieContainer method that returns you a CookieContainer that can be used for subsequent call with WebRequest object.

[DllImport("wininet.dll", SetLastError = true)]
    public static extern bool InternetGetCookieEx(
        string url, 
        string cookieName, 
        StringBuilder cookieData, 
        ref int size,
        Int32  dwFlags,
        IntPtr  lpReserved);

    private const Int32 InternetCookieHttponly = 0x2000;

/// <summary>
/// Gets the URI cookie container.
/// </summary>
/// <param name="uri">The URI.</param>
/// <returns></returns>
public static CookieContainer GetUriCookieContainer(Uri uri)
{
    CookieContainer cookies = null;
    // Determine the size of the cookie
    int datasize = 8192 * 16;
    StringBuilder cookieData = new StringBuilder(datasize);
    if (!InternetGetCookieEx(uri.ToString(), null, cookieData, ref datasize, InternetCookieHttponly, IntPtr.Zero))
    {
        if (datasize < 0)
            return null;
        // Allocate stringbuilder large enough to hold the cookie
        cookieData = new StringBuilder(datasize);
        if (!InternetGetCookieEx(
            uri.ToString(),
            null, cookieData, 
            ref datasize, 
            InternetCookieHttponly, 
            IntPtr.Zero))
            return null;
    }
    if (cookieData.Length > 0)
    {
        cookies = new CookieContainer();
        cookies.SetCookies(uri, cookieData.ToString().Replace(';', ','));
    }
    return cookies;
}
Community
  • 1
  • 1
Jaanus
  • 15,013
  • 43
  • 137
  • 193
4

You can, but it's a bit tricky. Use the InternetSetCookie call together with a CookieContainer from HttpWebRequest.

Here's the method: http://msdn.microsoft.com/en-us/library/windows/desktop/aa385107(v=vs.85).aspx

and here's an example on how to set it: http://social.msdn.microsoft.com/Forums/en-SG/csharpgeneral/thread/76a38eee-3ef6-4993-a54d-3fecc4eb6cff

ThomasArdal
  • 4,314
  • 4
  • 22
  • 50
  • Hmm I am getting the cookies like this: http://stackoverflow.com/questions/650536/c-sharp-webrequest-using-webbrowser-cookie , the second answer there , and setting to HttpWebRequest, but it isn't working, account isn't logged in. – Jaanus Feb 24 '13 at 11:07
  • Are you setting your own instance of the CookieContainer on the HttpWebRequest? This container should contain the cookie after doing the http request. – ThomasArdal Feb 25 '13 at 17:53
  • Ah sorry didn't see that you already solved the issue :) – ThomasArdal Feb 25 '13 at 17:54
  • @ThomasArdal, aren't cookies local to each browser and not per PC? – Old Geezer Jul 27 '17 at 09:30
  • @old-geezer Sorry, but don't remember. – ThomasArdal Jul 31 '17 at 06:53
1

I think you might be stretching the technologies a little bit too far. The webbrowser control in windows forms are usually designed to give you basic html rendering from local files or internet, but it shouldn't be used to replace a full-fledge web browser.

If you want to authenticate against a SSO provider, then you have to use the right libraries, in this case from Windows Identitity Foundation, with Microsoft.IdentityModel you will get claims authentication mechanisms to handle the claims from your SSO provider. Cookies cannot be shared across applications, in fact some new web technologies are designed just to avoid that, so in my opinion try to use WIF instead of a webbrowser control.

Hope it helps,

Jorge Alvarado
  • 2,554
  • 19
  • 32
  • 1
    I don't think its is `SSO provider`, they just have somekind of javascript thing or similar that blocks two connections to account in same time. – Jaanus Feb 24 '13 at 09:41
1

I do it this way

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(address);
var cookies = new CookieContainer();
cookies.SetCookies(webBrowser.Document.Url, 
                          webBrowser.Document.Cookie.Replace(';', ','));
req.CookieContainer = cookies;
ihorbond
  • 1,396
  • 10
  • 20