Private/Api/Request-ApiToken.ps1
|
<#
Copyright (c) 2025-2026 Robert Faddes SPDX-License-Identifier: MPL-2.0 #> function Request-ApiToken { <# .SYNOPSIS Requests a new API access token from the Datto RMM OAuth endpoint. .DESCRIPTION This internal function generates a new access token by making an OAuth password grant request to the Datto RMM API. It handles credential conversion, request construction, and secure cleanup of sensitive data. .PARAMETER Key The API key for authentication. .PARAMETER Secret The API secret as a SecureString. .PARAMETER APIUrl The base API URL for the target platform (e.g., https://pinotage-api.centrastage.net). .PARAMETER Proxy Optional proxy server URI for the request. .PARAMETER ProxyCredential Optional credentials for proxy authentication. .OUTPUTS PSCustomObject with properties: access_token, token_type, expires_in .NOTES This is an internal function used by Connect-DattoRMM. It automatically clears plaintext credentials from memory after use. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string] $Key, [Parameter(Mandatory = $true)] [securestring] $Secret, [Parameter(Mandatory = $true)] [string] $APIUrl, [Parameter(Mandatory = $false)] [uri] $Proxy, [Parameter(Mandatory = $false)] [pscredential] $ProxyCredential ) try { # Convert SecureString to plaintext $AuthSecret = ConvertFrom-SecureStringToPlaintext -SecureString $Secret # Build OAuth token request $PublicCredential = [PSCredential]::new('public-client', ('public' | ConvertTo-SecureString -AsPlainText -Force)) $TokenRequest = @{ Credential = $PublicCredential Uri = "$APIUrl/auth/oauth/token" Method = 'Post' Body = "grant_type=password&username=$Key&password=$AuthSecret" ContentType = 'application/x-www-form-urlencoded' TimeoutSec = $Script:ApiMethodRetry.TimeoutSeconds } switch ($PSBoundParameters.Keys) { 'Proxy' {$TokenRequest.Proxy = $Proxy} 'ProxyCredential' {$TokenRequest.ProxyCredential = $ProxyCredential} } # Make the request $Response = Invoke-RestMethod @TokenRequest Write-Verbose "Successfully authenticated to Datto RMM API." return $Response } catch { throw $_ } finally { # Clear plaintext credentials from memory $AuthSecret = $null } } # SIG # Begin signature block # MIIF+wYJKoZIhvcNAQcCoIIF7DCCBegCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAnLdrrzQ6YzVcL # DHZXgLgE7/dpYTnqSBQXuSZfXQ1gG6CCA04wggNKMIICMqADAgECAhB464iXHfI6 # gksEkDDTyrNsMA0GCSqGSIb3DQEBCwUAMD0xFjAUBgNVBAoMDVJvYmVydCBGYWRk # ZXMxIzAhBgNVBAMMGkRhdHRvUk1NLkNvcmUgQ29kZSBTaWduaW5nMB4XDTI2MDMz # MTAwMTMzMFoXDTI4MDMzMTAwMjMzMFowPTEWMBQGA1UECgwNUm9iZXJ0IEZhZGRl # czEjMCEGA1UEAwwaRGF0dG9STU0uQ29yZSBDb2RlIFNpZ25pbmcwggEiMA0GCSqG # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQChn1EpMYQgl1RgWzQj2+wp2mvdfb3UsaBS # nxEVGoQ0gj96tJ2MHAF7zsITdUjwaflKS1vE6wAlOg5EI1V79tJCMxzM0bFpOdR1 # L5F2HE/ovIAKNkHxFUF5qWU8vVeAsOViFQ4yhHpzLen0WLF6vhmc9eH23dLQy5fy # tELZQEc2WbQFa4HMAitP/P9kHAu6CUx5s4woLIOyyR06jkr3l9vk0sxcbCxx7+dF # RrsSLyPYPH+bUAB8+a0hs+6qCeteBuUfLvGzpMhpzKAsY82WZ3Rd9X38i32dYj+y # dYx+nx+UEMDLjDJrZgnVa8as4RojqVLcEns5yb/XTjLxDc58VatdAgMBAAGjRjBE # MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQU # H+B0vf97dYXqdUX1YMcWhFsY6fcwDQYJKoZIhvcNAQELBQADggEBAJmD4EEGNmcD # 1JtFoRGxuLJaTHxDwBsjqcRQRE1VPZNGaiwIm8oSQdHVjQg0oIyK7SEb02cs6n6Y # NZbwf7B7WZJ4aKYbcoLug1k1x9SoqwBmfElECeJTKXf6dkRRNmrAodpGCixR4wMH # KXqwqP5F+5j7bdnQPiIVXuMesxc4tktz362ysph1bqKjDQSCBpwi0glEIH7bv5Ms # Ey9Gl3fe+vYC5W06d2LYVebEfm9+7766hsOgpdDVgdtnN+e6uwIJjG/6PTG6TMDP # y+pr5K6LyUVYJYcWWUTZRBqqwBHiLGekPbxrjEVfxUY32Pq4QfLzUH5hhUCAk4HN # XpF9pOzFLMUxggIDMIIB/wIBATBRMD0xFjAUBgNVBAoMDVJvYmVydCBGYWRkZXMx # IzAhBgNVBAMMGkRhdHRvUk1NLkNvcmUgQ29kZSBTaWduaW5nAhB464iXHfI6gksE # kDDTyrNsMA0GCWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKEC # gAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwG # CisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIN79sTVNHyqy6EEK/OGzqnmB+bRB # R8FMgbp86EPTAtqDMA0GCSqGSIb3DQEBAQUABIIBAAal2RW6abZ7Etd+Nm2fhI8Z # QSA5duIIm/pod6jD3qbQSwDj8LURuWP9FXuCNBeSAUHZ8LCqAKcyXWhTvYfHF2Jq # opAfn4oGL96ONAwywD18Oq0QALe9VFWoiPCQMQ+vVS6xGr++bl5Nw49qXtrTyx7a # DHJLjuLjudqbNLzSce4txIadgCxfuyRsqgfwKoXX8O1xEiA9BtxbISeNSkcalxhP # rmeRiOxmlJILLCgok7UJh+8KpeEGWbFWtP1ZnKf+LjnnWoiwoqw4NP3pFUZnMePn # Sbx0LcB8U9GOQKPgxY0Yrvb0LaNuWPrEHT2E1nOUlZvC7uq5rkXCI7/sNOUTbZQ= # SIG # End signature block |