Invoke-WebRequest does not save all Cookies in SessionVariable

[UPDATE 2014-04-08] Thanks to Meir I updated the post as the code was missing the definition for the regular expression. Now I corrected that, so the code should work now. In addition, I found out that the apple web server is not serving ‘Set-Cookie’ header according to RFC so I changed the example from apple.com to google.ch (as we are in Switzerland). Furthermore, keep in mind that even when you request e.g. ‘http://www.google.de’ you might be ending up with cookies from ‘google.com’ (as you get redirected). If in doubt use Fiddler to trace the traffic.
[UPDATE 2014-04-08 END]

When you use the Invoke-WebRequest Cmdlet that is available since PowerShell 3.0 you have the option of saving a “WebSession” object via the “-SessionVariable” parameter. This comes in handy when you load web pages that have session state cookies so you can make subsequent and stay in the same session (via the “-WebSession” parameter).

Unfortunately not all cookies returned by web pages are saved into this variable. You can easily observe this behaviour when comparing the “Set-Cookie” header in the response headers with the cookies saved in the session variable:

$Uri = "http://www.google.ch/"
$r = Invoke-WebRequest -Uri $Uri -Method GET -SessionVariable s;
$s.Cookies.GetCookies($Uri)


Comment    :
CommentUri :
HttpOnly   : False
Discard    : False
Domain     : .google.ch
Expired    : False
Expires    : 07.04.2016 11:00:27
Name       : PREF
Path       : /
Port       :
Secure     : False
TimeStamp  : 08.04.2014 11:00:24
Value      : ID=8433f29e7847bc24:FF=0:TM=1396947627:LM=1396947627:S=Gm0Sn_3dalialh6o
Version    : 0

Comment    :
CommentUri :
HttpOnly   : True
Discard    : False
Domain     : .google.ch
Expired    : False
Expires    : 08.10.2014 11:00:27
Name       : NID
Path       : /
Port       :
Secure     : False
TimeStamp  : 08.04.2014 11:00:24
Value      : 67=B9UgmJrwbNRJQ64FpOnJKNJKiVXtbw81VuwxyQ4bLugd5tX1r3Ocg0ITtWRpI038ru6fJ3qB1ju1f8RcX19Flk-vTZ6T2zcw8BzRehq
             u4cwmbFYza4d8zAuFYupiMzq8
Version    : 0

$SetCookieHeader = $r.Headers.'set-cookie';
$SetCookieHeader
PREF=ID=8433f29e7847bc24:FF=0:TM=1396947627:LM=1396947627:S=Gm0Sn_3dalialh6o; expires=Thu, 07-Apr-2016 09:00:27 GMT; pa
th=/; domain=.google.ch,NID=67=B9UgmJrwbNRJQ64FpOnJKNJKiVXtbw81VuwxyQ4bLugd5tX1r3Ocg0ITtWRpI038ru6fJ3qB1ju1f8RcX19Flk-v
TZ6T2zcw8BzRehqu4cwmbFYza4d8zAuFYupiMzq8; expires=Wed, 08-Oct-2014 09:00:27 GMT; path=/; domain=.google.ch; HttpOnly
[/sourcode]
In order to get all cookie into the SessionVariable you have to extract them from the Set-Cookie header and construct a Cookie header manually similar to this:
function ConvertFrom-SetCookieHeader {
[cmdletbinding()]
Param
(
#Define parameters
[Parameter(Mandatory=$true,Position=0)]
[string] $SetCookieHeader
)
$res = @{}
$res.SetCookieSplit = "([^=]+)=([^;]+);\ ";
$SetCookie = $SetCookieHeader; #$r.Headers.'set-cookie';
$SetCookie = $SetCookie.Replace('Secure,', 'Secure=1;').Replace('Secure;', 'Secure=1;');
$SetCookie = $SetCookie.Replace('HTTPOnly,', 'HTTPOnly=1;').Replace('HTTPOnly;', 'HTTPOnly=1;');
$MatchInfo = Select-String -InputObject $SetCookie $res.SetCookieSplit -AllMatches;
$CookieHeader = "";
foreach($Match in $MatchInfo.Matches) {
if(!$Match.Success) { continue; }
$CookieName = $Match.Groups.Value[1].Trim();
$CookieValue = $Match.Groups.Value[2].Trim();
#$CookiePath = $res.CookiePathDefault;
$CookieDomain = $WebHost;
switch($CookieName) {
"version" { break; }
"path" { break; }
"domain" { break; }
"expires" { break; }
"HTTPOnly" { break; }
"Secure" { break; }
default {
Log-Debug $fn ("'{0}' = '{1}'" -f $CookieName, $CookieValue);
if(!$CookieHeader) {
$CookieHeader = ("{0}={1}" -f $CookieName, $CookieValue);
} else {
$CookieHeader += ("; {0}={1}" -f $CookieName, $CookieValue);
} # if
}
} # switch
} # foreach Match
return $CookieHeader;
} # ConvertFrom-SetCookieHeader

Comments

  1. Meir says:

    What should be set in $res variable? The code does not work.

    • Ronald Rink says:

      Hi Meir, you are right. $res is a hashtable that has a key “SetCookieSplit” that holds the regular expression (“([^=]+)=([^;]+);\ “) for match on the Cookie header. I updated the post. Thanks!

      • Meir says:

        Yes, it works, Thank you for your quick response and your effort to help to others.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: