Отправка мгновенных сообщений с помощью Skype для бизнеса Online из консольного приложения

Я пытаюсь настроить консольное приложение C #, которое может отправлять уведомления / напоминания пользователям через Skype для бизнеса в Интернете из общей учетной записи AD. На днях я был рад увидеть, что, согласно этой странице, UCWA теперь поддерживается в Skype для бизнеса в Интернете: https://msdn.microsoft.com/en-us/library/office/mt650889.aspx.

Я пытался следовать этому руководству, чтобы настроить эту настройку: https://msdn.microsoft.com/en-us/library/office/mt590891(v=office.16).aspx. Пока мне не особо везло ... У меня есть приложение, настроенное в Azure AD, но я застреваю на этапе этой статьи «Запрос токена доступа с использованием неявного потока предоставления» (не уверен на 100%, что я предприняв правильные действия и до этого) ... пока что у меня вот такое:

        string clientId = "xxxxxxxx"
        string resourceUri = "https://webdir.online.lync.com";
        string authorityUri = "https://login.windows.net/common/oauth2/authorize";
        AuthenticationContext authContext = new AuthenticationContext(authorityUri);
        UserCredential cred = new UserCredential("username", "password");
        string token = authContext.AcquireToken(resourceUri, clientId, cred).AccessToken;


        var poolReq = CreateRequest("https://webdir.online.lync.com/autodiscover/autodiscoverservice.svc/root", "GET",token);
        var poolResp = GetResponse(poolReq);

        dynamic tmp = JsonConvert.DeserializeObject(poolResp);
        string resourcePool = tmp._links.user.href;

        Console.WriteLine(resourcePool);

        var accessTokenReq = CreateRequest("https://login.windows.net/common/oauth2/authorize"
            + "?response_type=id_token"
            + "&client_id=" + clientId
            + "&redirect_uri=https://login.live.com/oauth20_desktop.srf"
            + "&state=" + Guid.NewGuid().ToString()
            + "&resource=" + new Uri(resourcePool).Host.ToString()
            , "GET",token);
        var accessTokenResp = GetResponse(accessTokenReq);

мои методы GetResponse и CreateRequest:

    public static string GetResponse(HttpWebRequest request)
    {
        string response = string.Empty;

        using (HttpWebResponse httpResponse = request.GetResponse() as System.Net.HttpWebResponse)
        {
            //Get StreamReader that holds the response stream
            using (StreamReader reader = new System.IO.StreamReader(httpResponse.GetResponseStream()))
            {
                response = reader.ReadToEnd();
            }
        }

        return response;
    }



    public static HttpWebRequest CreateRequest(string uri, string method, string accessToken)
    {
        HttpWebRequest request = System.Net.WebRequest.Create(uri) as System.Net.HttpWebRequest;
        request.KeepAlive = true;
        request.Method = method;
        request.ContentLength = 0;
        request.ContentType = "application/json";
        request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken));

        return request;
    }

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

Я рылся в сети в поисках других примеров, но на самом деле не нашел ни одного, тем более что поддержка UCWA для Office 365 настолько нова. Есть ли у кого-нибудь пример того, как делать то, что я пытаюсь сделать, или может указать мне на один? Все, что я нашел до сих пор, даже не было близко к тому, что я пытаюсь. К сожалению, я не могу использовать клиентский SDK Skype для бизнеса, так как он не отвечает всем моим требованиям.


person John K.    schedule 04.04.2016    source источник


Ответы (4)


Я пришел к рабочему решению, используя ADAL (v3), с помощью шагов, описанных в Аутентификация с помощью Azure AD

Вот шаги, которые включают запрос нескольких токенов аутентификации в AAD с помощью ADAL.

  • Зарегистрируйте свое приложение как собственное приложение в Azure AD.
  • Выполните автоматическое обнаружение, чтобы найти URI корневого ресурса UCWA пользователя.
    Это можно сделать, выполнив запрос GET на
    GET https://webdir.online.lync.com/Autodiscover/AutodiscoverService.svc/root?originalDomain=yourdomain.onmicrosoft.com

  • Запросите токен доступа для корневого ресурса UCWA, возвращенного в ответе автообнаружения, с помощью ADAL.
    Например, ваш корневой ресурс будет в https://webdir0e.online.lync.com/Autodiscover/AutodiscoverService.svc/root/oauth/user?originalDomain=yourdomain.onmicrosoft.com
    вам нужно будет получить токен из AAD для ресурса https://webdir0e.online.lync.com/

  • Выполните GET для корневого ресурса с токеном носителя, полученным от ADAL
    GET https://webdir0e.online.lync.com/Autodiscover/AutodiscoverService.svc/root/oauth/user?originalDomain=yourdomain.onmicrosoft.com

  • Это вернет в пользовательском ресурсе URI ресурса приложений, в котором нужно создать приложение UCWA. В моем случае это:
    https://webpoolam30e08.infra.lync.com/ucwa/oauth/v1/applications
    Затем проживает в другом домене, следовательно, другая аудитория / ресурс, не включенные в ранее полученный токен аутентификации

  • Получите новый токен от AAD для ресурса хоста, где находятся домашний пул и ресурс приложений (https://webpoolam30e08.infra.lync.com в моем случае)

  • Создайте новое приложение UCWA, выполнив POST для URI приложения, используя токен, полученный из ADAL.

Вуаля, ваше приложение UCWA создано. Что я замечаю в данный момент, так это то, что доступно очень мало ресурсов, исключая меня / присутствие. Таким образом, можно получить информацию о присутствии пользователей, но нельзя изменить статус собственного присутствия. Однако мне удалось получить свою личную заметку, и мне доступны следующие ресурсы:

  • люди
  • коммуникация
  • встречи

Покажи мне код:

Функция для выполнения потока получения и переключения токенов аутентификации

public static async Task<UcwaApp> Create365UcwaApp(UcwaAppSettings appSettings, Func<string, Task<OAuthToken>> acquireTokenFunc)
{
    var result = new UcwaApp();
    result.Settings = appSettings;

    var rootResource = await result.Discover365RootResourceAsync(appSettings.DomainName);
    var userUri = new Uri(rootResource.Resource.GetLinkUri("user"), UriKind.Absolute);
    //Acquire a token for the domain where user resource is
    var token = await acquireTokenFunc(userUri.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped));
    //Set Authorization Header with new token
    result.AuthToken = token;
    var usersResult = await result.GetUserResource(userUri.ToString());
    //
    result.ApplicationsUrl = usersResult.Resource.GetLinkUri("applications");
    var appsHostUri = new Uri(result.ApplicationsUrl, UriKind.Absolute).GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped);
    //Acquire a token for the domain where applications resource is
    token = await acquireTokenFunc(appsHostUri);
    //Set Authorization Header with new token
    result.AuthToken = token;
    //
    var appResult = await result.CreateApplicationAsync(result.ApplicationsUrl, appSettings.ApplicationId, appSettings.UserAgent, appSettings.Culture);

    return result;
}

Код использования для получения токенов OAuth с помощью ADAL

var ucSettings = new UcwaAppSettings
{
    UserAgent = "Test Console",
    Culture = "en-us",
    DomainName = "yourdomain.onmicrosoft.com",
    ApplicationId = "your app client id"
};

var acquireTokenFunc = new Func<string, Task<OAuthToken>>(async (resourceUri) =>
{
   var authContext = new AuthenticationContext("https://login.windows.net/" + ucSettings.DomainName);

   var ar = await authContext.AcquireTokenAsync(resourceUri,
                ucSettings.ApplicationId,
                new UserCredential("myusername", "mypassword"));


   return new OAuthToken(ar.AccessTokenType, ar.AccessToken, ar.ExpiresOn.Ticks);
});

var app = await UcwaApp.Create365UcwaApp(ucSettings, acquireTokenFunc);

Конечно, должно быть возможно избежать жесткого кодирования имени пользователя и пароля с помощью ADAL, но это было проще для PoC и особенно в случае консольного приложения, как вы просили

person Massimo Prota    schedule 10.04.2016
comment
Застрял на шаге 3, когда я запрашиваю токен доступа для корневого ресурса UCWA, возвращенный в ответе автообнаружения с помощью ADAL, я получаю следующую ошибку: The application named https://webdir1a.online.lync.com/Autodiscover/AutodiscoverService.svc/root/oauth/user?originalDomain=xxxxx.onmicrosoft.com was not found in the tenant named xxxxx.onmicrosoft.com. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. У меня зарегистрировано собственное приложение AAD, и я использую правильный идентификатор приложения ... любые идеи ? - person John K.; 12.04.2016
comment
Убедитесь, что URI, который вы передаете в AcquireTokenAsync, - это только URI хоста (например, https://webdir1a.online.lync.com). Не должен включать часть пути - person Massimo Prota; 12.04.2016
comment
Спасибо. Это была моя проблема. Теперь у меня все работает. - person John K.; 13.04.2016
comment
Это фантастика. Надеюсь, они вскоре позволят изменить свое присутствие. - person EricRRichards; 11.05.2016
comment
:) Проголосуйте за использование функции officepdev.uservoice.com/forums/224641-general/suggestions/ - person Massimo Prota; 12.05.2016
comment
@MassimoProta хмм, недоступный ресурс / me делает невозможным регистрацию для обработки входящих IM-сообщений, если только я чего-то не упускаю ... Такая вот полезность - person EricRRichards; 13.05.2016
comment
@EricRRichards Это работает для меня, но я не пробовал, если разговор изначально установлен с другой стороны (не UCWA). Это твой случай? - person Massimo Prota; 15.05.2016
comment
Да, это было бы похоже на бота, который отвечает на входящие мгновенные сообщения - я пробовал следовать вместе с документацией по получению IM (msdn.microsoft.com/EN-US/library/office/), но сообщение в / me / makeMeAvailable выходит из строя с Запрещенным кодом. - person EricRRichards; 16.05.2016
comment
Привет! Есть ли образец проекта, который мы можем скачать для этого? Просто начни работать в этой сфере. Вид запутался. Спасибо. - person urlreader; 24.05.2016
comment
Спасибо. Можно ли скачать образец сейчас? Я просматриваю образцы кода ADAL и заставляю его работать. Однако при попытке использовать его для SfB Online возникает множество проблем. Уверен, что что-то упускаю, но не знаю, что именно. Спасибо. - person urlreader; 25.05.2016
comment
например, в вашем коде вы используете новый UserCredential (myusername, mypassword) при вызове AcquireTokenAsync. По некоторым причинам в моей среде говорится, что UserCredential не принимает 2 параметра. Я разместил вопрос по адресу stackoverflow.com/questions/37443977/. благодаря. - person urlreader; 25.05.2016
comment
Я застрял на шаге 3. После вызова AcquireTokenAsync для webdir0b.online.lync.com отображается ошибка: AADSTS65001: Пользователь или администратор не дал согласия на использование приложения с идентификатором 'a3bf0b1a-7c07-4421-81d3-1bf67e169c57'. Отправьте интерактивный запрос авторизации для этого пользователя и ресурса. - person urlreader; 26.05.2016
comment
У меня есть токен на предъявителя, но когда я выполняю GET для корневого ресурса с токеном на предъявителя, он всегда возвращает 404, фраза причины: не найдено. Если я не добавлю токен, он вернется без авторизации. Итак, вроде авторизовано, но ресурс найти не могу. что могло вызвать это? - person urlreader; 31.05.2016
comment
когда я выполняю GET для корневого ресурса с токеном-носителем, если я не включаю параметр? originalDomain = ...., я получаю что-то вроде: {_ links: {self: {href: webdir1b.online.lync.com/Autodiscover/AutodiscoverService.svc/}, xframe: { href: webdir0B.online.lync.com/Autodiscover/AutodiscoverService}, перенаправление: {href: webdir0B.online.lync.com /Autodiscover/AutodiscoverService.svc/}}}. действительно нужна помощь. благодаря. - person urlreader; 02.06.2016
comment
@MassimoProta На шаге Выполните GET для корневого ресурса с токеном носителя, полученным от ADAL, я получаю ‹h2› 403 - Forbidden: Access is denied. ‹/H2› error. В чем может быть причина? - person KamyFC; 15.03.2019

Я только что написал об этом в блоге используя пример от начала до конца, надеюсь, он вам поможет. Я дошел только до входа в систему, но вы можете использовать его с другим постом, который я написал об отправке мгновенных сообщений с помощью Skype Web SDK здесь (см. день 13 и 14) и объедините их, все должно работать нормально.

-Том

person Tom Morgan    schedule 06.04.2016
comment
Это отличная информация, спасибо. Однако в моем случае я пытаюсь сделать это через консольное приложение с C # напрямую с помощью User REST API, а не с помощью javascript в браузере. - person John K.; 06.04.2016

Подобно решению Массимо, я создал консольное приложение Skype для бизнеса Online на основе C #, которое демонстрирует, как подписывать и использовать UCWA для создания / списка / удаления собраний и изменения присутствия пользователей. Я не удосужился расширить его для отправки мгновенных сообщений, но вы, безусловно, можете клонировать мой репозиторий и расширить его для своих нужд. Просто введите в код имя клиента Azure AD и собственный идентификатор приложения.

person Tam Huynh    schedule 29.06.2016

Думаю, они просто включили это сегодня - я делал что-то, не связанное с образцами Skype Web SDK, и мне пришлось создать новое приложение Azure AD, и я заметил, что есть две новые функции предварительного просмотра для получения обновлений разговоров и изменения информации о пользователях.

Теперь все, что есть в примерах Github, работает в Skype для бизнеса Online.

введите описание изображения здесь

person EricRRichards    schedule 06.06.2016