Private/Test-AzRetirementMonitorToken.ps1
|
function Test-AzRetirementMonitorToken { <# .SYNOPSIS Tests if the stored access token is valid and not expired .DESCRIPTION Decodes the JWT token and checks if it has expired Returns $true if token is valid, $false if expired or invalid #> [CmdletBinding()] param() if (-not $script:AccessToken) { return $false } try { # JWT tokens have 3 parts separated by dots: header.payload.signature $tokenParts = $script:AccessToken -split '\.' if ($tokenParts.Count -ne 3) { Write-Verbose "Token format is invalid" return $false } # Decode the payload (second part) $payload = $tokenParts[1] # Base64URL to Base64 conversion (add padding if needed) $base64 = $payload.Replace('-', '+').Replace('_', '/') switch ($base64.Length % 4) { 0 { break } 2 { $base64 += '==' } 3 { $base64 += '=' } default { Write-Verbose "Invalid Base64URL string length" return $false } } # Decode from Base64 and convert from JSON $payloadJson = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($base64)) $tokenData = $payloadJson | ConvertFrom-Json # Check expiration time (exp claim is in Unix timestamp format) if ($tokenData.exp) { $expirationTime = [DateTimeOffset]::FromUnixTimeSeconds($tokenData.exp) $currentTime = [DateTimeOffset]::UtcNow $expirationBuffer = [TimeSpan]::FromMinutes(5) if ($currentTime -ge $expirationTime.Subtract($expirationBuffer)) { Write-Verbose "Token has expired or is about to expire at $($expirationTime.DateTime) UTC" return $false } Write-Verbose "Token is valid until $($expirationTime.DateTime) UTC" return $true } else { Write-Verbose "Token does not contain expiration claim" return $false } } catch { Write-Verbose "Failed to decode token: $_" return $false } } |