How to make -AccessTokens work with Connect-MicrosoftTeams cmdlet? - powershell

I am following this link to connect to Microsoft Teams using Access Tokens:
https://learn.microsoft.com/en-us/MicrosoftTeams/teams-powershell-application-authentication
Here is the code:
$ClientSecret = 'xxxxx~xx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
$ApplicationID = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
$TenantID = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
$graphtokenBody = #{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
Client_Id = $ApplicationID
Client_Secret = $ClientSecret
}
$graphToken = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token" -Method POST -Body $graphtokenBody | Select-Object -ExpandProperty Access_Token
$teamstokenBody = #{
Grant_Type = "client_credentials"
Scope = "48ac35b8-9aa8-4d74-927d-1f4a14a0b239/.default"
Client_Id = $ApplicationID
Client_Secret = $ClientSecret
}
$teamsToken = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token" -Method POST -Body $teamstokenBody | Select-Object -ExpandProperty Access_Token
Connect-MicrosoftTeams -AccessTokens #("$graphToken", "$teamsToken")
The application is registered in Azure AD and has been assigned the API permissions as mentioned in the article. I have assigned Teams administrator role to the application as well. Tokens get populated correctly.
Running the code produces the following error:
Connect-MicrosoftTeams : Object reference not set to an instance of an object.
At line:29 char:1
+ Connect-MicrosoftTeams -AccessTokens #("$graphToken", "$teamsToken")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : AuthenticationError: (:) [Connect-MicrosoftTeams], NullReferenceException
+ FullyQualifiedErrorId : Connect-MicrosoftTeams,Microsoft.TeamsCmdlets.Powershell.Connect.ConnectMicrosoftTeams
Connect-MicrosoftTeams : Object reference not set to an instance of an object.
At line:29 char:1
+ Connect-MicrosoftTeams -AccessTokens #("$graphToken", "$teamsToken")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Connect-MicrosoftTeams], NullReferenceException
+ FullyQualifiedErrorId : System.NullReferenceException,Microsoft.TeamsCmdlets.Powershell.Connect.ConnectMicrosoftTeams
If someone had this issue and have successfully resolved it or have some tips on how to resolve it, please help.

I tried to reproduce the same in my environment and got the same error as below:
The error usually occurs if the version of Microsoft teams you are trying to connect is older than 4.7.1-preview version.
To resolve the error, try updating the Microsoft teams PowerShell version to 4.7.1-preview or later and this type of authentication is supported only in commercial environments.
Get-InstalledModule -Name MicrosoftTeams
Update-Module -Name MicrosoftTeams
After updating the PowerShell Module, I am able to connect to Microsoft Teams successfully like below:
$ClientSecret = "ClientSecret"
$ApplicationID = "AppID"
$TenantID = "TenantID"
$graphtokenBody = #{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
Client_Id = $ApplicationID
Client_Secret = $ClientSecret
}
$graphToken = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token" -Method POST -Body $graphtokenBody | Select-Object -ExpandProperty Access_Token
$teamstokenBody = #{
Grant_Type = "client_credentials"
Scope = "48ac35b8-9aa8-4d74-927d-1f4a14a0b239/.default"
Client_Id = $ApplicationID
Client_Secret = $ClientSecret
}
$teamsToken = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token" -Method POST -Body $teamstokenBody | Select-Object -ExpandProperty Access_Token
Connect-MicrosoftTeams -AccessTokens #("$graphToken", "$teamsToken")
Reference:
PowerShell Gallery | MicrosoftTeams 4.9.1

Related

Microsoft Graph "Access is denied. Check credentials and try again" in PowerShell

I am unable to list events in a calendar via MS Graph API: calls result in "Access is denied". Switching to raw HTTP results in error 403 as well. I am able to create an event via a POST to /events endpoint, though.
This is the code I am executing:
$tenant = '<SNIP>'
$client_id = '<SNIP>'
$client_secret = '<SNIP>'
$scope = [System.Web.HttpUtility]::UrlEncode('https://graph.microsoft.com/.default')
$url = "https://login.microsoftonline.com/$tenant/oauth2/v2.0/token"
$Body = "client_id=$client_id&scope=$scope&client_secret=$client_secret&grant_type=client_credentials"
$response = Invoke-RestMethod $url -Method Post -Body $Body -Headers #{'Content-Type'='application/x-www-form-urlencoded'}
$token = $response.access_token
Connect-MgGraph -AccessToken $token
Get-MgUserEvent -UserId '17160c5f-dd86-46cc-92b8-54d6e94861e6'
Output:
.\Calendar.ps1
Welcome To Microsoft Graph!
Get-MgUserEvent : Access is denied. Check credentials and try again.
In C:\Users\SYSTOLA-rk\Calendar.ps1:15 Zeichen:1
+ Get-MgUserEvent -UserId '17160c5f-dd86-46cc-92b8-54d6e94861e6'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: ({ UserId = 1716..., Property = }:<>f__AnonymousType39`7) [Get-MgUserEvent_List1], RestException`1
+ FullyQualifiedErrorId : ErrorAccessDenied,Microsoft.Graph.PowerShell.Cmdlets.GetMgUserEvent_List1
Here are the permissions in Azure configured for the app (I lack reputation for posting images): App Permissions

Get-MsalToken Error : Parameter set cannot be resolved using the specified named parameters

I'm getting the error below when executing this script attempting to generate a TAP in Azure AD:
$tenantId = "**********"
$clientID = "**********"
$ClientSecret = ConvertTo-SecureString "**********" -AsPlainText -Force
$Scope = "https://**************"
$redirectUri = "https://***************"
$TokenResponse = Get-MsalToken -ClientId $clientID -clientsecret $clientsecret -TenantId $tenantId -Interactive -RedirectUri $redirectUri -Scopes $Scope
It errors as follows:
Get-MsalToken : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:18
+ $TokenResponse = get-msaltoken #connectiondetails
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-MsalToken], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Get-MsalToken
I cannot figure out what is wrong. Any input to assist will be greatly appreciated!
I attempted running the script without the -clientsecret paramater and I get this error:
Get-MsalToken : A configuration issue is preventing authentication - check the error message from the server for details. You can modify the configuration in the application registration portal. See
https://aka.ms/msal-net-invalid-client for details. Original exception: AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.
Trace ID: 478c441b-12e4-4968-a485-066872501300
Correlation ID: 55cf72cb-7c3c-4f4e-a26c-cfe746bb5985
Timestamp: 2023-01-15 22:04:27Z
At line:1 char:18
... nResponse = Get-MsalToken -ClientId $clientID -TenantId $tenantId -I ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : AuthenticationError: (Microsoft.Ident...arameterBuilder:AcquireTokenInteractiveParameterBuilder) [Write-Error], MsalServiceException
FullyQualifiedErrorId : GetMsalTokenFailureAuthenticationError,Get-MsalToken
I tried to reproduce the same in my environment and got the same error as below:
When I ran the script without Client-Secret, I got the below error:
I agree with mklement0, -Interactive with -ClientSecret is not feasible to use in one script while generating the token via Get-MsalToken.
I excluded -Interactive from the script and access token generated successfully like below:
$tenantId = "TenantID"
$clientID = "ClientID"
$ClientSecret = ConvertTo-SecureString "ClientSecret" -AsPlainText -Force
$Scope = "Scope"
$redirectUri = "RedirectURI"
$TokenResponse = Get-MsalToken -ClientId $clientID -clientsecret $clientsecret -TenantId $tenantId -RedirectUri $redirectUri -Scopes $Scope
For more in detail, please refer below links:
PowerShell Gallery | Get-MsalToken.ps1
Microsoft Graph Access Token Acquisition with PowerShell by Nicola Suter

