2023-03-14 18:10:59 +05:30
<#
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Name : Connect to MS Graph PowerShell using Certificate
Description : This script automates Azure app registration
2025-09-30 12:14:10 +05:30
Version : 1.1
website : blog . admindroid . com
2023-03-14 18:10:59 +05:30
For detailed Script execution : https : / / blog . admindroid . com / connect-to -microsoft -graph -powershell -using -certificate /
2025-09-30 12:14:10 +05:30
Change Log
~ ~ ~ ~ ~ ~ ~ ~ ~ ~
V1 . 0 ( Mar 14 , 2023 ) - File created
V1 . 1 ( Sep 30 , 2025 ) - Included -All param while retrieving app registrations to avoid app not found error .
2023-03-14 18:10:59 +05:30
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
#>
param (
$TenantID = $null ,
$ClientID = $null ,
$CertificateThumbprint = $null
)
Function ConnectMgGraphModule
{
$MsGraphModule = Get-Module Microsoft . Graph -ListAvailable
if ( $MsGraphModule -eq $null )
{
Write-host " Important: Microsoft graph module is unavailable. It is mandatory to have this module installed in the system to run the script successfully. "
$confirm = Read-Host Are you sure you want to install Microsoft graph module ? [ Y] Yes [N ] No
if ( $confirm -match " [yY] " )
{
Write-host " Installing Microsoft graph module... "
Install-Module Microsoft . Graph -Scope CurrentUser
Write-host " Microsoft graph module is installed in this machine successfully " -ForegroundColor Magenta
}
else
{
Write-host " Exiting. `n Note: Microsoft graph module must be available in your system to run the script " -ForegroundColor Red
Exit
}
}
Connect-MgGraph -Scopes " Application.ReadWrite.All,Directory.ReadWrite.All " -ErrorAction SilentlyContinue -Errorvariable ConnectionError | Out-Null
if ( $ConnectionError -ne $null )
{
Write-Host " $ConnectionError " -Foregroundcolor Red
Exit
}
Write-Host " Microsoft Graph Powershell module is connected successfully " -ForegroundColor Green
$Script:TenantID = ( Get-MgOrganization ) . Id
}
function RegisterApplication
{
Write-Progress -Activity " Registering an application "
while ( 1 )
{
$Script:AppName = Read-Host " `n Enter a name for the new App "
if ( $AppName -eq " " )
{
Write-Host " You didn't enter any name. Please provide an app name to continue. " -ForegroundColor Red
continue
}
break
}
$Script:RedirectURI = " https://login.microsoftonline.com/common/oauth2/nativeclient "
$params = @ {
DisplayName = $AppName
SignInAudience = " AzureADMyOrg "
PublicClient = @ {
RedirectUris = " $RedirectURI "
}
RequiredResourceAccess = @ (
@ {
ResourceAppId = " 00000003-0000-0000-c000-000000000000 " # Microsoft Graph Resource ID
ResourceAccess = @ (
@ {
Id = " 7ab1d382-f21e-4acd-a863-ba3e13f7da61 " #Directory.Read.All -> Id
Type = " Role " #Role -> Application permission
}
)
}
)
}
try {
$Script:App = New-MgApplication -BodyParameter $params
}
catch
{
Write-Host $_ . Exception . Message -ForegroundColor Red
CloseConnection
}
Write-Host " `n App created successfully " -ForegroundColor Green
$Script:APPObjectID = $App . Id
$Script:APPID = $App . AppId
}
function CertificateCreation
{
Write-Progress -Activity " Creating certificate "
$Script:CertificateName = " $AppName -Keycertifcate "
$Script:path = " Cert:\CurrentUser\My\ "
$Script:CertificatePath = Get-ChildItem -Path $path
$Script:Subject = " CN= $CertificateName "
try
{
$Script:Certificate = New-SelfSignedCertificate -Subject $Subject -CertStoreLocation " $path " -KeyExportPolicy Exportable -KeySpec Signature -KeyLength 2048 -HashAlgorithm SHA256
}
catch
{
Write-Host $_ . Exception . Message -ForegroundColor Red
CloseConnection
}
Write-Host " `n Certificate created successfully " -ForegroundColor Green
}
Function ImportCertificate
{
Write-Progress -Activity " Importing certificate "
$UploadCertificate = Read-Host " Enter the certificate path(For example: C:\Users\Admin\user.cer) "
try
{
$Script:Certificate = Import-Certificate -FilePath " $UploadCertificate " -CertStoreLocation " Cert:\CurrentUser\My "
}
catch
{
Write-Host $_ . Exception . Message -ForegroundColor Red
$ImportCertificateError = $True
ShowAppDetails
CloseConnection
}
Write-Host " `n Certificate imported successfully " -ForegroundColor Green
}
Function UpdateCertficateDetails
{
$GetAppInfo = Get-MgApplication -ApplicationId $APPObjectID -Property KeyCredentials
$Thumbprint = $Certificate . Thumbprint
$CertificateName = $Certificate . Subject
if ( $GetAppInfo -ne $null )
{
$NewKeys + = $GetAppInfo . KeyCredentials
UploadCertificate
# Get new certificate key credentials after updating new certificate
Start-Sleep -Milliseconds 10000 # Takes time to update certificate to an application
while ( 1 )
{
$GetAppInfo = Get-MgApplication -ApplicationId $APPObjectID -Property KeyCredentials
if ( $GetAppInfo . KeyCredentials -eq $null )
{
Write-Host " The certificate is not yet uploaded to an application. Waiting for 3 seconds... " -ForegroundColor Yellow
Start-Sleep -Seconds 3
Continue
}
break
}
$NewKeys + = $GetAppInfo . KeyCredentials #new keycredential
Update-MgApplication -ApplicationId $APPObjectID -KeyCredentials $NewKeys
}
else
{
Write-Host " The application does not exist. Please try again with a different name. " -ForegroundColor Green
}
}
function UploadCertificate
{
Write-Progress -Activity " Uploading certificate "
$KeyCredential = @ {
Type = " AsymmetricX509Cert " ;
Usage = " Verify " ;
key = $Certificate . RawData
}
Update-MgApplication -ApplicationId $APPObjectID -KeyCredentials $KeyCredential -ErrorAction SilentlyContinue -ErrorVariable ApplicationError
if ( $ApplicationError -ne $null )
{
Write-Host " $ApplicationError " -ForegroundColor Red
CloseConnection
}
Write-Host " `n Certificate uploaded successfully " -ForegroundColor Green
$Script:Thumbprint = $Certificate . Thumbprint
}
function SecureCertificate
{
Write-Progress -Activity " Exporting pfx certificate "
$Script:CertificateLocation = Get-Location
$Script:CertificateLocation = " $CertificateLocation \ $CertificateName .pfx "
$GetPassword = Read-Host " `n Please enter password to secure your certificate "
try
{
$script:ExportError = " False "
$MyPwd = ConvertTo-SecureString -String " $GetPassword " -Force -AsPlainText
Export-PfxCertificate -Cert " Cert:\CurrentUser\My\ $Thumbprint " -FilePath " $CertificateLocation " -Password $MyPwd | Out-Null
}
catch
{
$script:ExportError = " True "
Write-Host $_ . Exception . Message -ForegroundColor Red
return
}
Write-Host " `n Pfx file exported successfully " -ForegroundColor Green
}
function GrantPermission
{
Write-Progress -Activity " Granting admin consent... "
Start-Sleep -Seconds 20
$Script:ClientID = $App . AppId
$URL = " https://login.microsoftonline.com/ $TenantID /adminconsent "
$Url = " $URL ` ?client_id= $ClientID "
Write-Host " `n MS Graph requires admin consent to access data. Please grant access to the application " -ForegroundColor Cyan
While ( 1 )
{
Add-Type -AssemblyName System . Windows . Forms
$script:mainForm = New-Object System . Windows . Forms . Form -Property @ {
Width = 680
Height = 640
}
$script:webBrowser = New-Object System . Windows . Forms . WebBrowser -Property @ {
Width = 680
Height = 640
URL = $URL
}
$document = {
if ( $webBrowser . Url -eq " $RedirectURI ` ?admin_consent=True&tenant= $TenantID " -or $webBrowser . Url -match " error " )
{
$mainForm . Close ( )
}
if ( $webBrowser . DocumentText . Contains ( " We received a bad request " ) )
{
$mainForm . Close ( )
}
}
$webBrowser . ScriptErrorsSuppressed = $true
$webBrowser . Add_DocumentCompleted ( $document )
$mainForm . Controls . Add ( $webBrowser )
$mainForm . Add_Shown ( { $mainForm . Activate ( ) ; $mainForm . Refresh ( ) } )
[ void ] $mainForm . ShowDialog ( )
if ( $webBrowser . Url . AbsoluteUri -eq " $RedirectURI ` ?admin_consent=True&tenant= $TenantID " )
{
Write-Host " `n Admin consent granted successfully " -ForegroundColor Green
break
}
else
{
Write-Host " `n Admin consent failed. " -ForegroundColor Red
$Confirm = Read-Host " Do you want to retry admin consent? [Y] Yes [N] No "
if ( $confirm -match " [yY] " )
{
Continue
}
else
{
Write-Host " You can grant admin consent manually in azure portal. " -ForegroundColor Yellow
break
}
}
}
}
Function ShowAppDetails
{
Write-Host " `n App info: " -ForegroundColor Magenta
2025-09-30 12:14:10 +05:30
$GetAppInfo = Get-MgApplication -All | ? { $_ . AppId -eq " $APPID " }
2023-03-14 18:10:59 +05:30
$Owner = Get-MgApplicationOwner -ApplicationId $GetAppInfo . Id | Select-Object -ExpandProperty AdditionalProperties
$Script:CertificateList = $GetAppInfo . KeyCredentials
$AppInfo = [ pscustomobject ] @ { 'App Name' = $GetAppInfo . DisplayName
'Application(Client) Id' = $GetAppInfo . AppId
'Object Id' = $GetAppInfo . Id
'Tenant Id' = $TenantID
'CertificateThumbprint' = $Thumbprint
'App Created Date Time' = $GetAppInfo . CreatedDateTime
'App Owner' = ( @ ( $Owner . displayName ) | Out-String ) . Trim ( )
}
if ( $ImportCertificateError -eq $True )
{
$AppInfo | select 'App Name' , 'Application(Client) Id' , 'Object Id' , 'Tenant Id' , 'App Created Date Time' , 'App Owner' | fl
Write-Host " You can copy & save " -NoNewline
Write-Host " Client Id " -ForegroundColor Cyan -NoNewline
Write-Host " and try again to add certificate to your application. "
Return
}
if ( $Action -ne 5 )
{
$AppInfo | select 'App Name' , 'Application(Client) Id' , 'Object Id' , 'Tenant Id' , 'CertificateThumbprint' , 'App Created Date Time' , 'App Owner' | fl
Write-Host " You can copy and save " -NoNewline
Write-Host " Client Id, Tenant Id, Certificate ThumbPrint " -ForegroundColor Cyan -NoNewline
Write-Host " as they will be required to connect to MS Graph PowerShell using certificate-based authentication. "
}
else
{
$AppInfo | select 'App Name' , 'Application(Client) Id' , 'Object Id' , 'Tenant Id' , 'App Created Date Time' , 'App Owner' | fl
Write-Host " App certificates : "
$CertificateList | Format-Table -Property DisplayName , KeyId , StartdateTime , EndDateTime
}
}
Function RevokeCertificate
{
Write-Progress -Activity " Revoking certificate "
$NewKeys = @ ( )
$APPID = Read-Host " Enter an application ID(Client ID) you want to revoke the certificate for that app "
2025-09-30 12:14:10 +05:30
$GetAppInfo = Get-MgApplication -All | ? { $_ . AppId -eq " $APPID " }
2023-03-14 18:10:59 +05:30
if ( $GetAppInfo -ne $null )
{
ShowAppDetails
$KeyId = Read-Host " `n Enter the certificate key ID to revoke that certificate "
if ( $GetAppInfo . KeyCredentials . KeyId -notcontains ( $KeyId ) )
{
Write-Host " Certificate not found " -ForegroundColor Red
CloseConnection
}
foreach ( $List in $CertificateList )
{
if ( $List . KeyId -eq " $KeyId " )
{
continue
}
$NewKeys + = $List
}
Update-MgApplication -ApplicationId $GetAppInfo . Id -KeyCredentials $NewKeys
Write-Host " `n Certificate revoked successfully " -ForegroundColor Green
}
else
{
Write-Host " The application does not exist. " -ForegroundColor Red
CloseConnection
}
}
Function ConnectApplication
{
Write-Progress -Activity " Connecting MS Graph "
try
{
if ( $ParameterPassed -eq " False " )
{
$TenantID = Read-Host " `n Please provide the tenant ID of the application "
$ClientID = Read-Host " Please provide the client ID of the application "
While ( $true ) {
$CertificatePath = Read-Host " Please provide certificate path(.cer or .pfx) "
$TestPath = Test-Path -Path $CertificatePath -PathType Leaf
if ( $TestPath -eq $false )
{
Write-Host " The certificate file could not be found. " -ForegroundColor Red
Continue
}
}
$CheckExtension = ( Get-ChildItem " $CertificatePath " ) . Extension
if ( $CheckExtension -eq " .pfx " )
{
$Password = Read-Host " Please enter password to import certificate "
$MyPwd = ConvertTo-SecureString -String " $Password " -Force -AsPlainText
$LoadCertificate = Import-PfxCertificate -FilePath $CertificatePath -CertStoreLocation " Cert:\CurrentUser\My " -Password $MyPwd
}
else
{
$LoadCertificate = Import-Certificate -FilePath " $CertificatePath " -CertStoreLocation " Cert:\CurrentUser\My "
}
$CertificateThumbprint = $LoadCertificate . Thumbprint
}
}
catch
{
Write-Host $_ . Exception . Message -ForegroundColor Red
Exit
}
Connect-MgGraph -TenantId $TenantID -ClientId $ClientID -CertificateThumbprint $CertificateThumbprint -ErrorAction SilentlyContinue -ErrorVariable ApplicationConnectionError
if ( $ApplicationConnectionError -ne $null )
{
Write-Host $ApplicationConnectionError -ForegroundColor Red
Exit
}
Get-MgContext
}
function CloseConnection
{
Disconnect-MgGraph | Out-Null
Exit
}
$ParameterPassed = " False "
if ( $TenantID -ne $null -and $ClientID -ne $null -and $CertificateThumbprint -ne $null )
{
$ParameterPassed = " True "
ConnectApplication
Exit
}
Write-Host " `n We can perform below operations. " -ForegroundColor Cyan
Write-Host " 1. Register an app with new certificate " -ForegroundColor Yellow -NoNewline
Write-Host " (Creates application - >Adds new certificate -> Grants admin consent -> Exports certificate) " -ForegroundColor White
Write-Host " 2. Register an app with existing certificate " -ForegroundColor Yellow -NoNewline
Write-Host " (Creates application -> Adds existing certificate -> Grants admin consent) " -ForegroundColor White
Write-Host " 3. Add certificate to an existing application " -ForegroundColor Yellow
Write-Host " 4. Connect MgGraph " -ForegroundColor Yellow
Write-Host " 5. Revoke certificate " -ForegroundColor Yellow
$Action = Read-Host " `n Please choose the action to continue "
switch ( $Action ) {
1 {
Write-Host " `n Connecting to MS Graph to create a application... "
ConnectMgGraphModule
RegisterApplication
CertificateCreation
UploadCertificate
SecureCertificate
GrantPermission
ShowAppDetails
if ( $ExportError -ne " True " )
{
Write-Host " `n Your Pfx certificate is available in $CertificateLocation " -ForegroundColor Green
}
break
}
2 {
Write-Host " `n Connecting to MS Graph to create a application.. "
ConnectMgGraphModule
RegisterApplication
ImportCertificate
UploadCertificate
GrantPermission
ShowAppDetails
break
}
3 {
ConnectMgGraphModule
$APPID = Read-Host " Enter the application id(Client id) of the app: "
2025-09-30 12:14:10 +05:30
$AppInfo = Get-MgApplication -All | ? { $_ . AppId -eq " $APPID " }
2023-03-14 18:10:59 +05:30
if ( $AppInfo -eq $null )
{
Write-Host " Application not found. " -ForegroundColor Red
CloseConnection
}
$AppName = $AppInfo . DisplayName
$APPObjectID = $AppInfo . Id
$confirm = Read-Host Are you sure you want to create new certificate ? [ Y] Yes [N ] No . Select '"No"' to import existing certificate .
if ( $confirm -match " [yY] " )
{
CertificateCreation
}
else
{
ImportCertificate
}
UpdateCertficateDetails
ShowAppDetails
break
}
4 {
ConnectApplication
Exit
}
5 {
ConnectMgGraphModule
RevokeCertificate
break
}
Default {
Write-Host " No Action Found " -ForegroundColor Red
Exit
}
}
CloseConnection