Private/Authentication/Curanet/Get-CuranetAccessToken.ps1
function Get-CuranetAccessToken { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateSet("3370", "3850")] [string]$Account, [Parameter()] [switch]$Force ) begin { try { if (!$script:CuranetCredentials -or $script:CuranetCredentials.Account -ne $Account) { $script:CuranetCredentials = Get-CuranetCredentials -Account $Account } # Define account-specific scopes $accountScopes = @{ '3850' = 'customers orders subscriptions invoicing microsoft365 microsoft365backup' '3370' = 'dns' } # Define OAuth endpoint $tokenEndpoint = 'https://apiauth.dk.team.blue/realms/Curanet/protocol/openid-connect/token' } catch { Write-ModuleLog -Message "Failed to get Curanet credentials" -Level Error -Component 'CuranetAccessToken' -ErrorRecord $_ throw [CuranetTokenOperationException]::new( 'Initialization', 'Failed to get Curanet credentials', $_ ) } } process { try { $cacheKey = "Curanet_$Account" $now = Get-Date # Set refresh threshold to 1 minute before expiration (tokens valid for 5 minutes) $refreshThreshold = $now.AddMinutes(4) # Check cache for valid token if (!$Force -and $script:TokenCache.ContainsKey($cacheKey)) { $cachedToken = $script:TokenCache[$cacheKey] # Token is still valid if ($cachedToken.ExpirationDateTime -gt $refreshThreshold) { Write-ModuleLog -Message "Using cached token for $cacheKey" -Level Verbose -Component 'CuranetAccessToken' return $cachedToken } } Write-ModuleLog -Message "Getting new token for $cacheKey" -Level Verbose -Component 'CuranetAccessToken' # Prepare token request try { $body = @{ grant_type = "client_credentials" client_id = $script:CuranetCredentials.ClientId client_secret = $script:CuranetCredentials.ClientSecret scope = $accountScopes[$Account] } $response = Invoke-RestMethod -Uri $tokenEndpoint ` -Method POST ` -Body $body ` -ContentType 'application/x-www-form-urlencoded' # Create token object with formatted Authorization header value $token = [PSCustomObject]@{ AccessToken = $response.access_token AuthorizationHeader = "bearer $($response.access_token)" TokenType = $response.token_type ExpirationDateTime = (Get-Date).AddSeconds(300) # 5 minutes Scope = $response.scope Account = $Account } } catch { $detailedError = switch -Regex ($_.Exception.Message) { 'invalid_client' { 'Invalid client credentials' } 'invalid_scope' { 'Invalid scope requested' } 'invalid_request' { 'Malformed request' } default { $_.Exception.Message } } Write-ModuleLog -Message "Failed to acquire Curanet token: $detailedError" -Level Error -Component 'CuranetAccessToken' -ErrorRecord $_ throw [CuranetTokenOperationException]::new( 'TokenAcquisition', "Failed to acquire Curanet token: $detailedError", $_ ) } # Manage cache try { if ($script:TokenCache.Count -ge $script:TokenCacheConfig.MaxSize) { $oldestTokens = $script:TokenCache.GetEnumerator() | Sort-Object { $_.Value.ExpirationDateTime } | Select-Object -First ($script:TokenCache.Count - $script:TokenCacheConfig.MaxSize + 1) foreach ($oldToken in $oldestTokens) { $script:TokenCache.Remove($oldToken.Key) } } $script:TokenCache[$cacheKey] = $token Save-TokenCache } catch { Write-ModuleLog -Message "Failed to manage token cache" -Level Error -Component 'CuranetAccessToken' -ErrorRecord $_ } return $token } catch [CuranetTokenOperationException] { throw } catch { Write-ModuleLog -Message "An unexpected error occurred during token operation" -Level Error -Component 'CuranetAccessToken' -ErrorRecord $_ throw [CuranetTokenOperationException]::new( 'Unknown', 'An unexpected error occurred during token operation', $_ ) } } } |