Apps Expiration Azure AD

This script will check all registered apps in Azure AD and will return the following information: expiring apps, expired apps, and apps with no expiration date. # needs permission Application.Read.All,Directory.Read.All $ClientID = '' $ClientSecret = '' $tenant_Id = '' $TenantName = $Body = @{ Grant_Type = "client_credentials" resource = "https://graph.microsoft.com" client_id = $clientId client_secret = $clientSecret } $ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoft.com/$tenant_Id/oauth2/token?api-version=1.0" -Method POST -Body $Body # Variable Collections # $path = "C:\temp\" $today = Get-Date $Headers = @{ 'Content-Type' = "application/json" 'Authorization' = "Bearer $($ConnectGraph.access_token)" } $token = $ConnectGraph.access_token # Force TLS 1.2. [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 function Get-GraphData { param ( [parameter(Mandatory)] [string]$AccessToken, [parameter(Mandatory)] [string]$Uri ) $Headers = @{ 'Authorization' = "Bearer $AccessToken" } do { $Results = Invoke-RestMethod -Uri $Uri -Headers $Headers -ErrorAction Stop $QueryResults += $Results.value $Uri = $Results.'@odata.nextLink' } while ($Uri) return $QueryResults } #This request get application info $uri = "https://graph.microsoft.com/beta/applications/" [array]$apps = Get-GraphData -AccessToken $Token -Uri $uri $credentials = @() if ($apps) { foreach ($app in $apps) { $ApiUrl = "https://graph.microsoft.com/beta/applications/"+$app.id+"/owners" $owner = Invoke-WebRequest -Method GET -Uri $ApiUrl -ContentType "application/json" -Headers $headers | ConvertFrom-Json $app.KeyCredentials | foreach-object { #write-host $_.KeyId $_.DisplayName $credentials += [PSCustomObject] @{ CredentialType = "KeyCredentials"; DisplayName = $app.DisplayName; AppId = $app.AppId; ExpiryDate = $_.EndDateTime; StartDate = $_.StartDateTime; #KeyID = $_.KeyId; Type = $_.Type; Usage = $_.Usage; Owners = $owner.value.userPrincipalName; Expired = (([DateTime]$_.EndDateTime) -lt $today) ? "Yes" : "No"; } } $app.PasswordCredentials | foreach-object { #write-host $_.KeyId $_.DisplayName $credentials += [PSCustomObject] @{ CredentialType = "PasswordCredentials"; DisplayName = $app.DisplayName; AppId = $app.AppId; ExpiryDate = $_.EndDateTime; StartDate = $_.StartDateTime; #KeyID = $_.KeyId; Type = 'NA'; Usage = 'NA'; Owners = $owner.value.userPrincipalName; Expired = (([DateTime]$_.EndDateTime) -lt $today) ? "Yes" : "No"; } } } } $credentials | Export-Csv -Path $path\credentials.csv -NoTypeInformation #$credentials | Format-Table | Out-String|ForEach-Object {Write-Host $_} reference https://pnp.github.io/script-samples/aad-apps-expired-keys/README.html?tabs=graphps {: .prompt-info } ...

April 7, 2023 · 2 min · 298 words · Benedikt Gabriel Egilsson

Getting licenses assigned to user accounts

Create a report of licenses assigned to Azure AD user accounts using the Microsoft Graph API This is a rewrite from here practical365.com My misson was to rewrite the script to use the Microsoft Graph API instead of the MgGraph PowerShell module. {: .prompt-info } $ClientID = '' $ClientSecret = '' $tenant_Id = '' # Connect to Graph # $Body = @{ Grant_Type = "client_credentials" resource = "https://graph.microsoft.com" client_id = $clientId client_secret = $clientSecret } $ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoft.com/$tenant_Id/oauth2/token?api-version=1.0" -Method POST -Body $Body # Variable Collections # $CSVOutputFile = "c:\temp\Microsoft365LicensesReport.CSV" $today = Get-Date $Headers = @{ 'Content-Type' = "application/json" 'Authorization' = "Bearer $($ConnectGraph.access_token)" } $token = $ConnectGraph.access_token # Force TLS 1.2. [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 function Get-GraphData { param ( [parameter(Mandatory)] [string]$AccessToken, [parameter(Mandatory)] [string]$Uri ) $Headers = @{ 'Authorization' = "Bearer $AccessToken" } do { $Results = Invoke-RestMethod -Uri $Uri -Headers $Headers -ErrorAction Stop $QueryResults += $Results.value $Uri = $Results.'@odata.nextLink' } while ($Uri) return $QueryResults } #This request get SecureScore [array]$Skus = Get-GraphData -AccessToken $Token -Uri "https://graph.microsoft.com/beta/subscribedSkus" #[Array]$Skus = Get-MgSubscribedSku # Generate CSV of all product SKUs used in tenant [array]$Sku = $Skus | Select-Object SkuId, SkuPartNumber # Generate list of all service plans used in SKUs in tenant $SPData = [System.Collections.Generic.List[Object]]::new() ForEach ($Sk in $Skus) { ForEach ($SP in $Sk.ServicePlans) { $SPLine = [PSCustomObject][Ordered]@{ ServicePlanId = $SP.ServicePlanId ServicePlanName = $SP.ServicePlanName ServicePlanDisplayName = $SP.ServicePlanName } $SPData.Add($SPLine) } } $SkuHashTable = @{} ForEach ($Line in $Sku) { $SkuHashTable.Add([string]$Line.SkuId, [string]$Line.skuPartNumber) } $ServicePlanHashTable = @{} ForEach ($Line2 in $SPData) { $ServicePlanHashTable.Add([string]$Line2.ServicePlanId, [string]$Line2.ServicePlanDisplayName) } [Array]$Users = Get-GraphData -AccessToken $Token -Uri "https://graph.microsoft.com/beta/users" $Report = [System.Collections.Generic.List[Object]]::new() ForEach ($User in $users) { If ([string]::IsNullOrWhiteSpace($User.AssignedLicenses) -eq $true) { # Only process account if it has some licenses Write-Host "Processing" $User.DisplayName [array]$LicenseInfo = $Null; [array]$DisabledPlans = $Null ForEach ($License in $User.AssignedLicenses) { If ($SkuHashTable.ContainsKey($License.SkuId) -eq $True) { # We found a match in the SKU hash table $LicenseInfo += $SkuHashTable.Item($License.SkuId) } Else { # Nothing doing, so output the SkuID $LicenseInfo += $License } # Report any disabled service plans in licenses If ([string]::IsNullOrWhiteSpace($License.DisabledPlans) -eq $False ) { # Check if disabled service plans in a license ForEach ($DisabledPlan in $License.DisabledPlans) { # Try and find what service plan is disabled If ($ServicePlanHashTable.ContainsKey($DisabledPlan) -eq $True) { # We found a match in the Service Plans hash table $DisabledPlans += $ServicePlanHashTable.Item($DisabledPlan) } Else { # Nothing doing, so output the Service Plan ID $DisabledPlans += $DisabledPlan } } # End ForEach disabled plans } # End if check for disabled plans } # End Foreach Licenses # Report information [string]$DisabledPlans = $DisabledPlans -join ", " [string]$LicenseInfo = $LicenseInfo -join (", ") $ReportLine = [PSCustomObject][Ordered]@{ User = $User.DisplayName UPN = $User.UserPrincipalName Country = $User.Country Department = $User.Department Title = $User.JobTitle Licenses = $LicenseInfo "Disabled Plans" = $DisabledPlans } Write-Host $ReportLine $Report.Add($ReportLine) } #end If account is licensed Else { $UnlicensedAccounts++ } } # End ForEach Users $Report | Export-CSV -NoTypeInformation $CSVOutputFile

