top of page

Microsoft Intune Graph API gebruiken met Visual Studio Code en een Entra Registered App

  • Writer: Pascal
    Pascal
  • Feb 19
  • 13 min read

Intune Graph API with Visual Studio Code and Entra App Registration
Intune Graph API with Visual Studio Code and Entra App Registration

Introduction

In this blog, I explain how to access Microsoft Intune via the Graph API using Microsoft Visual Studio Code, allowing you to create backups and upload configurations. For this, I use an Entra Registered App without relying on a client secret. Instead, I use a more secure alternative: a self-signed certificate.


Step 1: Creating a Self-Signed Certificate

A self-signed certificate enables secure connections to an Entra Registered App from a specific workstation. It offers a more secure alternative to using a client secret because:


  • A client secret can be easily stored in scripts as plain text, posing a security risk.

  • A self-signed certificate restricts access to a single workstation, whereas a client secret can be used from anywhere.

  • The certificate cannot be exported with private keys, making it harder to use on another workstation.


PowerShell Script for Generating a Self-Signed Certificate

The following PowerShell script creates a self-signed certificate and saves it in C:\temp\certs\{subjectname}. Modify the SubjectName in the script to give the certificate a clear and recognizable name.

### PowerShell Script: Secure Self-Signed Certificate for Azure App Registration

# This script creates a secure self-signed certificate for Azure App Registration.

# It uses a strong cryptographic algorithm and ensures that the private key is non-exportable.

# - Uses RSA with a key length of 4096 bits.
# - Marks the private key as non-exportable to enhance security.
# - Specifies KeySpec as Signature to avoid key duplication.
# - Sets a reasonable validity period (24 months by default).

# - Run this script with administrative privileges.
# - The certificate will be stored in the Local Machine's Personal store.
# - Use the certificate thumbprint in Azure App Registration.
#

param (
    [string]$subjectName = "{Name of cert}",
    [string]$certStore = "LocalMachine",
    [int]$validityPeriod = 24
)

$certParams = @{
    Subject = "CN=$subjectName"
    CertStoreLocation = "Cert:\CurrentUser\My"
    KeyAlgorithm = "RSA"
    KeyLength = 4096
    KeyExportPolicy = "NonExportable"
    KeySpec = "Signature"
    NotAfter = (Get-Date).AddMonths($validityPeriod)
    Provider = "Microsoft Enhanced RSA and AES Cryptographic Provider"
}

$Cert = New-SelfSignedCertificate @certParams

Write-Output "Certificate Created Successfully: $($Cert.Thumbprint)"

# Ask user if they want to export the certificate
$exportChoice = Read-Host "Do you want to export the certificate? (Yes/No)"
if ($exportChoice -eq "Yes") {
    $certFolder = "C:\temp\certs"
    if (!(Test-Path -Path $certFolder)) {
        New-Item -ItemType Directory -Path $certFolder -Force | Out-Null
    }
    
    $certExport = @{
        Cert = $Cert
        FilePath = "$($certFolder)\$($subjectName).cer"
    }
    Export-Certificate @certExport
    Write-Output "Certificate exported successfully to $($certExport.FilePath)"
} else {
    Write-Output "Certificate export skipped."
}
Use Visual Studio Code as Administrator
Create Certificate and save locally
Create Certificate and save locally

With this certificate, we can proceed to the next step: registering an App Registration in Entra and configuring the appropriate permissions.


Step 2: Entra App Registration and Configuration

