Nested ForEach Log In/Log Out - Successful First Log In, Failed Second Log In

Question

Hello, I have a system which requires impersonating (logging in as) a user, in order to create shortcuts for them. I have a script which will log a user in with the impersonation password, read a CSV storing the UserID and shortcuts, create the shortcuts and log them out. I need to scale this script up, so it will log in the first user, create shortcuts, log out and automatically proceed to the next user. I have updated my existing script to:

  1. Extract the distinct users from the CSV and passing it to $user

  2. Taken the majority of my original script and enclosed it within a ForEach loop to process each $user

  3. Added a clause to the second loop to only process shortcuts where the logged in user matches the user value in the CSV

  4. Added Write-Host statements to return the $user and where it is in the script i.e. signing in, signing out, executing the main function etc.

My sample CSV contains 2 users with 2 rows each: WALTEAND is first with 2 shortcuts and LIET is second with 2 shortcuts. WALTEAND's shortcuts are successfully created, but LIET's aren't:

Successfully created 793048 in WALTEAND's My Favorites
Successfully created 793057 in WALTEAND's My Favorites
WALTEAND SIGN OUT successful
WALTEAND Executing SIGNOUT FUNCTION
WALTEAND Executing MAIN FUNCTION

LIET SIGN IN unsuccessful, exiting
400- BAD REQUEST

To eliminate an issue with the LIET account, I reorder the CSV putting LIET's shortcuts first - they're processed successfully and WALTEAND' are not:

Successfully created 914861 in LIET's My Favorites
Successfully created 914902 in LIET's My Favorites
LIET SIGN OUT successful
LIET Executing SIGNOUT FUNCTION
LIET Executing MAIN FUNCTION

WALTEAND SIGN IN unsuccessful, exiting
400- BAD REQUEST

The first sign in and sign out is successful, but the second sign in fails. I suspect it's a problem with the order of events within the loops. If anyone could offer guidance on where I'm going wrong, it'd be greatly appreciated.

$header = @{
    "Accept" = "*/*";
    "Content-Type" = "application/x-www-form-urlencoded"
}

#Full CSV path
$csvfile = 'C:\Scripts\Shortcuts-Create.csv'

$csv = Import-Csv -Path $csvfile

#Extract distinct users from CSV
$UniqueUsers = Import-Csv -Path $csvfile -Header "LIBRARY","USERID","TARGETID","SHORTCUTNAME","WSTYPE" | Select-Object -Skip 1 -ExpandProperty UserID -Unique

#$UniqueUsers # << Skips header and correctly displays distinct users

ForEach ($user in $UniqueUsers) {

$server = 'ln.internal.com'

# Store the input variables for signing in.
$username = $user
$password = '<ImpersonationPasswordHere>'

function SignIn {
    try {
        $parameters = @{
            "username"  = $username
            "password" = $password
            "grant_type" = "password"
            "client_id" = $client_id
            "client_secret" = $client_secret
            "scope" = "admin"
        }

        # Send the 'POST' request to the server and store the response in a variable.
        $response = Invoke-RestMethod -Method Post -Uri "https://$server/auth/oauth2/token" -Header $header -Body $parameters

        # Retrieve the authorization token if present.
        $x_auth_token = $response.$("access_token")

        return $x_auth_token

        Write-Host -Message "$user SIGN IN successful, exiting"

    }
    catch {
        Write-Host -Message "Sign in unsuccessful, exiting"
        Write-Host -Message "$user SIGN IN unsuccessful, exiting"

        if ($_.Exception.Response)
        {
            # HTTP error response (server response)
            Write-Host -Message "$($_.Exception.Response.StatusCode.value__)- $($_.Exception.Response.StatusDescription)"
        }
        else
        {
            # Other exceptions (e.g., unable to locate remote server)
            Write-Host -Message "$($_.ToString())"
        }

        exit
    }
}

function SignOut {
    try {
        $response = Invoke-RestMethod -Method Get -Uri "https://$server/auth/logout" -Header $header
        Write-Host -Message "Sign out successful"
        Write-Host -Message "$user SIGN OUT successful"
    }
    catch {
        Write-Host -Message "Sign out unsuccessful, exiting"
        Write-Host -Message "$user SIGN OUT unsuccessful, exiting"

        if ($_.Exception.Response)
        {
            # HTTP error response (server response)
            Write-Host -Message "$($_.Exception.Response.StatusCode.value__)- $($_.Exception.Response.StatusDescription)"
        }
        else
        {
            # Other exceptions (e.g., unable to locate remote server)
            Write-Host -Message "$($_.ToString())"
        }

        exit
    }
}

function GetCustomerID {
    try {
        $response = Invoke-RestMethod -Method Get -Uri "https://$server/api" -Header $header
        $customerId = $response.data.user.customer_id

        return $customerId
    }
    catch {
        Write-Host -Message "API call unsuccessful, exiting"

        if ($_.Exception.Response)
        {
            # HTTP error response (server response)
            Write-Host -Message "$($_.Exception.Response.StatusCode.value__)- $($_.Exception.Response.StatusDescription)"
        }
        else
        {
            # Other exceptions (e.g., unable to locate remote server)
            Write-Host -Message "$($_.ToString())"
        }

        exit
    }
}

function Main {
    $XAuthToken = SignIn
    $header["X-Auth-Token"] = $XAuthToken
    $header["Content-Type"] = "application/json"
    $customer_id = GetCustomerID

$csv = Import-Csv -Path $csvfile

$csv | ForEach-Object {

if($user -eq $_.USERID) {
    
    # CSV variables
    $libraryId = $_.LIBRARY
    $userId    = $_.USERID
    $target_id = $_.TARGETID
    $name      = $_.SHORTCUTNAME
    $wstype    = $_.WSTYPE
    
    # Specify Payload/Body
    $body = 
                @{
                    "id" = $target_id
                    "name" = $name + " " + (Get-Date -Format 'dd/MM/yy HH:mm')
                    "wstype" = $wstype
                  } 

        try {
                $resource = "https://$server/api/v2/customers/$customer_id/libraries/$libraryId/my-favorites/shortcuts"
                Write-Host ""
                Write-Host "API Call: POST $resource"
                Write-Host ""

                LogWrite "API Call: POST $resource" "Log"

                # Send the 'POST' request to the server and store the response in a variable.
                $response = Invoke-RestMethod -Method Post -Uri "$resource" -Headers $header -Body ($body|ConvertTo-Json) #-ContentType "application/json; charset=utf-8"

                LogWrite "$library,$userid,$target_id,$name,SUCCESS" "Result"
                
                Write-Host ("Successfully created $target_id in $userid" + "'s My Favorites")
                Write-Host ""
              }
        catch {

                if ($_.Exception.Response)
                {
                    $err = $Error[0]
                    $pattern = "code_message`": `"(.*?)`","                    
                    $result = [regex]::match($err, $pattern).Groups[1].Value

                    $errMessage = "Error: "+$_.Exception.Response.StatusCode.value__ +" - " + $_.Exception.Response.StatusDescription + " - " +$result
                    
                    LogWrite "$library,$userid,$target_id,$name,$errMessage" "Result"
                }
                else
                {
                    $errMessage = $_.ToString()
                    LogWrite "$library,$userid,$target_id,$name$errMessage" "Result"
                }
              }
    }

}

SignOut

Write-Host -Message "$user Executing SIGNOUT FUNCTION"

}

Main

Write-Host -Message "$user Executing MAIN FUNCTION"

}

Posted Jun 23, 2026, 10:23 AM UTC

19
Loading comments…