В этой статье я покажу, как получить access token для Graph API. Ранее Microsoft предлагала разные API для разных конечных точек и для разных контекстов — AzureAD, Office 365, Sharepoint Online и т.д. Сейчас эти API считаются устаревшими, и всех их заменит MS Graph.
Важно помнить, что для подключения к AAD использовались две конечные точки — https://graph.windows.net (AAD Graph) и https://graph.microsoft.com (MS Graph). Их же используются Powershell командлеты из модулей AzureAD/AzureADPreview и MSGraph соответственно.
Azure AD Graph перестанет работать 30 июня 2022 года!
Тем не менее, в примере ниже я покажу подключение к обоим API. Для этого существует несколько способов.
Connect-AzAccount -Identity -AccountId <ClientID>
$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.microsoft.com").AccessToken
$aadToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.windows.net").AccessToken
Write-Output "Hi I'm $($context.Account.Id)"
Connect-AzureAD -AadAccessToken $aadToken -AccountId $context.Account.Id -TenantId $context.tenant.id
Connect-MgGraph -AccessToken $graphToken
Connect-AzAccount -Identity -AccountId <ClientID>
$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.microsoft.com").AccessToken
$aadToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.windows.net").AccessToken
Write-Output "Hi I'm $($context.Account.Id)"
Connect-AzureAD -AadAccessToken $aadToken -AccountId $context.Account.Id -TenantId $context.tenant.id
Connect-MgGraph -AccessToken $graphToken
Connect-AzAccount -Identity -AccountId <ClientID>
$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.microsoft.com").AccessToken
$aadToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.windows.net").AccessToken
Write-Output "Hi I'm $($context.Account.Id)"
Connect-AzureAD -AadAccessToken $aadToken -AccountId $context.Account.Id -TenantId $context.tenant.id
Connect-MgGraph -AccessToken $graphToken
В примере выше мы подключаемся в Azure с неким аккаунтом. Для более интересной ситуации я использовал подключение с User Managed Identity (UMI) по его ClientID. В простейшем случае это будет аккаунт пользвоателя.
Подключившись, мы устанавливаем контекст и для каждого API получаем по токену. После этого полученные access tokens можно использовать в командлетах Powershell для подключения к AAD и Ms Graph.
Другой способ — использование REST API запросов. На следующем примере я покажу подключение с помощью SPN приложения. используется получение токена в режиме client_credentials flow. Пользователь в конце логинится, используя delegated access права приложения.
function Get-GraphToken {
Param([string]$ApplicationId, $TenantName, $AppPassword)
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
client_id = $ApplicationId
client_secret = $AppPassword
scope = "https://graph.microsoft.com/.default"
grant_type = 'client_credentials'
$token = (Invoke-WebRequest -Method POST -Body $Body -ContentType 'application/x-www-form-urlencoded' -Uri $Url).Content `
| Select-Object -ExpandProperty access_token
$token = Get-GraphToken -ApplicationId $ApplicationID -TenantName $tenantID -AppPassword $ClientKey
Connect-AzureAD -TenantId $tenantId -AadAccessToken $token -AccountId user@domain.com
function Get-GraphToken {
Param([string]$ApplicationId, $TenantName, $AppPassword)
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
$Body = @{
client_id = $ApplicationId
client_secret = $AppPassword
scope = "https://graph.microsoft.com/.default"
grant_type = 'client_credentials'
}
$token = (Invoke-WebRequest -Method POST -Body $Body -ContentType 'application/x-www-form-urlencoded' -Uri $Url).Content `
| ConvertFrom-Json `
| Select-Object -ExpandProperty access_token
return $token
}
$token = Get-GraphToken -ApplicationId $ApplicationID -TenantName $tenantID -AppPassword $ClientKey
Connect-AzureAD -TenantId $tenantId -AadAccessToken $token -AccountId user@domain.com
function Get-GraphToken {
Param([string]$ApplicationId, $TenantName, $AppPassword)
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
$Body = @{
client_id = $ApplicationId
client_secret = $AppPassword
scope = "https://graph.microsoft.com/.default"
grant_type = 'client_credentials'
}
$token = (Invoke-WebRequest -Method POST -Body $Body -ContentType 'application/x-www-form-urlencoded' -Uri $Url).Content `
| ConvertFrom-Json `
| Select-Object -ExpandProperty access_token
return $token
}
$token = Get-GraphToken -ApplicationId $ApplicationID -TenantName $tenantID -AppPassword $ClientKey
Connect-AzureAD -TenantId $tenantId -AadAccessToken $token -AccountId user@domain.com
И есть еще один трюк — извлечение токена прямо из запроса к Azure, т.к. приложения можно читать не только через AAD, но и Az, т.к. при этом в ответ от Az включается токен для нужно скоупа (graph.windows.net).
$TenantId = "You tenant here"
$ApplicationId = "Your application id to login here"
$ServicePrincipalKey = ConvertTo-SecureString -String "Put a key of the application here" -AsPlainText -Force
Write-Information "Login to Azure as SP: $ApplicationId"
$AzureADCred = New-Object System.Management.Automation.PSCredential($ApplicationId, $ServicePrincipalKey)
Add-AzAccount -ServicePrincipal -Credential $AzureADCred -TenantId $TenantId
# Get application with Azure because this will fill the tokencache for AzureAD as well (hidden feature).
Write-Information "Get application with Azure: $ObjectIdOfApplicationToChange"
Get-AzADApplication -ObjectId $ObjectIdOfApplicationToChange
$ctx = Get-AzureRmContext
$cacheItems = $cache.ReadItems()
$token = ($cacheItems | where { $_.Resource -eq "https://graph.windows.net/" })
Write-Information "Login to AzureAD with same SP: $ApplicationId"
Connect-AzureAD -AadAccessToken $token.AccessToken -AccountId $ctx.Account.Id -TenantId $ctx.Tenant.Id
$TenantId = "You tenant here"
$ApplicationId = "Your application id to login here"
$ServicePrincipalKey = ConvertTo-SecureString -String "Put a key of the application here" -AsPlainText -Force
Write-Information "Login to Azure as SP: $ApplicationId"
$AzureADCred = New-Object System.Management.Automation.PSCredential($ApplicationId, $ServicePrincipalKey)
Add-AzAccount -ServicePrincipal -Credential $AzureADCred -TenantId $TenantId
# Get application with Azure because this will fill the tokencache for AzureAD as well (hidden feature).
Write-Information "Get application with Azure: $ObjectIdOfApplicationToChange"
Get-AzADApplication -ObjectId $ObjectIdOfApplicationToChange
$ctx = Get-AzureRmContext
$cache = $ctx.TokenCache
$cacheItems = $cache.ReadItems()
$token = ($cacheItems | where { $_.Resource -eq "https://graph.windows.net/" })
Write-Information "Login to AzureAD with same SP: $ApplicationId"
Connect-AzureAD -AadAccessToken $token.AccessToken -AccountId $ctx.Account.Id -TenantId $ctx.Tenant.Id
$TenantId = "You tenant here"
$ApplicationId = "Your application id to login here"
$ServicePrincipalKey = ConvertTo-SecureString -String "Put a key of the application here" -AsPlainText -Force
Write-Information "Login to Azure as SP: $ApplicationId"
$AzureADCred = New-Object System.Management.Automation.PSCredential($ApplicationId, $ServicePrincipalKey)
Add-AzAccount -ServicePrincipal -Credential $AzureADCred -TenantId $TenantId
# Get application with Azure because this will fill the tokencache for AzureAD as well (hidden feature).
Write-Information "Get application with Azure: $ObjectIdOfApplicationToChange"
Get-AzADApplication -ObjectId $ObjectIdOfApplicationToChange
$ctx = Get-AzureRmContext
$cache = $ctx.TokenCache
$cacheItems = $cache.ReadItems()
$token = ($cacheItems | where { $_.Resource -eq "https://graph.windows.net/" })
Write-Information "Login to AzureAD with same SP: $ApplicationId"
Connect-AzureAD -AadAccessToken $token.AccessToken -AccountId $ctx.Account.Id -TenantId $ctx.Tenant.Id