C# 从Metro应用程序访问受ACS保护的Azure中的Web API站点

C# 从Metro应用程序访问受ACS保护的Azure中的Web API站点,c#,azure,windows-8,acs,C#,Azure,Windows 8,Acs,我有一个运行ASP.NETWebAPI应用程序的Azure工作者角色。这是由ACS保护的。当我使用浏览器浏览web api时,ACS会向我提出挑战,要求我对Google或LiveId进行身份验证。当我进行身份验证时,我可以看到数据 我正在尝试从Win 8 Metro风格的应用程序访问相同的API。我正在尝试使用WebAuthenticationBroker WebAuthenticationResult WebAuthenticationResult=等待WebAuthenticationBro

我有一个运行ASP.NETWebAPI应用程序的Azure工作者角色。这是由ACS保护的。当我使用浏览器浏览web api时,ACS会向我提出挑战,要求我对Google或LiveId进行身份验证。当我进行身份验证时,我可以看到数据

我正在尝试从Win 8 Metro风格的应用程序访问相同的API。我正在尝试使用WebAuthenticationBroker

WebAuthenticationResult WebAuthenticationResult=等待WebAuthenticationBroker.AuthenticationAsync(
WebAuthenticationOptions。无,
新Uri(“https://xxxxx.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2fyyyyy.cloudapp.net%2f"),
新Uri(“http://yyyyy.cloudapp.net/")
);
当我启动应用程序时,它要求我像以前一样通过Google或LiveId进行身份验证。这一切都过去了,我得到了一个成功的结果

然后,我使用HttpClient创建对API的调用:

HttpClient=newhttpclient();
Uri _baseUri=新Uri(“http://yyyyy.cloudapp.net/api/");
client.BaseAddress=\u baseUri;
var response=client.GetAsync(“Values/”).Result;
var responseBodyAsText=response.Content.ReadAsStringAsync().Result;
var id=JsonConvert.DeserializeObject(responseBodyAsText);
这类工作正常,它似乎正确地导航到URI,但返回的负载是HTML,要求我登录,而不是我期望的JSON数据


我花在这件事上的时间比理智的多,而且已经没有想法了!有人能帮忙吗?

调用API时,您不应该重复使用
WebAuthenticationResult
中的令牌吗

var webAuthenticationResult=等待WebAuthenticationBroker.authenticateSync(WebAuthenticationOptions.None,
新Uri(“https://xxxxx.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2fyyyyy.cloudapp.net%2f“”,新Uri(“”)http://yyyyy.cloudapp.net/"));
var client=新的HttpClient();
client.DefaultRequestHeaders.Authorization
=新的AuthenticationHeaderValue(“OAuth”,webAuthenticationResult.ResponseData);

WebAuthenticationBroker将继续浏览,直到浏览器要加载的url是callbackUri参数中指定的url。然后,它将向您返回最终url,包括任何查询参数。它实际上从未向callbackUri发出请求

您遇到的问题是,ACS实现的WS-Federation协议将令牌发回返回url(在ACS配置门户中指定),该url可能与您在AuthenticateAsync方法中指定为callbackUri参数的url相同

您需要做的是处理该post并将请求重定向到callbackUri,但是使用包含令牌的查询字符串

我使用的是WebApi和WIF,我的callbackUri被指定为
http://localhost:3949/api/federationcallback/end
并返回指定为
http://localhost:3949/api/federationcallback
。这允许我让一个控制器处理post,然后用URL中的令牌重定向。控制器看起来像这样

public class FederationcallbackController : ApiController
{
    public HttpResponseMessage Post()
    {
        var response = this.Request.CreateResponse(HttpStatusCode.Redirect);
        response.Headers.Add("Location", "/api/federationcallback/end?acsToken=" + ExtractBootstrapToken());

        return response;
    }

    protected virtual string ExtractBootstrapToken()
    {
        return HttpContext.Current.User.BootstrapToken();
    }
}
然后我可以像这样获得令牌:

var authenticateResult = await WebAuthenticationBroker.AuthenticateAsync(
            WebAuthenticationOptions.None,
            new Uri("https://xyz.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost:3949%2f"),
            new Uri("http://localhost:3949/api/federationcallback/end"));

var oauthToken = authenticateResult.ResponseData.Substring(authenticateResult.ResponseData.IndexOf("acsToken=", StringComparison.Ordinal) + 9);

在本地主机上测试时,您必须确保ACS可以访问您的计算机

正如@caleb所写的,您需要监听令牌并为代理重定向它。 你可以看到我的文章中有一个工作示例以及如何设置它


如何从WebAuthenticationResponse获取令牌?据我所知,令牌应该位于ResponseData属性中,但不起作用-我在ResponseData中得到的只是它是否重要这是http而不是https?我发现ResponseData不包含安全令牌,我看不到如何从中获取它WebAuthenticationBroker。你有没有在这方面取得进一步的进展?遗憾的是,没有,我放弃了,我正在等待,直到它成熟一点,或者我在谷歌上找到一个答案。如果你知道它是如何工作的,请告诉我。我也有同样的问题。根据所使用的登录提供程序,响应数据是不同的。使用facebook,结果是一个长字符串,如:/v2/facebook?cx=cHI9d3NmZWRlcmF0aW9uJnJtPWh0,使用LiveID其短字符串:net/v2/wsfederation?wa=wsignin1.0。我也很想知道如何从这里开始,到目前为止,我已经发现,facebook的url需要response_type=token才能获得token。假设其他供应商也有类似的情况,谷歌的响应类型=代码,这是一个可行的解决方案。我的下一个问题是,现在我已经将ACS上的返回url更改为控制器,该控制器重定向metro应用程序的工作。但是,我的web界面不工作,因为除了返回url之外,什么是bootstraptoken方法?ACS知道localhost是我的ip,而不是作为ACS的localhost的localhost吗?bootstraptoken方法是wif.swt NuGet包中包含的扩展方法。我认为这是WIF的一部分,这就是为什么我之前没有提到它。ACS只是告诉浏览器重定向到localhost,然后浏览器解析名称。ACS不会直接与它对话。@AndrewBSchultz对不起,我现在想不出什么,只能再次检查您的ACS配置。另外,请确保指定一个回调URI,该URI与您要发布到的回调URI不同,因为WebAuthenticationBroker将在看到对该URI的请求时立即停止该进程。