functions/core/Update-MgaAccessToken.ps1
function Update-MgaAccessToken { <# .SYNOPSIS Updates an existing access token .DESCRIPTION Updates an existing access token for contacting the specified application endpoint as long as the token is still valid. Otherwise, a new access is called through New-MgaAccessToken. .PARAMETER Token The token object to renew. .PARAMETER Register Registers the renewed token, so all subsequent calls to Exchange Online reuse it by default. .PARAMETER PassThru Outputs the token to the console, even when the register switch is set .EXAMPLE PS C:\> New-MgaAccessToken -MailboxName 'max.musterman@contoso.com' Registers an application to run under 'max.mustermann@contoso.com'. Requires an interactive session with a user handling the web UI. .EXAMPLE PS C:\> New-MgaAccessToken -MailboxName 'max.musterman@contoso.com' -Credential $cred Generates a token to a session as max.mustermann@contoso.com under the credentials specified in $cred. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding(DefaultParameterSetName="Default")] param ( [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] #[MSGraph.Core.AzureAccessToken] $Token, [Parameter(ParameterSetName='Register')] [switch] $Register, [Parameter(ParameterSetName='Register')] [switch] $PassThru ) begin { } process { if (-not $Token) { $Token = $script:msgraph_Token $Register = $true } if (-not $Token) { Stop-PSFFunction -Message "Not connected! Use New-MgaAccessToken to create a Token and either register it or specifs it." -EnableException $true -Category AuthenticationError -Cmdlet $PSCmdlet } if (-not $Token.IsValid) { Write-PSFMessage -Level Warning -Message "Token lifetime already expired and can't be newed. New authentication is required. Calling New-MgaAccessToken..." -Tag "Authorization" $paramsNewToken = @{ ClientId = $Token.AccessTokenInfo.ApplicationID.Guid RedirectUrl = $Token.AppRedirectUrl } if ($Token.Credential) { $paramsNewToken.Add("Credential", $Token.Credential ) } if ($Register -or ($script:msgraph_Token.AccessTokenInfo.Payload -eq $Token.AccessTokenInfo.Payload) ) { $paramsNewToken.Add("Register", $true) } $resultObject = New-MgaAccessToken -PassThru @paramsNewToken if ($PassThru) { return $resultObject } else { return } } $resourceUri = "https://graph.microsoft.com" $endpointUri = "https://login.windows.net/common/oauth2" $endpointUriToken = "$($endpointUri)/token " $baselineTimestamp = [datetime]"1970-01-01Z00:00:00" $httpClient = New-HttpClient $queryHash = [ordered]@{ grant_type = "refresh_token" resource = [System.Web.HttpUtility]::UrlEncode($resourceUri) client_id = $Token.ClientId.Guid refresh_token = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Token.RefreshToken)) } $authorizationPostRequest = Convert-UriQueryFromHash $queryHash -NoQuestionmark $content = New-Object System.Net.Http.StringContent($authorizationPostRequest, [System.Text.Encoding]::UTF8, "application/x-www-form-urlencoded") $clientResult = $httpClient.PostAsync([Uri]$endpointUriToken, $content) if ($clientResult.Result.StatusCode -eq [System.Net.HttpStatusCode]"OK") { Write-PSFMessage -Level Verbose -Message "AccessToken renewal successful. $($clientResult.Result.StatusCode.value__) ($($clientResult.Result.StatusCode)) $($clientResult.Result.ReasonPhrase)" -Tag "Authorization" } else { Stop-PSFFunction -Message "Failed to renew AccessToken! $($clientResult.Result.StatusCode.value__) ($($clientResult.Result.StatusCode)) $($clientResult.Result.ReasonPhrase)" -Tag "Authorization" -EnableException $true } $jsonResponse = ConvertFrom-Json -InputObject $clientResult.Result.Content.ReadAsStringAsync().Result # Build output object $resultObject = New-Object MSGraph.Core.AzureAccessToken -Property @{ TokenType = $jsonResponse.token_type Scope = $jsonResponse.scope -split " " ValidUntilUtc = $baselineTimestamp.AddSeconds($jsonResponse.expires_on).ToUniversalTime() ValidFromUtc = $baselineTimestamp.AddSeconds($jsonResponse.not_before).ToUniversalTime() ValidUntil = New-Object DateTime($baselineTimestamp.AddSeconds($jsonResponse.expires_on).Ticks) ValidFrom = New-Object DateTime($baselineTimestamp.AddSeconds($jsonResponse.not_before).Ticks) AccessToken = $null RefreshToken = $null IDToken = $null Credential = $Token.Credential ClientId = $Token.ClientId.Guid Resource = $Token.Resource.ToString() AppRedirectUrl = $Token.AppRedirectUrl.ToString() } # Insert token data into output object. done as secure string to prevent text output of tokens if ($jsonResponse.psobject.Properties.name -contains "refresh_token") { $resultObject.RefreshToken = ($jsonResponse.refresh_token | ConvertTo-SecureString -AsPlainText -Force) } if ($jsonResponse.psobject.Properties.name -contains "id_token") { $resultObject.IDToken = ($jsonResponse.id_token | ConvertTo-SecureString -AsPlainText -Force) } if ($jsonResponse.psobject.Properties.name -contains "access_token") { $resultObject.AccessToken = ($jsonResponse.access_token | ConvertTo-SecureString -AsPlainText -Force) $resultObject.AccessTokenInfo = ConvertFrom-JWTtoken -Token $jsonResponse.access_token } if ((Get-Date).IsDaylightSavingTime()) { $resultObject.ValidUntil = $resultObject.ValidUntil.AddHours(1) $resultObject.ValidFrom = $resultObject.ValidFrom.AddHours(1) } if ($resultObject.IsValid) { if ($Register) { $script:msgraph_Token = $resultObject if ($PassThru) { $resultObject } } else { $resultObject } } else { Stop-PSFFunction -Message "Token failure. Acquired token is not valid" -EnableException -Tag "Authorization" } } end { } } |