Getting "remote server recieving 401 unauthorized when invoke-restmethod token request in Azure runbooks

AdminAS 146 Reputation points
2021-10-26T22:15:00.92+00:00

I need to use unattended login for the Microsoft Teams module. To do this I need the Graph and Teams resource tokens to pass to the connection. I have created a http call body for these requests and tested on my machine. They work. When I take the code and place it into the runbook environment i get the "401 Unauthorized" error.

I have given all the proper API permissions to the Service Principal i am using. And gone off this tutorial for the most part, missing the runbooks. teams-powershell-token-auth

Here is the code, minimizing the hardcoding as you would assume.

$Application = Get-AutomationCertificate -Name 'Onboarding-ServicePrincipal.PFX'
$Application
$connectionID = Get-AutomationConnection -Name 'Onboarding-ServicePrincipal'

Connect-ExchangeOnline -AppId $connectionID.ApplicationId -CertificateThumbprint $Application.Thumbprint -Organization "MyCompany.onmicrosoft.com" -verbose

$servicePrincipal = Get-AutomationPSCredential -Name 'Onboarding-ServicePrincipal'
$tenantName = "MyCompany.onmicrosoft.com"
$clientSecret = $servicePrincipal.password

write-output "Connection Details:"
$connectionID.ApplicationId
$servicePrincipal.password
write-output "########################"
$graphResource = "https://graph.microsoft.com/"
$graphTokenBody = @{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
Client_Id = $connectionID.ApplicationId
Client_Secret = $clientSecret
}
$graphUri = "https://login.microsoftonline.com/"+$tenantName+"/oauth2/v2.0/token"
$graphUri
$graphTokenResponse = Invoke-RestMethod -Uri $graphUri -Method POST -body $graphTokenBody
write-output "Here is Graph....."
$graphTokenResponse

$teamsResource = "https://api.interfacesrecords.teams.microsoft.com"
$teamsTokenBody = @{
Grant_Type = "client_credentials"
Scope = "48ac35b8-9aa8-4d74-927d-1f4a14a0b239/.default"
Client_Id = $connectionID.ApplicationId
Client_Secret = $clientSecret
}
$teamsUri = "https://login.microsoftonline.com/"+$tenantName+"/oauth2/v2.0/token"
$teamsTokenResponse = Invoke-RestMethod -Uri $teamsUri -Method POST -Body $teamsTokenBody
write-output "Here is Teams...."
$teamsTokenResponse

$servicePrincipal.ClientID

Azure Automation
Azure Automation
An Azure service that is used to automate, configure, and install updates across hybrid environments.
1,366 questions
Microsoft Partner Center API
Microsoft Security Microsoft Graph
0 comments No comments
{count} votes

Accepted answer
  1. AdminAS 146 Reputation points
    2021-10-27T15:44:18.577+00:00

    ANSWER:
    So if anyone else stumbles on my answering my own problems here ya go.

    It was exactly what i said, the system was sending over the literal "system.securestring" which is obviously not the password. So looking over this answer graciously given by @mklement0 how-do-you-decrypt-securestring-in-powershell I took the psobject password in a temporary variable and then pass the plaintext password decrypted in another variable to the POST. Here is the blurp:

    $secret = $servicePrincipal.password
    $clientSecret = [Net.NetworkCredential]::new('',$secret).Password

    .............

    $graphTokenBody = @{
    grant_Type = "client_credentials"
    tenant = $tenant
    scope = "https://graph.microsoft.com/.default"
    client_id = $connectionID.ApplicationId
    client_secret = $clientSecret
    }

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. AdminAS 146 Reputation points
    2021-10-27T15:28:20.537+00:00

    EDIT:

    This is what I found, in that code i pull in the Client secret from the account.password attribute. I have seen this translate in other things, but it does not in this case. I hardcoded my client secret into the code and it worked. NOW I ask if there is a way to disguise the client secret within the code (aka use the $client.Password) but input the "conversion" of the password as Plaintext into the body of the Call??

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.