Category Archives: Security

Get-CsTeamsMeetingPolicy: Invalid credential Provide valid credential.

For those googling, above error happened for us when trying to use application-based authentication for the MS Teams PowerShell commandlets.

We followed the instructions but kept getting Invalid credential Provide valid credential whenever calling a cmdlet, while the connect-microsoftteams command worked fine with the -accesstokens param.

Turns out, when you assign application level permissions to your service principal on top of the delegated permissions, the SPN is not authorized for all subsequent cmdlet calls :O

Microsoft Teams permission auditing

I lied, not just Teams, also Sharepoint and Onedrive!

As I am asked often how to report on specific permissions granted to individual (groups) of (internal/external) users….and Microsoft doesn’t have a good built-in solution, nor does the community seem to yet….this something was just asking to be coded!

My TeamPermissions PowerShell module will do exactly the above, a full report in XLSX, CSV or HTML format that contains ALL unique permissions for a given Team, Sharepoint site or Onedrive location for all files, folders, lists, list items etc. Example:

It uses the safe Entra Delegated Permission Flow for authentication so your credentials/tokens stay with you, but this does mean you have to run it as a Sharepoint Administrator (or Global Admin), there is no support for MI/SPN runs yet but can be added easily if there is much demand.

Since it exports to Excel in append mode, you could run it for multiple (or all) team sites and use e.g. Pivots to view all permissions for a given user.

Do note that although some work has been done on performance, it does not scan multiple locations in parallel yet, this will be added in a future version.

Example:

Install-PSResource -Name TeamPermissions -Repository PSGallery

#then get xlsx/html reports for the INT-Finance Department Team:

Get-TeamPermissions -teamName "INT-Finance Department" -ExpandGroups -OutputFormat XLSX,HTML

#Or get all permission for a Sharepoint site:

Get-TeamPermissions -TeamSiteUrl "https://tenant.sharepoint.com/sites/site" -ExpandGroups -OutputFormat Default

Notes

Required PS modules: PnP.PowerShell, ImportExcel

Running multiple times will append data if you don’t move the (xlsx, csv, html) file, turning the report into a multi-location report.

Guest report & cleanup new features

My script / runbook to automatically report on stale Guests and clean them up has received some updates

  • Exclusion Groups

Guests in Exclusion groups will never be deleted, even if they are in an Inclusion Group

  • Inclusion Groups

Guests in Inclusion Groups will be deleted if they meet the age requirements, all guests not in an inclusion group will be ignored

  • ReadOnly mode

Will pretend to delete guests are per configured settings, but won’t actually delete anything

download from git: https://gitlab.com/Lieben/assortedFunctions/-/blob/master/get-AzureAdInactiveGuestUsers.ps1?ref_type=heads

Programmatically grant admin consent to a service principal

Most articles and e.g. az module commands allow you to do an admin consent on an application object.

However, Service Principals have the same option in the Azure Portal:

In my scenario I have control over both the hosting tenant of this multi-tenant app registration, so I could use the requiredResourceAccess property to read all Oauth2permissiongrants and approleAssignments from the source app registration to re-apply it to the service principal in the consuming tenant.

The result is similar to consenting through the admin portal but does not require user interaction / is fully headless, ideal for when you’re adding scopes/roles to an application and don’t want to have to do a manual reconsent in all managed tenants.

Here’s the code to to programmatic admin consent:

https://gitlab.com/Lieben/assortedFunctions/-/blob/master/grant-adminConsentForServicePrincipal.ps1

It requires DelegatedPermissionGrant.ReadWrite.All and AppRoleAssignment.ReadWrite.All graph permissions for the calling principal (user or application).

If you don’t have access to the source tenant (e.g. multi tenant), you can also simply create a hashtable with the required permissions (manual definition or export from the application manifest).

Easily get access token for Azure Management API

Wrote this little snippet that assumes a logged in session (Connect-AzAccount) and easily/quickly produces an auth header.

function get-azRMAccessHeader(){
    $profile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
    $context = Get-AzContext
    $client = New-Object Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient($profile)

    $header = @{
        "Authorization" = "Bearer $($client.AcquireAccessToken((Get-AzContext).Tenant.TenantId).AccessToken)"
    }
    return $header
}