Invoke-RestMethod : The remote server returned an error: (403) Forbidden PowerShell

I want to get the display name and createdDateTime of Azure AD Groups by calling MS Graph from PowerShell.
For that, I'm using below PS Script:
$Body = #{
client_id = "app_id"
client_secret = "secret"
scope = "https://graph.microsoft.com/.default"
grant_type = 'client_credentials'
}
$Connect_Graph = Invoke-RestMethod -Uri "https://login.microsoftonline.com/my_tenant_id/oauth2/v2.0/token" -Method Post -Body $Body
$token = $Connect_Graph.access_token
$query = "https://graph.microsoft.com/v1.0/groups/"
$groups = (Invoke-RestMethod -Headers #{Authorization = "Bearer $($token)"} -Uri $query -Method Get).value | Select displayName, createdDateTime
It failed with 403 Forbidden
Invoke-RestMethod : The remote server returned an error: (403) Forbidden.
At C:\Users\script.ps1:13 char:12
+ $groups = (Invoke-RestMethod -Headers #{Authorization = "Bearer $($to ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I have given permissions for Group.Read.All and Directory.Read.All.
Please check what type of permissions you granted for Group.Read.All and Directory.Read.All.
If you are trying to access the API as signed-in user, then you have to use Delegated permissions.
If you are trying to access the API without signed-in user, then you have to use Application permissions.
I executed the same script in my environment and got the same error when I have Delegated permissions without signed-in user like below:
To resolve the error, I granted Application permissions for Group.Read.All and Directory.Read.All and executed the below script:
$Body = #{
client_id = "app_id"
client_secret = "secret"
scope = "https://graph.microsoft.com/.default"
grant_type = 'client_credentials'
}
$Connect_Graph = Invoke-RestMethod -Uri "https://login.microsoftonline.com/my_tenant_id/oauth2/v2.0/token" -Method Post -Body $Body
$token = $Connect_Graph.access_token
$query = "https://graph.microsoft.com/v1.0/groups/"
(Invoke-RestMethod -Headers #{Authorization = "Bearer $($token)"} -Uri $query -Method Get).value | Select displayName, createdDateTime
And I got the results successfully like below:

Scanner API Call using PowerShell for multiple PowerBI workspaces

I'm trying to call a PowerBI GETinfo Scanner API using PowerShell. One of the requirements is to pass multiple workspaces to get the info. Here is the MS doc link :\
https://learn.microsoft.com/en-us/rest/api/power-bi/admin/workspace-info-post-workspace-info#example
However, I'm not able to pass below syntax for API body in PowerShell.
The below syntax to call multiple workspaces in API body is not working :
$auth_body =#{
"workspaces": [
"97d03602-4873-4760-b37e-1563ef5358e3",
"67b7e93a-3fb3-493c-9e41-2c5051008f24"
]
}
I'm only able to pass single workspace and below syntax works :
$auth_body =#{'workspaces' ="3b7e9b1c-bdac-4e46-a39d-1b3d24a0e122"}
Please help me to form the syntax for multiple workspaces. Seems I'm not able to form key value pair inside PowerShell for multiple workspaces
Updated Code after applying MathiasR.Jessen suggestion:
$authority = 'https://login.microsoftonline.com/oauth2/'+ $tenantID
$authResult = Get-AdalToken -Authority $authority -Resource $resourceAppIdURI -ClientID $UId -Clientsecret $password -TenantID $tenantID
$Token=$authResult.AccessToken
#Write-Output "Token: $Token"
$auth_header = #{
'Accept' = "application/json";
'Authorization' = 'Bearer ' +$Token
}
$auth_body = #{
"workspaces" =
#("50c4bd8e-fc75-433e-a0cd-755f9329515e","97d03602-4873-4760-b37e-1563ef5358e3")
}
$uri = "https://api.powerbi.com/v1.0/myorg/admin/workspaces/getInfo"
$all_workspace = (Invoke-RestMethod -Uri $uri –Headers $auth_header -Body $auth_body –Method Post)
And Error Message :
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
+ ... rkspace1 = (Invoke-RestMethod -Uri $uri –Headers $auth_header -Body $ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
However, It works perfectly if I provide single workspace.
You're mixing PowerShell and JSON syntax.
To define an array in PowerShell, use the #() array subexpression operator:
$auth_body = #{
"workspaces" = #(
"97d03602-4873-4760-b37e-1563ef5358e3",
"67b7e93a-3fb3-493c-9e41-2c5051008f24"
)
}

Invoking MS Graph API from PowerShell

We need to be able to programatically POST to the MS Graph API in order to bulk assign users to Access Packages, e.g.: https://learn.microsoft.com/en-us/graph/api/accesspackageassignmentrequest-post?view=graph-rest-beta&tabs=http#examples
I am trying things like this:
Invoke-RestMethod 'https://graph.microsoft.com/beta/identityGovernance/entitlementManagement/accessPackageAssignmentRequests' -Method POST -ContentType 'application/json' -Body #{
"requestType": "AdminAdd",
"accessPackageAssignment":{
"targetId":"xxx",
"assignmentPolicyId":"xxx",
"accessPackageId":"xxx"
}
}
Unfortunately though I get errors like this:
At line:2 char:29
+ "requestType": "AdminAdd",
+ ~
Missing '=' operator after key in hash literal.
At line:2 char:29
+ "requestType": "AdminAdd",
+ ~
The hash literal was incomplete.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEqualsInHashLiteral
Does anyone know how I should be doing it please?
Additionally, we have MFA enforced so the standard $Cred = Get-Credential will not work. What should I use instead?
Thanks
There are several errors on the object syntax of your example:
In Powershell properties are assigned with =
Property names must not be quoted
Property assignments are separated with semicolon
The correct command would look like:
Invoke-RestMethod 'https://graph.microsoft.com/beta/identityGovernance/entitlementManagement/accessPackageAssignmentRequests' -Method POST -ContentType 'application/json' -Body #{
requestType = "AdminAdd";
accessPackageAssignment = {
targetId = "xxx";
assignmentPolicyId = "xxx";
accessPackageId = "xxx"
}
}
Regarding MFA, you need to either use AppTokens or OAuth.
I wanted to call Graph API endpoints through PowerShell as well. This was the script I ended up with:
Install-Module -Name MSAL.PS -RequiredVersion 4.2.1.3
Import-Module MSAL.PS
$clientId = "YOURCLIENTID"
$clientSecret = "YOURCLIENTSECRET"
$tenantId = "YOURTENANTID"
$ConfidentialClientOptions = New-Object Microsoft.Identity.Client.ConfidentialClientApplicationOptions -Property #{ ClientId = $clientId; ClientSecret = $clientSecret; TenantId = $tenantId }
$ConfidentialClient = $ConfidentialClientOptions | New-MsalClientApplication
$tokenObj = Get-MsalToken -Scope 'https://graph.microsoft.com/.default' -ConfidentialClientApplication $ConfidentialClient
$apiUrl = "https://graph.microsoft.com/beta/users?filter=signInActivity/lastSignInDateTime le 2021-06-21T00:00:00Z&`$select=userPrincipalName,displayName,mail,signInActivity"
$res = Invoke-RestMethod -Headers #{Authorization = "Bearer $($tokenObj.AccessToken)"} -Uri $apiUrl -Method Get
$res.value | select userPrincipalName, displayName, mail, #{L="LastSignInDateTime";E={$_.signInActivity.lastSignInDateTime}} | Sort-Object -Property LastSignInDateTime
I wrote a blog post about it as well: https://engineerer.ch/2021/07/01/how-to-use-powershell-to-call-graph-api-endpoints/