# 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 ExchangeOnlineManagement)) { 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", "Policy.ReadWrite.AuthenticationMethod" # ------------------------------- # Check for existing apps with the same name # ------------------------------- Write-Host "šŸ” Checking for existing applications named '$Name'..." $existingApps = Get-MgApplication -All | Where-Object { $_.DisplayName -eq $Name } if ($existingApps) { Write-Host "āš ļø Found $($existingApps.Count) existing application(s) with this name. Removing them..." foreach ($existingApp in $existingApps) { try { # Remove associated Service Principal first $sp = Get-MgServicePrincipal -Filter "AppId eq '$($existingApp.AppId)'" -ErrorAction SilentlyContinue if ($sp) { Remove-MgServicePrincipal -ServicePrincipalId $sp.Id -Confirm:$false Write-Host " āžœ Removed Service Principal: $($sp.Id)" } # Remove the application Remove-MgApplication -ApplicationId $existingApp.Id -Confirm:$false Write-Host " āžœ Removed Application: $($existingApp.Id)" } catch { Write-Warning " āŒ Failed to remove application $($existingApp.Id): $_" } } # Optional pause to ensure deletion propagates Write-Host "ā³ Waiting for application deletion..." Start-Sleep -Seconds 10 } else { Write-Host "āœ… No existing applications found with name '$Name'." } # 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 Write-Host "ā³ Waiting for application propagation..." Start-Sleep -Seconds 10 # Create 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 "----------------------------------" $null = Disconnect-Graph -ErrorAction SilentlyContinue $null = Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue