Создать Microsoft Graph GraphServiceClient с пользователем / паролем без присмотра

Я создаю консольное приложение, которое подключается к Microsoft Graph с помощью Microsoft Graph API (как показано на https://github.com/microsoftgraph/console-csharp-connect-sample). Все работает нормально, но мне интересно, есть ли способ, с помощью которого я могу аутентифицировать пользователя (когда я уже знаю его пользователь / пароль) без необходимости вручную вводить свои учетные данные в окне "Вход в свою учетную запись", отображаемом на рабочий стол. Идея заключается в том, чтобы запустить приложение без присмотра, поэтому пользователю не нужно вводить свои учетные данные при запуске приложения. Я не могу найти соответствующую информацию по этому вопросу. Это вообще возможно?

РЕДАКТИРОВАТЬ

Перейдя по ссылке @DanSilver, опубликованной о получении доступа без пользователя, я попробовал пример, предложенный в этой ссылке ( https://github.com/Azure-Samples/active-directory-dotnet-daemon-v2). Хотя это приложение MVC, которое заставляет пользователей проходить аутентификацию (именно то, чего я хотел избежать), мне удалось использовать часть кода аутентификации в этом примере с моим консольным приложением. После предоставления авторизации приложению вручную через запрос к https://login.microsoftonline.com/myTenantId/adminconsent я могу создать GraphServiceClient в своем консольном приложении, которое подключается к Graph без участия пользователя. Поэтому я отмечаю ответ как действительный. На случай, если кто-то окажется в такой же ситуации, GraphServiceclient создается как:

GraphServiceClient graphServiceClientApplication = new GraphServiceClient("https://graph.microsoft.com/v1.0", new DelegateAuthenticationProvider(
    async (requestMessage) =>
    {
        string clientId = "yourClientApplicationId";
        string authorityFormat = "https://login.microsoftonline.com/{0}/v2.0";
        string tenantId = "yourTenantId";
        string msGraphScope = "https://graph.microsoft.com/.default";
        string redirectUri = "msalXXXXXX://auth"; // Custom Redirect URI asigned in the Application Registration Portal in the native Application Platform
        string clientSecret = "passwordGenerated"; 
        ConfidentialClientApplication daemonClient = new ConfidentialClientApplication(clientId, String.Format(authorityFormat, tenantId), redirectUri, new ClientCredential(clientSecret), null, new TokenCache());
        AuthenticationResult authResult = await daemonClient.AcquireTokenForClientAsync(new string[] { msGraphScope });
        string token = authResult.AccessToken;
        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);                            
    }                
));

1 ответ

Решение

Одна идея заключается в использовании потока авторизации только для приложения. Идея состоит в том, что у вас могут быть долго работающие приложения, имеющие доступ к Microsoft Graph без аутентификации пользователя. Основное отличие состоит в том, что вместо маркера доступа, предоставляющего доступ конкретному пользователю, оно предоставляет вашему приложению доступ к ресурсам, на которые вы предварительно согласились. Там не будет диалоговое окно входа пользователя, и вы можете программно получить токены доступа для вызова Graph API.

Чтобы повторить, что эти токены не предназначены для конкретного пользователя, рассмотрите возможность сделать запрос GET на " https://graph.microsoft.com/v1.0/me ". Это вернет ошибку, поскольку токен доступа не предназначен для конкретного пользователя, а "я" ничего не значит. Запросы следует отправлять с полными идентификаторами пользователей "например, graph.microsoft.com/users/someuser@contosos.com".

Более подробную информацию об этом можно найти на странице Получить доступ без страницы документации пользователя.

Другая идея состоит в том, чтобы позволить пользователю аутентифицироваться в первый раз, когда они используют ваше приложение, а затем сохранить токен обновления. Эти токены живут дольше (несколько месяцев IIRC), и вам не нужно будет запрашивать согласие пользователя при каждом запуске приложения. Токены обновления можно обменять на токены доступа, которые живут 60 минут, и их можно использовать для вызова Graph API от имени пользователей.

Дополнительная информация о токенах обновления: https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_user

Я действительно хотел вернуться сюда и поделиться, так как вчера я столкнулся с этой проблемой, и идея предоставить доступ для чтения / записи к почтовому ящику для моего приложения... К ЯЩИКУ ЭЛЕКТРОННОЙ ПОЧТЫ КАЖДОГО ВО ВСЕЙ ОРГАНИЗАЦИИ... топ для моих нужд. (И это именно то, что происходит, когда вы начинаете говорить о предоставлении разрешений на уровне приложения вместо делегированных разрешений для вашего зарегистрированного приложения).

Это простой вариант использования: у меня был ночной процесс, который требовал для автоматизации отправки электронных писем из общего почтового ящика с использованием традиционной учетной записи службы AD.

К счастью... даже несмотря на то, что они стремятся устранить пароли (смеется)... кто-то в Microsoft все еще признает мой вариант использования, и в Azure AD нет альтернативы "яблоко-яблоко". Еще есть метод расширения, на который мы можем положиться, чтобы выполнить работу:

private AuthenticationContext authContext = null;
authContext = new AuthenticationContext("https://login.microsoftonline.com/ourmail.onmicrosoft.com", 
                new TokenCache());
result = authContext.AcquireTokenAsync("https://graph.microsoft.com/", 
                "12345678-1234-1234-1234-1234567890", 
                new UserPasswordCredential( 
                    Environment.GetEnvironmentVariable("UID", EnvironmentVariableTarget.User), 
                    Environment.GetEnvironmentVariable("UPD", EnvironmentVariableTarget.User) 
                )).Result;    

Вы можете заменить эти вызовы GetEnvironmentVariable своим именем пользователя (UID) и паролем (UPD). Я просто помещаю их в переменные среды учетной записи службы, чтобы мне не пришлось ничего проверять в системе управления версиями.

AcquireTokenAsync - это метод расширения, доступный из пространства имен Microsoft.IdentityModel.Clients.ActiveDirectory. Оттуда запустить GraphClient - несложно.

        string sToken = result.AccessToken;
        Microsoft.Graph.GraphServiceClient oGraphClient = new GraphServiceClient(
                    new DelegateAuthenticationProvider((requestMessage) => {
                        requestMessage
                            .Headers
                            .Authorization = new AuthenticationHeaderValue("bearer", sToken);
            return Task.FromResult(0);
        }));

Последней магией было добавление этих разрешений к регистрации приложений, которые я создал в Azure AD (откуда этот GUID). Приложение определено как общедоступный клиент (для этого есть переключатель в нижней части вкладки аутентификации). Я добавил следующие 5 ДЕЛЕГАТИВНЫХ разрешений (НЕ разрешения для приложений):

Microsoft Graph
1. Mail.ReadWrite.Shared
2. Mail.Send.Shared
3. User.Read
4. электронная почта
5. openid

Поскольку согласие пользователей фактически заблокировано в нашей организации, другому администратору разрешений пришлось просмотреть определение моего приложения, а затем предоставить эти права на уровне администратора, но как только он это сделал, все загорелось и работало так, как мне было нужно: ограниченный доступ со стороны учетной записи службы в один общий почтовый ящик, при этом фактическая безопасность этого доступа управляется в Office 365, а не в Azure AD.

Другие вопросы по тегам