PowerShell API token refresh best method

What is the best way to add a token refresh, or to just re-call the Connect-TargetSystem function after 2 hours?

I have some sync runs that are running longer than 3 hours and at the 2 hour mark all requests begin failing. I need to review the time and re-run the Connect-TargetSystem when running Get-InforObject in the below example. If I can't just rerun the function somehow, I will need to build the function call into the Get-InforObject function. Though, then I would have to pass all the arguments for that second call into the get-inforObject call which seems inefficient. 

Given the following powershell sync connection:

<?xml version="1.0" encoding="utf-8"?>
<PowershellConnectorDefinition Id="InforHelper" Description="Infor API connector helper" Version="1.0">
<PluginAssemblies/>
<ConnectionParameters>
<ConnectionParameter Name="ClientID" Description="ClientID" />
<ConnectionParameter Name="ClientSecret" Description="ClientSecret" />
<ConnectionParameter Name="Password" Description="Password" />
<ConnectionParameter Name="Username" Description="Username" />
<ConnectionParameter Name="BaseURI" Description="BaseURI" />
<ConnectionParameter Name="tokenUri" Description="tokenUri" />
</ConnectionParameters>
<Initialization>
<PredefinedCommands/>
<CustomCommands>
<CustomCommand Name="Connect-TargetSystem">
<![CDATA[
param(
[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$tokenUri,

[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$Username,

[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$Password,

[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$ClientID,

[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$ClientSecret

)

$headers = @{"Accept" = "application/json"; "Content-Type" = "application/json"}
$body = @{
username=$Username
password=$Password;
'grant_type'='password';
'client_id'=$ClientID;
'client_secret'=$ClientSecret
}

try{$tokens = Invoke-RestMethod -Uri $tokenUri -Method POST -Body $body -UseDefaultCredentials
$logdata = $tokens.access_token;
}
Catch {write-error $_.Exception.Response.GetResponseStream()}
$global:headToken = @{"Authorization" = "Bearer " + $($tokens.access_token)}

$global:inforRoundup = new-object system.data.dataset
]]>
</CustomCommand>
<CustomCommand Name="Disconnect-TargetSystem">
<![CDATA[
Write-Host "BYE"
]]>
</CustomCommand>

<CustomCommand Name="Search-InforObjects">
<![CDATA[
param(

[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$BaseURI,

[parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
[String]$listName,

[parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
[String]$className,

[parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$adlQuery
)

$strEndpoint = "$BaseURI/hcm/soap/classes/$className/lists/$listName"
$strEndpoint += "?_out=json"
If (-not [string]::IsNullOrEmpty($adlQuery)) {
$thisDay = (get-date).addDays(-1).ToString("yyyyMMdd")
$strEndpoint += $($($($("$adlQuery" -replace "_EQUALS_","=") -replace "_AMPERSAND_","&") -replace "_DCOLON_","::") -replace "_TODAY_",$thisDay)
}

try {
$respObject = Invoke-RestMethod -Headers $global:headToken -Uri $strEndpoint
}
Catch {

}
If ($respObject) {
$RetSimple = New-Object System.Data.DataTable ($InforRoundup)
$RetSimple.TableName = $className

foreach ($BOSet in $respObject._fields[1].psobject.properties) {$RetSimple.Columns.Add($(new-Object system.data.DataColumn($($BOSet.name -replace "\.","_"))))}

foreach ($BOSet in $respObject._fields) {
If ($bOSet) {
$NewRow = $RetSimple.NewRow()
foreach ($field in $BOSet.psobject.properties) {
if ([string]::IsNullOrEmpty($field.value)) {
$NewRow[$($field.name -replace "\.","_")] = ""
}
Else {
$NewRow[$($field.name -replace "\.","_")] = $field.value
}
}
$RetSimple.Rows.Add($NewRow)
}
}
If (-not $global:inforRoundup.tables.Contains($className)) {
$global:inforRoundup.tables.add($RetSimple)
}
$RetSimple

}

]]>
</CustomCommand>
<CustomCommand Name="Get-InforObject">
<![CDATA[
param(

[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$BaseURI,

[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$className,

[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$listName,

[parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$keyField,

[parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$adlQuery,

[parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[String]$RecId
)
$strEndpoint = "$BaseURI/hcm/soap/classes/$className/lists/$listName"
$strEndpoint += "?_out=json&_filter=$keyField::$RecId"
If (-not [string]::IsNullOrEmpty($adlQuery)) {
$thisDay = (get-date).addDays(-1).ToString("yyyyMMdd")
$strEndpoint += $($($($("$adlQuery" -replace "_EQUALS_","=") -replace "_AMPERSAND_","&") -replace "_DCOLON_","::") -replace "_TODAY_",$thisDay)
}

try {
$respObject = Invoke-RestMethod -Headers $global:headToken -Uri $strEndpoint
}
Catch {

}
If ($respObject) {
$RetSimple = New-Object System.Data.DataTable ($InforRoundup)
$RetSimple.TableName = $className

foreach ($BOSet in $respObject._fields[1].psobject.properties) {$RetSimple.Columns.Add($(new-Object system.data.DataColumn($($BOSet.name -replace "\.","_"))))}

foreach ($BOSet in $respObject._fields) {
If ($bOSet) {
$NewRow = $RetSimple.NewRow()
foreach ($field in $BOSet.psobject.properties) {
if ([string]::IsNullOrEmpty($field.value)) {
$NewRow[$($field.name -replace "\.","_")] = ""
}
Else {
$NewRow[$($field.name -replace "\.","_")] = $field.value
}
}
$RetSimple.Rows.Add($NewRow)
}
}

$RetSimple

}

]]>
</CustomCommand>

</CustomCommands>
<EnvironmentInitialization>
<Connect>
<CommandSequence>
<Item Command="Connect-TargetSystem" Order="1">
<SetParameter Param="ClientID" Source="ConnectionParameter" Value="ClientID" />
<SetParameter Param="ClientSecret" Source="ConnectionParameter" Value="ClientSecret" />
<SetParameter Param="Username" Source="ConnectionParameter" Value="Username" />
<SetParameter Param="Password" Source="ConnectionParameter" Value="Password" />
<SetParameter Param="tokenUri" Source="ConnectionParameter" Value="tokenUri" />
</Item>
</CommandSequence>
</Connect>
<Disconnect>
<CommandSequence>
<Item Command="Disconnect-TargetSystem" Order="1"/>
</CommandSequence>
</Disconnect>
</EnvironmentInitialization>
</Initialization>
<Schema>
<Class Name="Supervisor">
<Properties>
<Property Name="ShortDescription" DataType="String" IsDisplay="true">
<ReturnBindings>
<Bind CommandResultOf="Search-InforObjects" Path="ShortDescription"/>
<Bind CommandResultOf="Get-InforObject" Path="ShortDescription"/>
</ReturnBindings>
</Property>
<Property Name="Supervisor" DataType="String" IsUniqueKey="true" IsMandatory="true" AccessConstraint="ReadAndInsertOnly">
<ReturnBindings>
<Bind CommandResultOf="Search-InforObjects" Path="Supervisor"/>
<Bind CommandResultOf="Get-InforObject" Path="Supervisor"/>
</ReturnBindings>
<CommandMappings>
<Map ToCommand="Get-InforObject" Parameter="RecId"/>
</CommandMappings>
</Property>
<Property Name="Description" DataType="String">
<ReturnBindings>
<Bind CommandResultOf="Get-InforObject" Path="Description"/>
</ReturnBindings>
</Property>
<Property Name="Active" DataType="String">
<ReturnBindings>
<Bind CommandResultOf="Search-InforObjects" Path="Active"/>
<Bind CommandResultOf="Get-InforObject" Path="Active"/>
</ReturnBindings>
</Property>
<Property Name="HROrganization" DataType="String">
<ReturnBindings>
<Bind CommandResultOf="Get-InforObject" Path="HROrganization"/>
</ReturnBindings>
</Property>
<Property Name="HROrganizationUnit" DataType="String">
<ReturnBindings>
<Bind CommandResultOf="Get-InforObject" Path="HROrganizationUnit"/>
</ReturnBindings>
</Property>
<Property Name="ParentSupervisor" DataType="String">
<ReferenceTargets>
<ReferenceTarget Class="Supervisor" Property="Supervisor" />
</ReferenceTargets>
<ReturnBindings>
<Bind CommandResultOf="Search-InforObjects" Path="ParentSupervisor"/>
<Bind CommandResultOf="Get-InforObject" Path="ParentSupervisor"/>
</ReturnBindings>
</Property>
<Property Name="Supervisor_HasNoChildren" DataType="String">
<ReturnBindings>
<Bind CommandResultOf="Get-InforObject" Path="Supervisor_HasNoChildren"/>
</ReturnBindings>
</Property>
<Property Name="SupervisorEmployeeName" DataType="String">
<ReturnBindings>
<Bind CommandResultOf="Get-InforObject" Path="SupervisorEmployeeName"/>
</ReturnBindings>
</Property>
<Property Name="SupervisorType" DataType="String">
<ReturnBindings>
<Bind CommandResultOf="Get-InforObject" Path="SupervisorType"/>
</ReturnBindings>
</Property>
<Property Name="FirstAssignmentIsSupervisorWAEmp" DataType="String">
<ReturnBindings>
<Bind CommandResultOf="Get-InforObject" Path="FirstAssignmentIsSupervisorWAEmp"/>
</ReturnBindings>
</Property>
</Properties>
<ReadConfiguration>
<ListingCommand Command="Search-InforObjects">
<SetParameter Param="BaseURI" Source="ConnectionParameter" Value="BaseURI" />
<SetParameter Param="className" Source="FixedValue" Value="Supervisor" />
<SetParameter Param="listName" Source="FixedValue" Value="Supervisors" />
<SetParameter Param="adlQuery" Source="FixedValue" Value="_AMPERSAND__fields_EQUALS_UniqueID,ShortDescription,Supervisor,Active,ParentSupervisor" />
</ListingCommand>
<CommandSequence>
<Item Command="Get-InforObject" Order="2">
<SetParameter Param="BaseURI" Source="ConnectionParameter" Value="BaseURI" />
<SetParameter Param="className" Source="FixedValue" Value="Supervisor" />
<SetParameter Param="listName" Source="FixedValue" Value="Supervisors" />
<SetParameter Param="keyField" Source="FixedValue" Value="Supervisor" />
<SetParameter Param="adlQuery" Source="FixedValue" Value="_AMPERSAND__fields_EQUALS_UniqueID,ShortDescription,Supervisor,Description,Active,HROrganization,HROrganizationUnit,ParentSupervisor,Supervisor_HasNoChildren,SupervisorEmployeeName,SupervisorType,FirstAssignmentIsSupervisorWAEmp" />
</Item>
</CommandSequence>
</ReadConfiguration>
</Class>

</Schema>
</PowershellConnectorDefinition>

  • Why not have a separate function that calculates the need for refresh or not, have it called at the start of each function, and let it handle the session refresh (if its OAuth, you have to use the /refresh and not the /token).