TeamViewer API + PowerShell Invoke-RestMethod problems

Hi all,

I'm trying to get some custom automation going where only users in specific AD groups would be imported, and they'd be assigned different QuickSupport assignments based on those groups.  I've got the ActiveDirectory side of the script working, and it's telling me what it'd do for each user correctly.  However, I'm having trouble getting the API to work.

I've create company and user tokens, so I can test with either as needed.  I can successfully ping the API using either token and get token_valid = true.  I can also return a list of users, or a single user using parameters.  It's when I try to add or remove users that things start to get sticky.  (I've removed the tokens below for obvious reasons, but they're the actual tokens in my script)

PS C:\Users\user> $header

Name Value
---- -----
Authorization Bearer $userToken


PS C:\Users\user> $postHeader

Name Value
---- -----
Content-Type application/json
Authorization Bearer $userToken

PS C:\Users\user> Invoke-RestMethod -Method 'GET' -Headers $header -Uri "$baseUri/api/v1/users?email=john.testmoe@example.com.au"

users
-----
{}

PS C:\Users\user> $body
{
"email": "john.testmoe@example.com.au",
"name": "John TestMoe",
"language": "en",
"password": "Testing123"
}

PS C:\Users\user> Invoke-RestMethod -Method 'POST' -Headers $postHeader -Uri "$baseUri/api/v1/users" -Body $body
Invoke-RestMethod : {"error":"invalid_request","error_description":"This e-mail address is already in use","error_code":1}
At line:1 char:1
+ Invoke-RestMethod -Method 'POST' -Headers $postHeader -Uri "$baseUri/ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

This appears to be because I had a test user with that address before, but it hasn't cleared from the system yet.  So we'll try a new account.

PS C:\Users\user> $body = @{
>> 'email' = 'john.testmoe2@example.com.au';
>> 'language' = 'en';
>> 'name' = 'John TestMoe2';
>> 'password' = 'Testing123'
>> } | ConvertTo-Json
>>
PS C:\Users\user> Invoke-RestMethod -Method 'POST' -Headers $postHeader -Uri "$baseUri/api/v1/users" -Body $body
Invoke-RestMethod : {"error":"internal_error","error_code":3,"error_signature":"DwLxS4/88105bc5/060318"}
At line:1 char:1
+ Invoke-RestMethod -Method 'POST' -Headers $postHeader -Uri "$baseUri/ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

error = internal_error, and error_code = 3.  Not the most helpful of error messages.  Can anyone tell me where I'm going wrong?

Cheers,

John Moe

Best Answer

Answers

  • JohnMoe
    JohnMoe Posts: 10 ✭✭

    Well, this is annoying.  I thought at first read, you just removed the "permissions" and "custom_quicksupport_id" fields, so I removed them from my test code, and it ran through fine.  But then I noticed that in the testing I did for this post, I had already removed them, so I looked further at what you posted.  It seems you just stripped the quotes off the names; is that correct?  Because I didn't do that in my test today, and it worked.  I'm at a loss to explain why.

  • DomLan
    DomLan Posts: 490 ⭐Star⭐

    Yes, I removed the quotation marks, according to what was stated by Microsoft in the documentation related to the ConvertTo-Json function.

    Do not use quotation marks for the field name. Use double quotes for the relative value.

    Regards

    Domenico Langone

    MCSD: App Builder

  • JohnMoe
    JohnMoe Posts: 10 ✭✭

    I just read that document; I don't see where it says that quotation marks shouldn't be used.

    One of the quirks of PowerShell that I don't like is the implicit conversion of types, especially strings.  Hence these two become functionally equivalent:

    $test1 = @{
    name = "value"
    }

    $test2 = @{
    'name' = 'value'
    }

    It automatically converts the unquoted name field into a string.  Strings *should* be quoted for clarity purposes; automatically converting unquoted text into strings leads to misunderstandings.  It's even more disappointing that a lot of Microsoft's official documentation gives examples without quotes.

    As for single or double quotes, the main difference in PowerShell is that single quotes won't do variable expansion, which double quotes will.

    In all three cases, you end up with the same string variable.  So leaving the quotes out should not have any effect on the code.

    If you run the example I posted above in PowerShell and then examine $test1 and $test2, you'll see they're identical.  You end up with an object with a Name parameter of "name" and a Value parameter of "value".  And when you convert them to JSON, they're identical:

     

    PS C:\Users\user> ($test1 | ConvertTo-Json) -eq  ($test2 | ConvertTo-Json)
    True

    However, it now seems to be working; I've removed the custom_quicksupport_id parameter and the permissions parameter, and it creates the user just fine.  I don't honestly know what I've done differently, but I've successfully created a number of users (with the quotation marks still in the script), so I'm going to treat this as resolved.

     

  • TeamViewerAsk
    TeamViewerAsk Posts: 2 ✭✭

    Solved with a little digging,

    $header = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"

    $token = 'PUT_YOUR_API_TOKEN_HERE'

    $header.Add("authorization", "Bearer $token")

    $rid = Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\TeamViewer"

    $cid = "r"+$rid.ClientID

    $devices = Invoke-RestMethod -Uri "https://webapi.teamviewer.com/api/v1/devices" -Method Get -Headers $header

    ForEach($item in $devices.devices)

      {

      If($item.remotecontrol_id -eq $cid)

        {

        $x = $item.device_id

        }

      }

    $body = (@{

          Alias = "$env:COMPUTERNAME - $env:USERNAME"

         }) | ConvertTo-Json

    Invoke-RestMethod -Uri "https://webapi.teamviewer.com/api/v1/devices/$x" -Method Put -Headers $header -ContentType application/json -Body $body


    Make this run on logon somehow, I add it to the startup folder with a batch script through gpo, if the device is already managed, this will run and rename it, I've built our teamviewer deployment from scratch so if you need any help deploying, let me know and I'll try and help.

    Bonus, because all this does is connect to the API, you don't have to have admin privs on the host device.


    If this doesn't work, try changing "$rid = Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\TeamViewer"" to "$rid = Get-ItemProperty "HKLM:\SOFTWARE\TeamViewer""

    Enjoy :)