Как я могу использовать удостоверение управляемой службы, используя локальные учетные данные Azure в Visual Studio с расширенными разрешениями для Microsoft Graph - PullRequest
0 голосов
/ 12 июня 2019

Я использую API-интерфейс Graph для извлечения пользовательских изображений и элементов списка SharePoint и аутентификации с использованием идентификатора управляемой службы. Я успешно смог добавить необходимые разрешения для идентификации своей службы с помощью powershell.

<#
ERRORS OUT BUT WORKS. YOU CAN VALIDATE BY USING THE GRAPH EXPLORER TO CALL: 
https://graph.microsoft.com/beta/servicePrincipals/{msiObjectId}/appRoleAssignedTo
NOTE: Get-AzureADServiceAppRoleAssignedTo DOES NOT WORK, MUST USE GRAPH EXPLORER FOR VALIDATION
#>

Connect-AzureAD

$msiObjectId = "12345678-1234-1234-1234-123456789101"
$app_name = "Microsoft Graph"
$role_names = @("Sites.Read.All", "User.Read.All", "Directory.Read.All")

$sp = Get-AzureADServicePrincipal -Filter "displayName eq '$app_name'"

$role_names | foreach {
    $role_name = $_
    $appRole = $sp.AppRoles | Where-Object { ($_.DisplayName -eq $role_name) -or ($_.Value -eq $role_name) }
    New-AzureADServiceAppRoleAssignment -ObjectId $msiObjectId -PrincipalId $msiObjectId -ResourceId $sp.ObjectId -Id $appRole.Id
}

Disconnect-AzureAD

Это ошибка, но добавляет разрешения и прекрасно работает, когда я публикую приложение в службе Azure, назначенной идентификатору службы.

Я использую Microsoft.Azure.Services.AppAuthentication для получения токена и выполнения вызовов.

using Microsoft.Azure.Services.AppAuthentication;
...
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await new AzureServiceTokenProvider().GetAccessTokenAsync("00000003-0000-0000-c000-000000000000"));
...

Проблема в локальном развитии, это связано с моими полномочиями. Это успешно получает токен, который имеет некоторый базовый доступ к графу, такой как / me и / user basic, но когда я пытаюсь получить список или изображение пользователя, я получаю следующую ошибку:

{
  "error": {
    "code": "accessDenied",
    "message": "The caller does not have permission to perform the action.",
    "innerError": {
      "request-id": "55555555-1234-1234-1234-123456789101",
      "date": "2019-06-12T17:05:31"
    }
  }
}

Я пытался использовать свой собственный идентификатор объекта вместо $msiObjectId в коде PowerShell точно так же, как он есть, а также пытался изменить New-AzureADServiceAppRoleAssignment на New-AzureADUserAppRoleAssignment, но ни один из них не работал. Я также попробовал все, что мог в пользовательском интерфейсе, и не нашел способа добавить разрешения, и попытался https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize?client_id=00000003-0000-0000-c000-000000000000&scope=offline_access%20User.Read.All%20Sites.Read.All, который выдает ошибку об отсутствии URL-адреса ответа, а также не работает.

Я думаю, что мне может понадобиться добавить некоторые разрешения делегатов для моей учетной записи вместо назначений ролей приложений, но я не могу найти способ сделать это. Я могу видеть разрешения, используя $sp.Oauth2Permissions, но не могу найти способ предоставить себе эти разрешения.

Можно ли это сделать, и если да, то как?

В основном мне нужно, чтобы мои учетные данные (без приложения) имели как минимум доступ "Sites.Read.All" и "User.Read.All" к Microsoft Graph (GraphAggregatorService) при использовании new AzureServiceTokenProvider().GetAccessTokenAsync())

Ответы [ 2 ]

1 голос
/ 12 июня 2019

Я столкнулся с этой проблемой, когда делал свои примеры использования AzureServiceTokenProvider для локального вызова своих собственных API.Проблема, как вы заметили, в том, что токен, полученный локально, является делегированным токеном.В Azure это токен только для приложения.

Вы не можете назначать пользователю разрешения на приложения, если только в appRoles не разрешены типы элементов, включающие как пользователя, так и приложение.И это было бы довольно странно.MS Graph API этого не делает.

Так что вам нужен токен только для приложения.

Локально, вам лучше всего использовать MSAL для получения токена с учетными данными клиента и использоватьAzureServiceTokenProvider только в Azure.Затем вы получите токен, аналогичный тому, который вы получаете в Azure, с разрешениями приложений и тому подобным.

0 голосов
/ 13 июня 2019

@ juunas Спасибо за подтверждение.В итоге я зарегистрировал приложение специально для своей локальной среды разработки, которое я буду использовать для локального получения токенов.Я храню свой идентификатор клиента и секрет клиента в своих пользовательских секретах (secrets.json), чтобы исключить их из своего развертывания, и использую наличие обоих этих значений, чтобы определить, использовать ли токен приложения с этими идентификаторами или идентификатор службы..

private async Task<string> GetDevTokenAsync()
{
    var clientID = _configuration.GetValue<string>("AppSettings:ClientID") ?? _configuration.GetValue<string>("Authentication:AppSettings:ClientID");
    var clientSecret = _configuration.GetValue<string>("AppSettings:ClientSecret") ?? _configuration.GetValue<string>("Authentication:AppSettings:ClientSecret");
    if (string.IsNullOrWhiteSpace(clientID) || string.IsNullOrWhiteSpace(clientSecret))
        return null;

    using (var RestClient = new HttpClient())
    {
        var content = new FormUrlEncodedContent(
            new[]
                {
                    new KeyValuePair<string, string>("client_id", clientID),
                    new KeyValuePair<string, string>("client_secret", clientSecret),
                    new KeyValuePair<string, string>("scope", "https://graph.microsoft.com/.default"),
                    new KeyValuePair<string, string>("grant_type", "client_credentials")
                }
                );
        var response = await RestClient.PostAsync($"https://login.microsoftonline.com/{_tenantId}/oauth2/v2.0/token", content);
        return !response.IsSuccessStatusCode ? null : JObject.Parse(await response.Content.ReadAsStringAsync())?.Property("access_token")?.Value?.ToString();
    }
}
...

request.Headers.Authorization = new AuthenticationHeaderValue("Bearer",
    await GetDevTokenAsync() ?? 
    await new AzureServiceTokenProvider().GetAccessTokenAsync("00000003-0000-0000-c000-000000000000"));
...
...