Setting a Windows Cookie with Powershell (using InternetSetcookie in WinInet)

As I’m trying to improve OnedriveMapper, I’ve been looking into methods to avoid using Browser Emulation to authenticate with Office 365.

This wasn’t difficult, but storing the cookie posed a challenge. There are no available methods in Powershell to do so, thus I went searching until I ran into a post on Stackoverflow that shows how to store a cookie using C#

Since Powershell can eat C#, this ended up being my working code to set a persistent OS cookie from Powershell:


$source=@"
using System.Runtime.InteropServices;
using System;
namespace Cookies
{
    public static class setter
    {
        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool InternetSetCookie(string url, string name, string data);

        public static bool SetWinINETCookieString(string url, string name, string data)
        {
            bool res = setter.InternetSetCookie(url, name, data);
            if (!res)
            {
                throw new Exception("Exception setting cookie: Win32 Error code="+Marshal.GetLastWin32Error());
            }else{
                return res;
            }
        }
    }
}
"@

$compilerParameters = New-Object System.CodeDom.Compiler.CompilerParameters
$compilerParameters.CompilerOptions="/unsafe"

Add-Type -TypeDefinition $source -Language CSharp -CompilerParameters $compilerParameters

[DateTime]$dateTime = Get-Date
$dateTime.AddDays(1)
$str = $dateTime.ToString("R")

[Cookies.setter]::SetWinINETCookieString("https://cookieURL","cookieNAME","value;Expires=$str")

edit: don’t use the Get-Hotfix PS command before you run above code, for some reason it breaks things.

O365Undo updated for O365 Groups

O365Undo is a great script you can use to roll back actions of your user(s) in Office 365. Most likely, actions your user wasn’t aware of but were actually done by a CryptoLocker or by RansomWare.

These nasty virusses can cause havoc on your mapped or synced Sharepoint Online or Onedrive for Business libraries in the form of file level encryption or file name obfuscation.

This new version also protects Office 365 Groups.

Read more or download the script

Using Powershell to check a user’s tenant logon setting in Office 365 (without logging in)

I was interested in being able to see, for any given email, what type of authentication Microsoft requires for that user. This could be Office 365 (Azure AD) native, ADFS, etc.

Powershell can easily help you out:

Add-Type -AssemblyName System.Web
$uid = "YOUR EMAIL ADDRESS"
$uidEnc = [System.Web.HttpUtility]::HtmlEncode($uid)
$res = Invoke-WebRequest -Uri https://login.microsoftonline.com -SessionVariable cookies -Method Get -UseBasicParsing
$stsRequest = ($res.InputFields | where {$_.Name -eq "ctx"}).Value
$flowToken = ($res.InputFields | where {$_.Name -eq "flowToken"}).Value
$canary = ($res.InputFields | where {$_.Name -eq "canary"}).Value
$res = Invoke-WebRequest -Uri "https://login.microsoftonline.com/common/userrealm?user=$uidEnc&api-version=2.1&stsRequest=$stsRequest&checkForMicrosoftAccount=false" -WebSession $cookies -Method GET -UseBasicParsing

The response will contain a redirect to another authentication provider (ADFS) or Azure AD Native. This is an example JSON response:

{"NameSpaceType":"Managed","Login":"mymailaddress@domain.nl","DomainName":"lieben.nu","FederationBrandName":"Lieben Consultancy","TenantBrandingInfo":null,"cloud_instance_name":"microsoftonline.com"}

If you also wish to include Microsoft accounts, set the checkForMicrosoftAccount parameter in the second request to true

AzureAD Connect SSO
If you’re using AzureAD Connect SSO, you can use the above to check if this is correctly set in Office 365. The JSON response will contain a propert is_dsso_enabled, which will be set to True

Prevent duplicate or hanging Powershell processes that run from the Task Scheduler

Many automated processes we write in Powershell are scheduled on a server somewhere and run periodically.
Sometimes, the script may hang. In my experience, the task scheduler setting “Stop the task if it runs longer than:” rarely works properly when a Powershell script hangs. It either thinks it stopped the task, or is unable to.

This can result in memory hogging runaway Powershell processes, locked log files, concurrent user issues, etc etc.

If you want to prevent that from happening, add this function to your script and call it once at the start of your script. It will kill any Powershell process with the same script name that does not match the running process’s Process ID. It requires Powershell 3+:


function preventDoubleSchedule{
    try{
        $scriptFileName = split-path $MyInvocation.PSCommandPath -Leaf
    }catch{$scriptFileName = $Null}
    try{
        [Array]$psProcesses = @(Get-WmiObject Win32_Process -Filter "name like '%Powershell.exe%' and handle != '$pid'" | where {$_})
    }catch{
        Throw
    }
    if($psProcesses.Count -gt 0){
        foreach($psProcess in $psProcesses){
            if($psProcess.CommandLine -like "*$scriptFileName*" -and $scriptFileName){
                ##we've found a Powershell process that is running this script, but does not have the same process ID, lets try to kill it
                try{
                    Stop-Process -Id $psProcess.Handle -Force -Confirm:$False
                }catch{
                    Throw
                }
            }
        }
    }
}

O365GroupSync v0.50 available!

Version 0.50 is out, changes:

  • fixed a bug in using the wrong smtp prefix when searching
  • removed log spam about skipped inactive accounts
  • set managedBy after creating all groups
  • extra mail parameters to allow configuration of WHEN emails are sent (e.g. only in case of errors)
  • send error mail when log file is locked
  • reconnect to ExO each caching action
  • overwrite instead of add primary smtp
  • set mailNickName and legacyExchangeDN values when creating AD group so the group isn’t invisible in the legacy exchange console

Get it here

OnedriveMapper v2.53 released!

Version 2.53 of OneDriveMapper has been released!

  • Updated to work with changes in MS’s backend
  • Better handling of AzureAD SSO Preview

This morning I received reports that the O4B mapping was failing, but SpO ones weren’t. Digging into this I noticed that if I attempted to map the moment the script hits O4B, it did work, so OnedriveMapper now handles the timing a bit different to work with the changes Microsoft made on their end.

Get the new version here

OnedriveMapper v2.51, AADConnect SSO workaround

Hi all, I’ve just posted v2.51, which has a workaround for the Preview Version of SSO in Azure AD Connect that some people have reported not working with OnedriveMapper.

It took me a while to reproduce the issue, but v2.51 now works with Azure AD Connect SSO as long as you do not configure the 2 intranet URL’s through GPO. OnedriveMapper will handle the SSO sites in your local intranet for you, and will still prompt the user for a password once and then cache it.

I’ve got a call with Microsoft to assist on why AADConnect SSO does not generate a persistent cookie, so full compatibility may come in the future.

Changelog:

  • detect and log OS and IE version, only check for relevant KB if necessary
  • semi-compatible with Azure AD Connect SSO (bypass)

Get it here

OnedriveMapper v2.50 released!

Version 2.50 of OneDriveMapper has been released!

  • Less ‘in your face’ progress display
  • timestamped logging
  • automatically prevent IE firstrun wizard from making the script hang
  • Powershell 2 friendly version check
  • also do SSO attempt at userlookupmode 1 and 2 if offered
  • Log errors if AADConnect Preview SSO is set

Get the new version here