April 1, 2023 · 3 min · 480 words · Benedikt Gabriel Egilsson

MS Graph API - Get Secure Score for tenant

Secure Score for O365 Tenant Getting the secure score for a tenant is a bit more complicated than getting the last logon time of a user. You only need to call the following endpoint: https://graph.microsoft.com/beta/security/secureScores and divide the result by 100 to get the percentage. # Needs permission SecurityEvents.Read.All $ClientID = '' $ClientSecret = '' $tenant_Id = '' # Connect to Graph # $Body = @{ Grant_Type = "client_credentials" resource = "https://graph.microsoft.com" client_id = $clientId client_secret = $clientSecret } $ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoft.com/$tenant_Id/oauth2/token?api-version=1.0" -Method POST -Body $Body # Variable Collections # $path = "C:\temp\" $Headers = @{ 'Content-Type' = "application/json" 'Authorization' = "Bearer $($ConnectGraph.access_token)" } $token = $ConnectGraph.access_token # Force TLS 1.2. [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 function Get-GraphData { param ( [parameter(Mandatory)] [string]$AccessToken, [parameter(Mandatory)] [string]$Uri ) $Headers = @{ 'Authorization' = "Bearer $AccessToken" } do { $Results = Invoke-RestMethod -Uri $Uri -Headers $Headers -ErrorAction Stop $QueryResults += $Results.value $Uri = $Results.'@odata.nextLink' } while ($Uri) return $QueryResults } #This request get SecureScore $uri = "https://graph.microsoft.com/beta/security/secureScores" $Result = @() [array]$Response = Get-GraphData -AccessToken $Token -Uri $uri if ($Response) { ForEach ($Respons in $Response) { $SecureScore = $Respons.currentScore / $Respons.maxScore * 100 $Result += New-Object PSObject -property $([ordered]@{ CreatedDateTime = $Respons.createdDateTime CurrentScore = $Respons.currentScore MaxScore = $Respons.maxScore LicensedUserCount = $Respons.licensedUserCount ActiveUserCount = $Respons.activeUserCount SecureScore = [math]::Round($SecureScore, 2) }) } } else { Write-Host "No SecureScore data found" } # export to csv $Result | export-csv -path "$path\SecureScore.csv" -NoTypeInformation

March 25, 2023 · 2 min · 235 words · Benedikt Gabriel Egilsson

Getting Started with MSGraph API

Authentication and Authorization MSGraph API is a powerful tool for authentication and authorization that allows developers to access Microsoft services and data. It provides a secure way to authenticate users, authorize applications, and manage user data. With MSGraph API, developers can easily integrate their applications with Microsoft services like Outlook, OneDrive, Office 365, Azure Active Directory, and more. In this article, we’ll explore how to get started with MSGraph API concepts and use cases of the API. Authentication We will use the Azure CLI to create a service principal and get the app id and secret. We will also use the Azure CLI to view all the API permissions available in Microsoft Graph. Get the Azure CLI from here {: .prompt-info } ...

March 25, 2023 · 2 min · 352 words · Benedikt Gabriel Egilsson

MS Graph API - Get User info

Microsoft Graph API can be used to get the last logon time of a user. To do this, you will need to make a GET request to the /users/{id}/lastLogonTimeStamp endpoint. This endpoint will return the last logon time of the user in the form of a timestamp. You can then use this timestamp to determine the exact date and time of the user’s last logon. This query get’s. DisplayName,UserPrincipalName,UsageLocation,Contry,LastSignInDateTime,IsLicensed,IsGuestUser {: .prompt-info } ...

March 25, 2023 · 2 min · 316 words · Benedikt Gabriel Egilsson