In this step, we will create an Entra App Registration, assign API permissions, and link our self-signed certificate.


  1. Go to the Azure portal (https://portal.azure.com) and navigate to Microsoft Entra ID.

  2. In Entra ID, go to App registrations and click New registration.

  3. Provide a logical name for the app registration (in this example, Demo_Nubes365_API_Intune) and click Register.


Assigning API Permissions

Once the app is created, go to API Permissions. Depending on your needs, you will need to add specific permissions. For this demo, the following permissions have been assigned to the App Registration:



After adding the permissions, make sure to click "Grant admin consent" to apply them!

Entra App Registration API Permissions Consent
Entra App Registration API Permissions Consent

After granting consent for the API permissions, we proceed to Certificates & secrets to add the self-signed certificate.


  1. In the Certificates & secrets section, go to the Certificates tab and click Upload certificate.

  2. Browse to the certificate's location (C:\Temp\certs) and select the certificate file.

  3. Optionally, add a description and click Add.


The certificate is now added to the Registered App, allowing us to move on to Step 3: Authenticating with Entra App Registration and Certificate.


Add certificate to App Registration
Add certificate to App Registration

Step 3: Authenticating with Visual Studio Code and Certificate

In this step, we will authenticate using the created App Registration in combination with Visual Studio Code.


Before proceeding, we need to install a few PowerShell modules. These modules should be installed and imported in PowerShell before using VS Code.


The required modules are:


Install-Module -Name MSAL.PS -Force
Import-Module MSAL.PS
Install-Module -Name Microsoft.Graph -Force

In addition to the PowerShell modules, the REST Client extension must also be added in Visual Studio Code:


  1. Open Visual Studio Code.

  2. Go to the Extensions marketplace (Ctrl + Shift + X).

  3. Search for REST Client.

  4. Click Install.


This extension allows us to send API requests directly from Visual Studio Code, making it easier to interact with Microsoft Graph API.

VS Code REST Client
VS Code REST Client

Now that we have set up all the necessary components—including the PowerShell modules, app registration, VS Code extension, and certificate—it’s time to test whether we can successfully authenticate.


We will do this using the following PowerShell script:


<#
.SYNOPSIS
    Authenticate using an AAD app registration and a certificate to obtain a token
.DESCRIPTION
    After generating a self-signed certificate, use the MSAL.PS module to authenticate to Azure AD and obtain a token.
.EXAMPLE
    .\Get-CBATokenMSAL.ps1 -tenantId "{tenantID" -applicationId "{clientID}x" -certStore "CurrentUser" -thumbprint "{thumbprint}"
.NOTES
    Requires MSAL.PS module // Install-Module MSAL.PS -Scope CurrentUser    
#>

# Define variables at the top
$certStore = "LocalMachine"
$thumbprint = "{thumbprint}"
$tenantId = "{tenantID}"
$applicationId = "{ClientID}"

function Set-Certificate {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateSet('LocalMachine', 'CurrentUser')]
        [string]$certStore,
        
        [string]$thumbprint,
        [string]$tenantId,
        [string]$applicationId
    )

    # Function body here
}
Function Get-Token {
    # Connect to Graph and authenticate with the certificate
    Import-Module -Name MSAL.PS -Force

    $connectStringSplat = @{
        TenantId          = $tenantId
        ClientId          = $applicationId
        ClientCertificate = Get-ChildItem -Path "Cert:\$($certStore)\My\$($thumbprint)"
    }

    $authToken = Get-MsalToken @connectStringSplat
    Return $authToken
}

# Get token
Get-Token -tenantId $tenantId -applicationId $applicationId -certStore $certStore -thumbprint $thumbprint

After running this script, you should see an output like the following:

Authentication Graph VS Code with Certificate
Authentication Graph VS Code with Certificate

Step 4: Backup of Microsoft Intune

Now that we have successfully authenticated with the Graph API, we can start performing useful tasks. One of these is creating a backup of Microsoft Intune.

In this example, we will capture the configuration of various Intune components, including:


  • Device Configuration

  • Compliance Policies

  • Apps

  • Scripts

  • Remediations

  • Conditional Access


The following PowerShell script performs the backup and saves all configurations in C:\BackupIntune. The data is stored as JSON in structured folders, and a Markdown file is generated to log the date and time of the backup.


# 📌 **Intune Configuration Backup Script**
#
# This script backs up Microsoft Intune **Device Configurations** and **Compliance Policies**.
# It retrieves policies via **Microsoft Graph API** using certificate-based authentication.
#
# ---
# ## 🔹 **Prerequisites**
# - An **Azure AD App Registration** with **certificate-based authentication**.
# - The app must have the following **API Permissions**:
#   - `DeviceManagementConfiguration.Read.All`
#   - `DeviceManagementConfiguration.ReadWrite.All`
# - A valid **.PFX certificate** installed in the **Local Machine** store.
# - **Microsoft Graph PowerShell SDK** installed (`Install-Module Microsoft.Graph`).
#
# ---
# ## 🔹 **Script Overview**
# - Connects to **Microsoft Graph API** with a certificate.
# - Backs up:
#   - **Device Configurations** to `C:\backupIntune\DeviceConfigurations`
#   - **Compliance Policies** to `C:\backupIntune\CompliancePolicies`
#   - and more...
# - Saves each configuration as a **separate JSON file**.
# - Generates a **Markdown report** with timestamps.
#
# ---
# ## 🔹 **How to Use**
# 1. Update the following variables:
#    - `$tenantId`: **Azure Tenant ID**
#    - `$clientId`: **Azure App Registration Client ID**
#    - `$thumbprint`: **Thumbprint of your installed certificate**
# 2. Run the script in **PowerShell (Admin)**.
#
# ---
# ## 🔹 **Output**
# - JSON files for each **Device Configuration** and **Compliance Policy**.
# - A Markdown report with timestamp and backup details.
#
# 🚀 **Ready to automate your Intune backups!**
#
# ---

# Define variables
$tenantId = "{tenantID}"
$clientId = "{clientID}"
$thumbprint = "{thumbprint}"
$certStore = "LocalMachine"
$backupFolder = "C:\BackupIntune"

# Create the backup folder if it doesn't exist
if (-not (Test-Path -Path $backupFolder)) {
    New-Item -Path $backupFolder -ItemType Directory
}

# Define subfolders for each Intune category
$folders = @(
    "DeviceConfigurations",
    "CompliancePolicies",
    "Intents",
    "Apps",
    "Scripts",
    "Remediations",
    "FeatureUpdates",
    "Filters",
    "ConditionalAccess"
    #"AuditEvents"
)

# Create each backup subfolder if it doesn't exist
foreach ($folder in $folders) {
    $path = Join-Path -Path $backupFolder -ChildPath $folder
    if (-not (Test-Path -Path $path)) {
        New-Item -Path $path -ItemType Directory
    }
}

# Define the Graph API endpoints
$apiEndpoints = @{
    "DeviceConfigurations"   = "https://graph.microsoft.com/v1.0/deviceManagement/deviceConfigurations"
    "CompliancePolicies"     = "https://graph.microsoft.com/v1.0/deviceManagement/deviceCompliancePolicies"
    "Intents"       = "https://graph.microsoft.com/beta/deviceManagement/Intents"
    "Apps"                   = "https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps"
    "Scripts"                = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts"
    "Remediations"           = "https://graph.microsoft.com/beta/deviceManagement/deviceHealthScripts"
    "FeatureUpdates"         = "https://graph.microsoft.com/beta/deviceManagement/windowsFeatureUpdateProfiles"
    "Filters"                = "https://graph.microsoft.com/beta/deviceManagement/assignmentFilters"
    "ConditionalAccess"      = "https://graph.microsoft.com/beta/identity/conditionalAccess/policies"
    #"AuditEvents"            = "https://graph.microsoft.com/beta/deviceManagement/auditEvents"
}

# Get the certificate from the specified store
$certificate = Get-Item -Path "Cert:\$certStore\My\$thumbprint"

# Get access token using MSAL
$token = Get-MsalToken -TenantId $tenantId -ClientId $clientId -ClientCertificate $certificate

# Get the Access Token from the result
$accessToken = $token.AccessToken

# Define API headers
$headers = @{
    "Authorization" = "Bearer $accessToken"
    "Content-Type"  = "application/json"
}

# Function to create Markdown header for each run
function New-MarkdownHeader {
    $dateTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $markdownHeader = @"
# Intune Backup Report
- **Date and Time**: $dateTime
- **Backup Path**: $backupFolder
- **Backed Up Items**:
  - Device Configurations
  - Compliance Policies
  - Intents
  - Apps (Managed, Win32)
  - Scripts (Device/User)
  - Remediations (Proactive Remediations)
  - Managed Updates (Update Rings)
  - Filters
  - Conditional Access Policies
"@
    return $markdownHeader
}

# Function to retrieve and save configurations
function Get-ConfigurationBackup {
    param (
        [string]$url,
        [string]$configType
    )

    # Send the request to download configurations from Intune
    $response = Invoke-RestMethod -Uri $url -Headers $headers -Method GET

    # Check if the response contains any configurations
    if ($response.value -and $response.value.Count -gt 0) {
        # Get the backup folder path for this category
        $backupPath = Join-Path -Path $backupFolder -ChildPath $configType

        # Iterate through each configuration and save it as a separate JSON file
        foreach ($config in $response.value) {
            # Ensure DisplayName is safe for filenames (replace invalid characters)
            $displayName = $config.displayName -replace '[\\/:*?"<>|]', '_'

            # Define the timestamp for uniqueness
            $timestamp = (Get-Date).ToString("yyyyMMdd-HHmmss")

            # Define the output file path
            $outputFilePath = Join-Path -Path $backupPath -ChildPath "$displayName-$timestamp.json"

            # Convert the configuration to JSON and save to the file
            $config | ConvertTo-Json -Depth 10 | Out-File -FilePath $outputFilePath

            Write-Host "$configType backup completed for DisplayName: $($config.displayName). File saved to: $outputFilePath"
        }
    } else {
        Write-Warning "No $configType configurations found to backup. Skipping."
    }
}

# Save Markdown report
$markdownHeader = New-MarkdownHeader
$markdownFilePath = Join-Path -Path $backupFolder -ChildPath "Backup_Report_$((Get-Date).ToString('yyyyMMdd-HHmmss')).md"
$markdownHeader | Out-File -FilePath $markdownFilePath
Write-Host "Markdown report saved: $markdownFilePath"

# Iterate over all API endpoints and back up configurations
foreach ($configType in $apiEndpoints.Keys) {
    Get-ConfigurationBackup -url $apiEndpoints[$configType] -configType $configType
}

Write-Host "Intune backup completed successfully!"

After running the script, you should see an output like the following:

Result Intune Backup Script
Result Intune Backup Script

Yes, after successfully executing the script, the backup files should be stored in the C:\BackupIntune folder. The files are structured into subfolders by category and saved as JSON files. Additionally, a Markdown file is generated containing the date and time of the backup.


Intune Backup JSON files
Intune Backup JSON files

Now that we have the basics down, we can do many more interesting and powerful things. A good example of this is retrieving audit logs, which can be useful for monitoring, security, or compliance purposes.


The following script allows you to effortlessly retrieve all audit logs:

# Script to List Changes Made to Microsoft Intune Using App Registration with Self-Signed Certificate

## Prerequisites
#1. **App Registration in Azure AD**: Create an app registration and upload the self-signed certificate.
#2. **Permissions**: Ensure the app has the following required permissions to read Intune audit logs:
#   - `AuditLog.Read.All`
#3. **Install the MSAL.PS Module**: This module is required to handle authentication using a certificate. It can be installed via PowerShell.

## Description
#This PowerShell script authenticates to Microsoft Graph using an app registration with a self-signed certificate and lists changes made to Microsoft Intune. The script uses the `directoryAudits` API to fetch audit logs and displays key information about each change, such as the change ID, activity date, user, and activity details.

## How to Use
#1. Replace the placeholders for your **tenant ID**, **client ID**, and **certificate thumbprint**.
#2. Ensure the app registration has the necessary permissions to access the audit logs.
#3. Run the script in PowerShell or Visual Studio Code (VS Code). If using VS Code, ensure the PowerShell extension is installed for enhanced syntax highlighting and linting.

## Outputs
#- Displays the details of changes made to Intune, such as:
#   - **Change ID**
#   - **Activity Date**
#   - **User**
#   - **Activity**
#   - **Target Resource**
#- Optionally exports the data to a CSV file (`IntuneChanges.csv`) for further analysis.

#---

#```powershell


# Step 1: Define variables for certificate and authentication
$certStore = "LocalMachine"
$thumbprint = "<tumbprint>"
$tenantId = "<tenantID>"
$applicationId = "<ClientID>"
$graphApiEndpoint = "https://graph.microsoft.com/v1.0/auditLogs/directoryAudits"

# Step 2: Define the Set-Certificate function to handle certificate-based authentication
function Set-Certificate {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateSet('LocalMachine', 'CurrentUser')]
        [string]$certStore,
        
        [string]$thumbprint,
        [string]$tenantId,
        [string]$applicationId
    )

    # Import MSAL.PS module
    Import-Module -Name MSAL.PS -Force

    # Define the connection string for MSAL token retrieval
    $connectStringSplat = @{
        TenantId          = $tenantId
        ClientId          = $applicationId
        ClientCertificate = Get-Item -Path "Cert:\$($certStore)\My\$($thumbprint)"
    }

    # Get the authentication token using MSAL.PS
    $authToken = Get-MsalToken @connectStringSplat
    Return $authToken
}

# Step 3: Define the Get-Token function to retrieve the token
Function Get-Token {
    param (
        [string]$tenantId,
        [string]$applicationId,
        [string]$certStore,
        [string]$thumbprint
    )

    # Get token using Set-Certificate function
    $authToken = Set-Certificate -tenantId $tenantId -applicationId $applicationId -certStore $certStore -thumbprint $thumbprint
    Return $authToken
}

# Step 4: Get the token
$token = Get-Token -tenantId $tenantId -applicationId $applicationId -certStore $certStore -thumbprint $thumbprint

# Step 5: Use the token to make a GET request to the Microsoft Graph API to list the changes
$headers = @{
    "Authorization" = "Bearer $($token.AccessToken)"
    "Content-Type"  = "application/json"
}

# Step 6: Get the audit logs for Intune changes
$response = Invoke-RestMethod -Uri $graphApiEndpoint -Headers $headers -Method Get

# Step 7: Display the changes
$response.value | ForEach-Object {
    Write-Host "Change ID: $($_.id)"
    Write-Host "Activity Date: $($_.activityDateTime)"
    Write-Host "User: $($_.initiatedBy.user.displayName)"
    Write-Host "Activity: $($_.activityDisplayName)"
    Write-Host "Target: $($_.targetResources.displayName)"
    Write-Host "-------------------------------------"
}

# Step 8: Optional: Output the data to a file
$response.value | Export-Csv -Path "IntuneChanges.csv" -NoTypeInformation

One feature I personally find extremely useful is retrieving all Entra ID App Registrations. This provides a comprehensive overview of all certificates and details in a CSV file, making it easy to gain insight into the status and validity of your applications.


The following script can help you pull all Entra ID App Registrations:


# Script to List Azure AD App Registrations and Certificate Expiration Dates

## Prerequisites
#1. **App Registration in Azure AD**: The app registration used for authentication must have the required permissions, such as `Application.Read.All` to read application and certificate details.
#2. **Install the MSAL.PS Module**: This module is required to handle authentication using a certificate. It can be installed via PowerShell.

## Description
#This PowerShell script authenticates to Microsoft Graph using an app registration with a self-signed certificate. It retrieves a list of all app registrations in your Azure AD tenant and displays the expiration dates of their associated certificates.

## Outputs
#- A list of Azure AD app registrations.
#- The certificate thumbprint and expiration date for each app registration.
#- Optionally, export the data to a CSV file (`AppRegistrationsWithCerts.csv`) for further analysis.

#---

#```powershell


# Step 1: Define variables for certificate and authentication
$certStore = "LocalMachine"
$thumbprint = "<thumbprint>"
$tenantId = "<tenantID>"
$applicationId = "<ClientID>"
$graphApiEndpoint = "https://graph.microsoft.com/v1.0/applications"

# Step 2: Define the Set-Certificate function to handle certificate-based authentication
function Set-Certificate {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateSet('LocalMachine', 'CurrentUser')]
        [string]$certStore,
        
        [string]$thumbprint,
        [string]$tenantId,
        [string]$applicationId
    )

    # Import MSAL.PS module
    Import-Module -Name MSAL.PS -Force

    # Define the connection string for MSAL token retrieval
    $connectStringSplat = @{
        TenantId          = $tenantId
        ClientId          = $applicationId
        ClientCertificate = Get-Item -Path "Cert:\$($certStore)\My\$($thumbprint)"
    }

    # Get the authentication token using MSAL.PS
    $authToken = Get-MsalToken @connectStringSplat
    Return $authToken
}

# Step 3: Define the Get-Token function to retrieve the token
Function Get-Token {
    param (
        [string]$tenantId,
        [string]$applicationId,
        [string]$certStore,
        [string]$thumbprint
    )

    # Get token using Set-Certificate function
    $authToken = Set-Certificate -tenantId $tenantId -applicationId $applicationId -certStore $certStore -thumbprint $thumbprint
    Return $authToken
}

# Step 4: Get the token
$token = Get-Token -tenantId $tenantId -applicationId $applicationId -certStore $certStore -thumbprint $thumbprint

# Step 5: Use the token to make a GET request to the Microsoft Graph API to list all app registrations
$headers = @{
    "Authorization" = "Bearer $($token.AccessToken)"
    "Content-Type"  = "application/json"
}

# Step 6: Get the app registrations
$response = Invoke-RestMethod -Uri $graphApiEndpoint -Headers $headers -Method Get

# Step 7: Process each app registration and fetch certificate details
$applicationsWithCerts = @()
foreach ($app in $response.value) {
    $appName = $app.displayName
    $appId = $app.appId
    $certificates = $app.keyCredentials

    foreach ($cert in $certificates) {
        $thumbprint = $cert.keyId
        $expirationDate = $cert.endDate

        # Store the certificate info
        $applicationsWithCerts += [PSCustomObject]@{
            ApplicationName = $appName
            ApplicationId   = $appId
            CertificateThumbprint = $thumbprint
            CertificateExpirationDate = $expirationDate
        }
    }
}

# Step 8: Display the results
$applicationsWithCerts | Format-Table -Property ApplicationName, ApplicationId, CertificateThumbprint, CertificateExpirationDate

# Step 9: Optional: Output the data to a CSV file
$applicationsWithCerts | Export-Csv -Path "AppRegistrationsWithCerts.csv" -NoTypeInformation

Step 4: Upload JSON to Intune

In addition to retrieving information via Microsoft Graph, we can also push configurations to Intune using a POST request. Just as we can back up configurations in JSON format, we can also upload these JSON files directly to Intune. While there are various out-of-the-box solutions available, it’s interesting and valuable to understand how to do this manually.


Working with JSON Configurations

When uploading configurations, we make use of JSON files, each corresponding to different API endpoints (URIs). As an example, I’m using the Intune Baselines created by James Robinson. These baselines contain carefully configured JSON files and can be downloaded from his GitHub page:



For this example, I’ll work with the baseline "iOS - Baseline - BYOD - App Protection.json". I will download this file from GitHub and apply it using the following script:


# 📌 **Upload JSON Configurations to Microsoft Intune via Graph API**
# 
# This script uploads JSON configuration policies to Intune using 
# Microsoft Graph API with certificate-based authentication.
# 
# ## 🔹 **Prerequisites**
# - An **Azure AD App Registration** with **certificate-based authentication**.
# - The app must have the following **API Permissions**:
#   - `DeviceManagementConfiguration.ReadWrite.All`
# - A valid **.PFX certificate** installed in the **Local Machine** store.
# - The JSON configuration files to be uploaded.
# 
# ## 🔹 **How to Use**
# 1. Modify the script to set:
#    - `$clientId` (Azure AD App Registration Client ID)
#    - `$tenantId` (Azure Tenant ID)
#    - `$certThumbprint` (Thumbprint of your installed certificate)
# 2. Save your JSON file locally and set its path in `$jsonFilePath`
# 3. Run the script in **PowerShell (Admin)**
# 
# ---


param (
    [string]$clientId = "<ClientID>",
    [string]$tenantId = "<tenantID>",
    [string]$certThumbprint = "<Thumbprint>",
    [string]$jsonFilePath = "C:\Software\Blog\iOS - Baseline - BYOD - App Protection.json"
)

# Load the certificate from the Local Machine store
$cert = Get-Item "Cert:\LocalMachine\My\$certThumbprint"

if (-not $cert) {
    Write-Host "❌ Certificate not found. Check the thumbprint and try again." -ForegroundColor Red
    exit 1
}

# Generate JWT Client Assertion
$now = [DateTimeOffset]::Now.ToUnixTimeSeconds()
$exp = $now + (60 * 10) # Token valid for 10 minutes

$header = @{
    alg = "RS256"
    typ = "JWT"
    x5t = [System.Convert]::ToBase64String($cert.GetCertHash())
}

$payload = @{
    aud = "https://login.microsoftonline.com/$tenantId/oauth2/token"
    iss = $clientId
    sub = $clientId
    jti = [Guid]::NewGuid().ToString()
    iat = $now
    exp = $exp
}

$jwtHeader = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -Compress $header)))
$jwtPayload = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -Compress $payload)))

$jwt = "$jwtHeader.$jwtPayload"

$signature = [System.Convert]::ToBase64String(
    $cert.PrivateKey.SignData(
        [System.Text.Encoding]::UTF8.GetBytes($jwt),
        [Security.Cryptography.HashAlgorithmName]::SHA256,
        [Security.Cryptography.RSASignaturePadding]::Pkcs1
    )
)

$assertion = "$jwt.$signature"

# Get Access Token from Microsoft Identity Platform
$tokenRequest = @{
    grant_type          = "client_credentials"
    client_id           = $clientId
    client_assertion    = $assertion
    client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
    scope              = "https://graph.microsoft.com/.default"
}

$tokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -Method Post -Body $tokenRequest
$accessToken = $tokenResponse.access_token

if (-not $accessToken) {
    Write-Host "❌ Failed to obtain access token. Check authentication settings." -ForegroundColor Red
    exit 1
}

# Read JSON Configuration
$jsonContent = Get-Content -Raw -Path $jsonFilePath

if (-not $jsonContent) {
    Write-Host "❌ JSON file is empty or could not be read. Check the file path." -ForegroundColor Red
    exit 1
}

# Set API endpoint for iOS Managed App Protection
$uri = "https://graph.microsoft.com/beta/deviceAppManagement/iosManagedAppProtections"

# Upload Configuration
$headers = @{
    Authorization = "Bearer $accessToken"
    "Content-Type" = "application/json"
}

try {
    $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Post -Body $jsonContent
    Write-Host "✅ Configuration uploaded successfully: $($response.id)" -ForegroundColor Green
}
catch {
    Write-Host "❌ Error uploading configuration: $_" -ForegroundColor Red
}

This might be a longer blog, but I hope it has provided you with valuable insights and helps you in your work with Visual Studio Code, Intune, and the Graph API.

Comments


bottom of page