3

我正在尝试设置一个 C# 控制台应用程序,该应用程序可以从通用 AD 帐户通过 Skype for Business Online 向用户发送通知/提醒。前几天我很高兴看到根据此页面,现在 Skype for Business Online 支持 UCWA: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 的支持是如此新。有没有人有一个如何做我想做的事情的例子,或者可以给我指出一个例子?到目前为止,我发现的所有东西都还没有真正接近我正在尝试的东西。不幸的是,我也不能使用 Skype for Business 客户端 SDK,因为它不能满足我的所有要求。

4

4 回答 4

4

在使用 Azure AD 进行身份验证中概述的步骤的帮助下,我找到了一个使用ADAL (v3) 的工作解决方案

这里的步骤涉及使用 ADAL 向 AAD 请求多个身份验证令牌

  • 在 Azure AD 中将您的应用程序注册为本机应用程序。
  • 执行自动发现以查找用户的 UCWA 根资源 URI。
    这可以通过执行 GET 请求来完成
    GET https://webdir.online.lync.com/Autodiscover/AutodiscoverService.svc/root?originalDomain=yourdomain.onmicrosoft.com

  • 使用 ADAL 为自动发现响应中返回的 UCWA 根资源请求访问令牌
    例如,您的根资源将位于 https://webdir0e.online.lync.com/Autodiscover/AutodiscoverService.svc/root/oauth/user?originalDomain=yourdomain.onmicrosoft.com
    您必须从 AAD 获取资源令牌https://webdir0e.online.lync.com/

  • 使用从 ADAL 获得的不记名令牌对根资源执行 GET
    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在我的情况下)

  • 使用从 ADAL 获得的令牌,通过对应用程序 URI 执行 POST 来创建新的 UCWA 应用程序

瞧,您的 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;
}

使用 ADAL 检索 OAuth 令牌的使用代码

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 来说更容易,尤其是在您询问的控制台应用程序的情况下

于 2016-04-10T12:54:50.023 回答
1

我刚刚使用一个从头到尾的例子写了一篇关于这个的博客,希望它会对你有所帮助。我只登录,但您可以将它与我在此处使用 Skype Web SDK 发送 IM 所做的另一篇文章(见第 13 天和第 14 天)结合使用,它应该可以正常工作。

-汤姆

于 2016-04-06T20:09:52.397 回答
1

与 Massimo 的解决方案类似,我创建了一个基于 Skype for Business Online C# 的控制台应用程序,演示如何签署和使用 UCWA 来创建/列出/删除会议和更改用户状态。我还没有开始扩展它以发送 IM,但当然欢迎您克隆我的存储库并将其扩展到您的需要。只需将您的 Azure AD 租户名称和本机应用 ID 放入代码中即可。

于 2016-06-29T22:02:33.637 回答
0

我想他们今天才打开它——我正在做一些与 Skype Web SDK 示例无关的事情,并且不得不创建一个新的 Azure AD 应用程序,并注意到有两个新的预览功能用于接收对话更新和更改用户信息。

现在 Github 示例中的所有内容都适用于 Skype For Business Online。

在此处输入图像描述

于 2016-06-06T18:41:40.810 回答