# Ensure Microsoft.Graph module is installed if (-not (Get-Module -ListAvailable -Name Microsoft.Graph)) { Write-Host "Installing Microsoft.Graph module..." Install-Module -Name Microsoft.Graph -Force -AllowClobber } # Ensure ExchangeOnlineManagement module is installed if (-not (Get-Module -ListAvailable -Name Microsoft.Graph)) { Write-Host "Installing ExchangeOnlineManagement Module..." Install-Module -Name ExchangeOnlineManagement -Force -AllowClobber } # Import necessary modules Import-Module Microsoft.Graph.Authentication Import-Module Microsoft.Graph.Applications Import-Module ExchangeOnlineManagement # Connect to Microsoft Graph with required permissions Connect-MgGraph -Scopes "Application.ReadWrite.All", "Directory.ReadWrite.All", "AppRoleAssignment.ReadWrite.All" -NoWelcome # Application details $Name = "GraphAPI" $Scope = "Application.ReadWrite.All", "DeviceManagementApps.ReadWrite.All", "DeviceManagementConfiguration.ReadWrite.All", "DeviceManagementServiceConfig.ReadWrite.All", "Group.ReadWrite.All", "Policy.ReadWrite.ApplicationConfiguration", "User.ReadWrite.All" # Fetch Microsoft Graph Service Principal $graphSp = Get-MgServicePrincipal -Filter "AppId eq '00000003-0000-0000-c000-000000000000'" $graphRoles = $graphSp.AppRoles # Debugging: Confirm AppRoles permissions # Write-Host "`nšŸ” Retrieved AppRoles from Microsoft Graph:" # $graphRoles | Format-Table DisplayName, Id, Value -AutoSize # Build required resource access list $resourceAccess = @() foreach ($perm in $Scope) { $permId = ($graphRoles | Where-Object { $_.Value -eq $perm }).Id if ($permId) { $resourceAccess += @{ "id" = $permId "Type" = "Role" # Use "Scope" if using delegated permissions } } else { Write-Host "āš ļø Skipping $perm - Role ID not found in Microsoft Graph." } } # Debugging: Confirm matched permissions # Write-Host "`nāœ… Final Mapped Permissions:" # $resourceAccess | Format-Table -AutoSize # Define app creation body $body = @{ DisplayName = $Name SignInAudience = "AzureADMyOrg" RequiredResourceAccess = @( @{ ResourceAppId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph ResourceAccess = $resourceAccess } ) } # Convert body to JSON $payload = $body | ConvertTo-Json -Depth 4 # Create the application Write-Host "Creating Azure AD application..." $app = New-MgApplication -BodyParameter $payload if (-not $app) { Write-Host "āŒ Failed to create application. Exiting." exit } Write-Host "āœ… Application Created: $($app.Id)" # Wait for the application to propagate Start-Sleep -Seconds 10 Write-Host "ā³ Waiting for application propagation..." # Create Service Principal Write-Host "Creating Service Principal..." $servicePrincipal = New-MgServicePrincipal -AppId $app.AppId if (-not $servicePrincipal) { Write-Host "āŒ Failed to create Service Principal. Exiting." exit } Write-Host "āœ… Service Principal created: $($servicePrincipal.Id)" # Wait for service principal to propagate Start-Sleep -Seconds 10 Write-Host "ā³ Waiting for application permissions to propagate..." # Grant Admin Consent foreach ($access in $resourceAccess) { # Write-Host "`nšŸ”¹ About to grant admin consent for:" # Write-Host " āžœ AppRoleId: $($access.id)" # Write-Host " āžœ ServicePrincipalId: $($servicePrincipal.Id)" # Write-Host " āžœ PrincipalId: $($servicePrincipal.Id)" # Write-Host " āžœ ResourceId: $($graphSp.Id)" try { $null = New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $servicePrincipal.Id -PrincipalId $servicePrincipal.Id -ResourceId $graphSp.Id -AppRoleId $access.id Write-Host "āœ… Successfully granted admin consent for AppRoleId: $($access.id)" } catch { Write-Host "āŒ Failed to grant admin consent for AppRoleId: $($access.id) - $_" } } Write-Host "`nšŸŽ‰ Admin consent process completed!" # ------------------------------- # CREATE CLIENT SECRET # ------------------------------- Write-Host "`nšŸ” Creating Client Secret..." $secretStartDate = Get-Date $secretEndDate = $secretStartDate.AddYears(1) # Secret valid for 1 year $clientSecret = Add-MgApplicationPassword -ApplicationId $app.Id -PasswordCredential @{ DisplayName = "GraphAPI-ClientSecret" StartDateTime = $secretStartDate EndDateTime = $secretEndDate } if (-not $clientSecret) { Write-Host "āŒ Failed to create client secret. Exiting." exit } Write-Host "āœ… Client Secret Created!" # ------------------------------- # PRINT CREDENTIALS (STORE SECURELY!) # ------------------------------- $tenantId = (Get-MgOrganization).Id Write-Host "`nšŸš€ **Application Credentials**" Write-Host "----------------------------------" Write-Host "🌐 Tenant ID: $tenantId" Write-Host "šŸ”‘ Client ID: $($app.AppId)" Write-Host "šŸ•µļøā€ā™‚ļø Client Secret: $($clientSecret.SecretText)" Write-Host "----------------------------------" #Connect-ExchangeOnline -ShowBanner:$false $scope = "https://graph.microsoft.com/.default" $tokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" # Create the body for the token request $body = @{ client_id = "$($app.AppId)" scope = $scope client_secret = "$($clientSecret.SecretText)" grant_type = "client_credentials" } # Request the token $tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenEndpoint -ContentType "application/x-www-form-urlencoded" -Body $body $accessToken = $tokenResponse.access_token # Use the token in subsequent requests $headers = @{ Authorization = "Bearer $accessToken" } $templates = Invoke-RestMethod -Method Get -Uri "https://graph.microsoft.com/beta/deviceManagement/templates" -Headers $headers # Output the templates $templates $null = Disconnect-Graph -ErrorAction SilentlyContinue $null = Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue