Skip to main content
Below is a detailed, customer-ready document you can use internally, send to an admin, or adapt for public documentation.

Overview

This document explains how to automatically configure Microsoft Entra ID so TruU can securely integrate with Microsoft Graph using an application registration, application permissions, admin consent, and a client secret. The automation script creates a new Entra application named TruUIDS, assigns the required Microsoft Graph application permissions, grants admin consent, generates a client secret, and then outputs the credentials needed to complete the TruU directory configuration. This approach is intended to reduce manual setup effort, standardize configuration, and ensure the Entra directory is prepared consistently for TruU’s integration requirements.

Required Permissions Granted by the Script

The script assigns the following Microsoft Graph application permissions:

Prerequisites

Before running the script, confirm the following:

Administrative Requirements

  • The person running the script must be able to sign in as a Global Administrator, or otherwise hold sufficient privilege to create applications and grant admin consent for Microsoft Graph application permissions.
  • The tenant must allow Microsoft Graph PowerShell access.

PowerShell Requirements

  • PowerShell must be installed.
  • The Microsoft Graph PowerShell SDK must be installed.

Security and Process Requirements

  • The generated client secret is shown only once.
  • The output should be copied immediately into a secure secret store or password vault.
  • The organization should determine who owns rotation of the client secret before deployment.

Script

# Define the application name
$appName = "TruUIDS"
# Define the required Application permissions (app-only)
$permissionNames = @(
    "Application.Read.All",
    "Device.Read.All",
    "Group.Read.All",
    "Directory.Read.All",
    "User.Read.All",
    "UserAuthenticationMethod.Read.All",
    "UserAuthenticationMethod.ReadWrite.All"
)

Write-Host "Connecting to Microsoft Graph and prompting for Global Admin logon..." -ForegroundColor Cyan

# Connect to the Microsoft Graph API with required scopes to manage applications and app role assignments
# This will open a browser window for you to log in as a Global Administrator and consent
Connect-MgGraph -Scopes "Application.ReadWrite.All", "AppRoleAssignment.ReadWrite.All"

# Check if connection was successful
if (-not (Get-MgContext)) {
    Write-Host "Could not connect to Microsoft Graph. Exiting script." -ForegroundColor Red
    exit
}

Write-Host "Connected successfully." -ForegroundColor Green

# Get the Service Principal for Microsoft Graph (resource app) - needed for building RequiredResourceAccess
$graphServicePrincipal = Get-MgServicePrincipal -Filter "DisplayName eq 'Microsoft Graph'"
$graphResourceId = $graphServicePrincipal.AppId  # Microsoft Graph AppId

# Build the list of ResourceAccess (permissions) for the application manifest
Write-Host "Building permission list for application manifest..." -ForegroundColor Cyan
$resourceAccessList = @()

foreach ($permissionName in $permissionNames) {
    $appRole = $graphServicePrincipal.AppRoles | Where-Object { $_.Value -eq $permissionName }

    if ($appRole) {
        $resourceAccessList += @{
            Id   = $appRole.Id
            Type = "Role"  # "Role" = Application permission, "Scope" = Delegated permission
        }
        Write-Host "  Added '$permissionName' to manifest" -ForegroundColor Gray
    } else {
        Write-Host "  Could not find App Role for '$permissionName'. Skipping..." -ForegroundColor Yellow
    }
}

# Define RequiredResourceAccess for Microsoft Graph
$requiredResourceAccess = @(
    @{
        ResourceAppId  = $graphResourceId
        ResourceAccess = $resourceAccessList
    }
)

# 1. Create the new application registration with RequiredResourceAccess (Configured Permissions)
Write-Host "Creating new application registration: $appName" -ForegroundColor Cyan
try {
    $app = New-MgApplication -DisplayName $appName -RequiredResourceAccess $requiredResourceAccess
    Write-Host "Application '$appName' created successfully with AppId: $($app.AppId)" -ForegroundColor Green
} catch {
    Write-Host "Failed to create application. Check if an app with the same name exists or if you have sufficient permissions." -ForegroundColor Red
    Write-Error $_.Exception.Message
    exit
}

# 2. Create a Service Principal for the application (required for granting consent)
Write-Host "Creating Service Principal for the application..." -ForegroundColor Cyan
$servicePrincipal = New-MgServicePrincipal -AppId $app.AppId
Write-Host "Service Principal created successfully." -ForegroundColor Green

# 3. Grant admin consent for each Application permission
Write-Host "Granting admin consent for Application permissions..." -ForegroundColor Cyan

foreach ($permissionName in $permissionNames) {
    Write-Host "  Granting consent for '$permissionName'..." -ForegroundColor Cyan

    # Get the App Role ID for the Application permission
    $appRole = $graphServicePrincipal.AppRoles | Where-Object { $_.Value -eq $permissionName }

    if (-not $appRole) {
        Write-Host "  Could not find the App Role for '$permissionName'. Skipping..." -ForegroundColor Yellow
        continue
    }

    # Define the app role assignment parameters
    $appRoleAssignmentParams = @{
        PrincipalId = $servicePrincipal.Id
        ResourceId  = $graphServicePrincipal.Id
        AppRoleId   = $appRole.Id
    }

    # Grant the Application permission (admin consent)
    try {
        New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $servicePrincipal.Id -BodyParameter $appRoleAssignmentParams
        Write-Host "  Admin consent granted for '$permissionName'" -ForegroundColor Green
    } catch {
        Write-Host "  Failed to grant '$permissionName'. Error: $($_.Exception.Message)" -ForegroundColor Red
    }
}

# 4. Generate a client secret for the application
Write-Host "Generating client secret..." -ForegroundColor Cyan

$secretParams = @{
    PasswordCredential = @{
        DisplayName = "Auto-generated secret"
        EndDateTime = (Get-Date).AddYears(1)  # Secret valid for 1 year
    }
}

try {
    $secret = Add-MgApplicationPassword -ApplicationId $app.Id -BodyParameter $secretParams
    Write-Host "Client secret generated successfully." -ForegroundColor Green
} catch {
    Write-Host "Failed to generate client secret. Error: $($_.Exception.Message)" -ForegroundColor Red
    exit
}

# Get Tenant ID
$context = Get-MgContext
$tenantId = $context.TenantId

# Display application credentials
Write-Host ""
Write-Host "=============================================" -ForegroundColor Cyan
Write-Host "       APPLICATION CREDENTIALS               " -ForegroundColor Cyan
Write-Host "=============================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Application Name  : $appName" -ForegroundColor White
Write-Host "Tenant ID         : $tenantId" -ForegroundColor White
Write-Host "Client ID (AppId) : $($app.AppId)" -ForegroundColor White
Write-Host "Client Secret     : $($secret.SecretText)" -ForegroundColor Yellow
Write-Host "Secret Expires    : $($secret.EndDateTime)" -ForegroundColor White
Write-Host ""
Write-Host "=============================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "IMPORTANT: Copy the Client Secret now! It will not be shown again." -ForegroundColor Red
Write-Host ""

Write-Host "Script finished." -ForegroundColor Green