Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
309 changes: 162 additions & 147 deletions AdminConsent/GA_AdminConsent_Set.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,199 +7,214 @@ See LICENSE in the project root for license information.

#>

####################################################

function Get-AuthToken {

function Connect-GraphAPI {
<#
.SYNOPSIS
This function is used to authenticate with the Graph API REST interface
Connects to Microsoft Graph API with appropriate scopes for Intune operations
.DESCRIPTION
The function authenticate with the Graph API Interface with the tenant name
This function connects to Microsoft Graph using the Microsoft.Graph.Authentication module
.PARAMETER Scopes
Array of permission scopes required for the operations
.PARAMETER Environment
The Microsoft Graph environment to connect to (Global, USGov, USGovDod, China, Germany)
.EXAMPLE
Connect-GraphAPI
Connects to Microsoft Graph with default scopes
.EXAMPLE
Get-AuthToken
Authenticates you with the Graph API interface
Connect-GraphAPI -Environment "USGov"
Connects to Microsoft Graph US Government environment
.NOTES
NAME: Get-AuthToken
Requires Microsoft.Graph.Authentication module
#>

[cmdletbinding()]

param
(
[Parameter(Mandatory=$true)]
$User
)

$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User

$tenant = $userUpn.Host

Write-Host "Checking for AzureAD module..."

$AadModule = Get-Module -Name "AzureAD" -ListAvailable

if ($AadModule -eq $null) {

Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview"
$AadModule = Get-Module -Name "AzureADPreview" -ListAvailable

}

if ($AadModule -eq $null) {
write-host
write-host "AzureAD Powershell module not installed..." -f Red
write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow
write-host "Script can't continue..." -f Red
write-host
exit
}

# Getting path to ActiveDirectory Assemblies
# If the module count is greater than 1 find the latest version

if($AadModule.count -gt 1){

$Latest_Version = ($AadModule | select version | Sort-Object)[-1]

$aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version }

# Checking if there are multiple versions of the same module found

if($AadModule.count -gt 1){

$aadModule = $AadModule | select -Unique

}

$adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"

}

else {

$adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"

}

[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null

[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null

# Using this authentication method requires a clientID. Register a new app in the Entra ID admin center to obtain a clientID. More information
# on app registration and clientID is available here: https://learn.microsoft.com/entra/identity-platform/quickstart-register-app

$clientId = "<replace with your clientID>"

$redirectUri = "urn:ietf:wg:oauth:2.0:oob"

$resourceAppIdURI = "https://graph.microsoft.com"

$authority = "https://login.microsoftonline.com/$Tenant"
[CmdletBinding()]
param(
[string[]]$Scopes = @(
"DeviceManagementConfiguration.ReadWrite.All",
"Group.Read.All"
),
[ValidateSet("Global", "USGov", "USGovDod", "China", "Germany")]
[string]$Environment = "Global"
)

try {
# Set global Graph endpoint based on environment
switch ($Environment) {
"Global" { $global:GraphEndpoint = "https://graph.microsoft.com" }
"USGov" { $global:GraphEndpoint = "https://graph.microsoft.us" }
"USGovDod" { $global:GraphEndpoint = "https://dod-graph.microsoft.us" }
"China" { $global:GraphEndpoint = "https://microsoftgraph.chinacloudapi.cn" }
"Germany" { $global:GraphEndpoint = "https://graph.microsoft.de" }
default { $global:GraphEndpoint = "https://graph.microsoft.com" }
}

$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority

# https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx
# Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession

$platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto"

$userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId")

$authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId,"prompt=admin_consent").Result

if($authResult.AccessToken){

# Creating header for Authorization token

$authHeader = @{
'Content-Type'='application/json'
'Authorization'="Bearer " + $authResult.AccessToken
'ExpiresOn'=$authResult.ExpiresOn
}

return $authHeader
Write-Host "Graph Endpoint: $global:GraphEndpoint" -ForegroundColor Magenta
# Check if Microsoft.Graph.Authentication module is available
if (-not (Get-Module -Name Microsoft.Graph.Authentication -ListAvailable)) {
Write-Error "Microsoft.Graph.Authentication module not found. Please install it using: Install-Module Microsoft.Graph.Authentication"
return $false
}

# Import the module if not already loaded
if (-not (Get-Module -Name Microsoft.Graph.Authentication)) {
Import-Module Microsoft.Graph.Authentication -Force
}

# Connect to Microsoft Graph
Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Cyan
Connect-MgGraph -Scopes $Scopes -Environment $Environment -NoWelcome

# Verify connection
$context = Get-MgContext
if ($context) {
Write-Host "Successfully connected to Microsoft Graph!" -ForegroundColor Green
Write-Host "Tenant ID: $($context.TenantId)" -ForegroundColor Yellow
Write-Host "Account: $($context.Account)" -ForegroundColor Yellow
Write-Host "Environment: $($context.Environment)" -ForegroundColor Yellow
Write-Host "Scopes: $($context.Scopes -join ', ')" -ForegroundColor Yellow
return $true
}
else {

Write-Host
Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red
Write-Host
break

Write-Error "Failed to establish connection to Microsoft Graph"
return $false
}

}

catch {

write-host $_.Exception.Message -f Red
write-host $_.Exception.ItemName -f Red
write-host
break

Write-Error "Error connecting to Microsoft Graph: $($_.Exception.Message)"
return $false
}

}

####################################################
function Invoke-IntuneRestMethod {
<#
.SYNOPSIS
Invokes Microsoft Graph REST API calls with automatic paging support
.DESCRIPTION
This function makes REST API calls to Microsoft Graph with built-in error handling and automatic paging for large result sets
.PARAMETER Uri
The Microsoft Graph URI to call (can be relative path or full URL)
.PARAMETER Method
The HTTP method to use (GET, POST, PUT, DELETE, PATCH)
.PARAMETER Body
The request body for POST/PUT/PATCH operations
.PARAMETER ContentType
The content type for the request (default: application/json)
.EXAMPLE
Invoke-IntuneRestMethod -Uri "v1.0/deviceManagement/deviceConfigurations" -Method GET
.EXAMPLE
Invoke-IntuneRestMethod -Uri "v1.0/deviceManagement/deviceConfigurations" -Method GET
.NOTES
Requires an active Microsoft Graph connection via Connect-MgGraph
Uses the global $GraphEndpoint variable for environment-specific endpoints
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$Uri,

#region Authentication
[Parameter(Mandatory = $false)]
[ValidateSet('GET', 'POST', 'PUT', 'DELETE', 'PATCH')]
[string]$Method = 'GET',

write-host
[Parameter(Mandatory = $false)]
[object]$Body = $null,

# Checking if authToken exists before running authentication
if($global:authToken){
[Parameter(Mandatory = $false)]
[string]$ContentType = 'application/json'
)

# Setting DateTime to Universal time to work in all timezones
$DateTime = (Get-Date).ToUniversalTime()
try {
# Ensure we have a Graph endpoint set
if (-not $global:GraphEndpoint) {
$global:GraphEndpoint = "https://graph.microsoft.com"
Write-Warning "No Graph endpoint set, defaulting to: $global:GraphEndpoint"
}

# If the authToken exists checking when it expires
$TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes
# Handle both relative and absolute URIs
if (-not $Uri.StartsWith("http")) {
$Uri = "$global:GraphEndpoint/$Uri"
}

if($TokenExpires -le 0){
$results = @()
$nextLink = $Uri

write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow
write-host
do {
Write-Verbose "Making request to: $nextLink"

# Defining Azure AD tenant name, this is the name of your Azure Active Directory (do not use the verified domain name)
$requestParams = @{
Uri = $nextLink
Method = $Method
ContentType = $ContentType
}

if($User -eq $null -or $User -eq ""){
if ($Body) {
if ($Body -is [string]) {
# Check if the string is valid JSON by trying to parse it
try {
$null = $Body | ConvertFrom-Json -ErrorAction Stop
# If we get here, it's valid JSON - use as-is
$requestParams.Body = $Body
Write-Verbose "Body detected as JSON string"
}
catch {
# String is not valid JSON, treat as plain string and wrap in quotes
$requestParams.Body = "`"$($Body)`""
Write-Verbose "Body detected as plain string, wrapping in quotes"
}
} else {
# Body is an object (hashtable, PSCustomObject, etc.), convert to JSON
$requestParams.Body = $Body | ConvertTo-Json -Depth 10
Write-Verbose "Body detected as object, converting to JSON"
}
}

$User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication"
Write-Host
$response = Invoke-MgGraphRequest @requestParams

# Handle paging
if ($response.value) {
$results += $response.value
$nextLink = $response.'@odata.nextLink'
}
else {
$results += $response
$nextLink = $null
}

$global:authToken = Get-AuthToken -User $User
} while ($nextLink)

return $results
}
catch {
$errorMessage = $_.Exception.Message
if ($_.Exception.Response) {
$statusCode = $_.Exception.Response.StatusCode
Write-Error "Graph API request failed with status $statusCode : $errorMessage"
}
else {
Write-Error "Graph API request failed: $errorMessage"
}
throw
}
}

# Authentication doesn't exist, calling Get-AuthToken function

else {
####################################################

if($User -eq $null -or $User -eq ""){
####################################################

$User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication"
Write-Host

}
####################################################

# Getting the authorization token
$global:authToken = Get-AuthToken -User $User
#region Authentication

# Connect to Microsoft Graph
if (-not (Connect-GraphAPI)) {
Write-Error "Failed to connect to Microsoft Graph. Exiting script."
exit 1
}

#endregion

####################################################

Write-Host

Loading