WebAuthenticationBroker 是否在 Windows 8 Metro App post Release Candidate 中工作工作、Metro、Windows、WebAuthen

由网友(你我都在改变何须感慨从前)分享简介:解决方案我的工作解决方案可以在答案或我的更新二中找到.1) 现在,为了在 localhost 上进行测试,请确保您已经为 localhost 端口上的入站设置了 windows 防火墙.路由器上的端口转发(如果有).2) 然后你需要告诉 IIS Express,请求来自 localhost 外部是可以的:找到 Docu...

解决方案我的工作解决方案可以在答案或我的更新二中找到.

1) 现在,为了在 localhost 上进行测试,请确保您已经为 localhost 端口上的入站设置了 windows 防火墙.路由器上的端口转发(如果有).

Windows 12 UI界面抢先看

2) 然后你需要告诉 IIS Express,请求来自 localhost 外部是可以的:找到 DocumentsIISExpressconfig 并编辑 applicationhost.config.在列表中找到您的站点并从绑定中删除 localhost.

 <网站名称="S-Innovations.TrafficTheory.Web2" id="1591449597"><应用程序路径="/" applicationPool="Clr4IntegratedAppPool"><virtualDirectory path="/" physicalPath="G:DocumentsVisual Studio 2012ProjectsS-Innovations.TrafficTheoryS-Innovations.TrafficTheory.Web2"/></应用程序><绑定><绑定协议="http" bindingInformation="*:909090:localhost"/></绑定></网站>

2a) ISS 需要以管理员身份运行,以管理员身份运行 Visual Studio 也以管理员身份启动 iss...

3) 找到您的 ip,www.myip.com 并将 ACS 返回 uri 更改为:http://90.90.90.90:909090/api/federation/

4) 更改网络经纪人以使用您的 ip:

 WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None,new Uri("https://traffictheory.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a48451%2f"),新的 Uri("http://99.99.99.99:909090/api/federation/end"));

一切都像这样对我有用.我得到了一个 hello world 作为令牌传递给我的 Metro 应用程序.

问题

我已经设置了 WCF 服务和 Metro 应用程序.WCF 服务设置为使用 Azure ACS 进行身份验证.

我制作了一个可与 WebService 和 ACS 配合使用的控制台应用程序:

 static void Main(string[] args){尝试{//先启动web项目,再启动客户端WebClient 客户端 = 新 WebClient();var token = RetrieveACSToken();client.Headers.Add("授权", token);client.Headers.Add("内容类型", "text/xml");var url = new Uri("http://traffictheory.azurewebsites.net/UserService.svc/Users");//var url = new Uri("http://localhost:4000/UserService.svc/Users");//流流 = client.OpenRead(url);StreamReader reader = new StreamReader(stream);字符串响应 = reader.ReadToEnd();Console.Write(响应);}捕捉(例外前){Console.Write(ex.Message);}Console.ReadLine();}私有静态字符串 RetrieveACSToken(){var acsHostName = ConfigurationManager.AppSettings.Get("ACSHostName");var acsNamespace = ConfigurationManager.AppSettings.Get("ACSNamespace");var username = ConfigurationManager.AppSettings.Get("ServiceIdentityUserName");var 密码 = ConfigurationManager.AppSettings.Get("ServiceIdentityCredentialPassword");var scope = "http://traffictheory.azurewebsites.net/";//var scope = "http://localhost:4000/";////从 ACS 请求令牌WebClient 客户端 = 新 WebClient();client.BaseAddress = string.Format("https://{0}.{1}", acsNamespace, acsHostName);NameValueCollection 值 = 新名称值集合();values.Add("wrap_name", 用户名);values.Add("wrap_password", 密码);values.Add("wrap_scope", scope);字节 [] 响应字节 =client.UploadValues("WRAPv0.9", "POST", values);字符串响应 =Encoding.UTF8.GetString(responseBytes);字符串标记 = 响应.Split('&').Single(值 =>value.StartsWith("wrap_access_token=",StringComparison.OrdinalIgnoreCase)).Split('=')[1];var decodedToken = string.Format("WRAP access_token="{0}"", HttpUtility.UrlDecode(token));返回解码令牌;}

当我想从 Metro 应用程序中使用它时,我现在面临两个问题.第一个与服务无关,与 WebAuthenticationBroker 有关.

1)当我使用

WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None,新的 Uri("https://s-innovations.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2ftraffictheory.azurewebsites.net%2f"),新的 Uri("https://s-innovations.accesscontrol.windows.net"));

我可以使用 LiveID、Facebook 等登录.不是谷歌,因为 ACS 没有正确包含 ID.但我没有得到任何形式的代币或索赔.我只得到:

https://s-innovations.accesscontrol.windows.net/v2/wsfederation?wa=wsignin1.0https://s-innovations.accesscontrol.windows.net/v2/facebook?cx=cHI9d3NmZWRlcmF0aW9uJn...cmFmZmljdGhlb3J5LmF6dXJld2Vic2l0ZXMubmV0JTJmJmlwPUZhY2Vib29rLTM1NTk5MjQ2NzgxNzc5OQ2&code=AQDagvq

我如何获得这部电影结尾处的声明:http://channel9.msdn.com/Events/BUILD/BUILD2011/SAC-858T他的应用程序有效!

2)上面显示的控制台应用程序在调用 API 时经过身份验证并获取要传递给服务的令牌,我如何从 Metro 应用程序中获取此令牌.

更新

我按照建议创建了控制器:

[HttpPost]公共动作结果结束(){返回 Json("Hello World");}

我已经设置了一个断点,看看它是否得到它.还没有命中.

 WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None,new Uri("https://traffictheory.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a48451%2f"),new Uri("http://localhost:909090/Federation/End"));

在我的依赖方应用程序中,我有

领域 http://localhost:909090/Return Url:Nothing(已尝试 http://localhost:909090/Federation/End )

响应数据现在包含:http://localhost:909090/Federation/End.

更新 2

我还尝试使用 api 控制器,如您在另一篇文章中所示:

公共类 FederationController : ApiController{

public HttpResponseMessage Post(){var response = this.Request.CreateResponse(HttpStatusCode.Redirect);response.Headers.Add("位置", "/api/federation/end?acsToken=" + ExtractBootstrapToken());返回响应;}公共字符串获取(){返回你好世界";}受保护的虚拟字符串 ExtractBootstrapToken(){返回你好世界";}

}

现在登录屏幕只是挂起,并以您正在寻找的服务尚未准备好(或类似的东西)结束.

acs 返回网址 http://localhost:48451/api/Federation

 WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None,new Uri("https://traffictheory.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a909090%2f"),新的 Uri("http://localhost:909090/api/federation/end"));

解决方案

WebAuthenticationBroker 只是继续浏览,直到下一个请求的页面是 callbackUri 参数指定的页面.此时它会返回最终的 URL,因此如果您想取回任何内容,则需要在该 URL 中进行编码.

在依赖方的 ACS 控制面板中,您需要指定位于您网站某处的返回 URL.例如 https://traffictheory.azurewebsites.net/federationcallback.然后创建一个控制器来处理接受该 URL 的帖子.该帖子将有一个表单字段 wresult,它是一些包含从 ACS 返回的令牌的 xml.

然后,您可以通过重定向到 https://traffictheory.azurewebsites.net/federationcallback/end?token={whatever you want to return} 将令牌发送回 WebAuthenticationBroker/代码>

然后,您需要将身份验证代理的使用更改为以下内容:

var webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None,新的 Uri("https://s-innovations.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2ftraffictheory.azurewebsites.net%2f"),新的 Uri("https://traffictheory.azurewebsites.net/federationcallback/end"));//你返回的数据var token = authenticateResult.ResponseData.Substring(authenticateResult.ResponseData.IndexOf("token=", StringComparison.Ordinal) + 6);

我用于处理身份验证回调帖子的控制器如下所示.

公共类 FederationcallbackController : ApiController{公共 HttpResponseMessage Post(){var response = this.Request.CreateResponse(HttpStatusCode.Redirect);response.Headers.Add("位置", "/api/federationcallback/end?acsToken=" + ExtractBootstrapToken());返回响应;}受保护的虚拟字符串 ExtractBootstrapToken(){返回 HttpContext.Current.User.BootstrapToken();}}

BootstrapToken() 扩展方法是 wif.swt NuGet 包的一部分.默认情况下,WIF 不会将任何内容保存到引导令牌属性,您需要通过在 <service> 元素下包含 saveBootstrapTokens="true" 属性来启用它代码><microsoft.identityModel> 在您的 web.config 中.我的看起来像这样:

<microsoft.identityModel><服务 saveBootstrapTokens="true"><audienceUris><加值="http://localhost:3949/"/></audienceUris><联合身份验证><wsFederation passiveRedirectEnabled="true" issuer="https://xyz.accesscontrol.windows.net/v2/wsfederation" realm="http://localhost:3949/" 回复="http://localhost:3949/" requireHttps="假"/><cookieHandler requireSsl="false" path="/"/></federatedAuthentication><issuerNameRegistry type="Microsoft.IdentityModel.Swt.SwtIssuerNameRegistry, Wif.Swt"><受信任的发行人><添加名称="https://readify.accesscontrol.windows.net/" thumbprint="{thumbprint}"/></trustedIssuers></issuerNameRegistry><securityTokenHandlers><添加类型="Microsoft.IdentityModel.Swt.SwtSecurityTokenHandler, Wifi.Swt"/></securityTokenHandlers><issuerTokenResolver type="Microsoft.IdentityModel.Swt.SwtIssuerTokenResolver, Wif.Swt"/></服务></microsoft.identityModel>

SOLUTION My working solution can be found in the answer or in my update two.

1) Now make sure, for testing on localhost, that you have setup windows firewalls for inbound on the localhost port. Port forwarding on the router if you have one.

2) Then you need to tell IIS Express that its okay that the request comes from outsite the localhost: Find DocumentsIISExpressconfig and edit applicationhost.config. Find your site in the list and remove the localhost from the binding.

        <site name="S-Innovations.TrafficTheory.Web2" id="1591449597">
            <application path="/" applicationPool="Clr4IntegratedAppPool">
                <virtualDirectory path="/" physicalPath="G:DocumentsVisual Studio 2012ProjectsS-Innovations.TrafficTheoryS-Innovations.TrafficTheory.Web2" />
            </application>
            <bindings>
                <binding protocol="http" bindingInformation="*:909090:localhost" />
            </bindings>
        </site>

2a) ISS need to run as administrator, running visual studio as administrator also starts iss as admin...

3) Locate your ip, www.myip.com and change the ACS return uri to : http://90.90.90.90:909090/api/federation/

4) change the webbroker to use your ip also:

        WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
WebAuthenticationOptions.None,
new Uri("https://traffictheory.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a48451%2f"),
new Uri("http://99.99.99.99:909090/api/federation/end"));

Everything worked for me like this. I got a hello world passed on to my metro app as the token.

Problem

I have set up a WCF Service and a Metro App. The WCF service is set up to authenticate using Azure ACS.

I made a Console Application that works with the WebService and ACS:

            static void Main(string[] args)
        {
            try
            {

                // First start the web project, then the client
                WebClient client = new WebClient();
                var token = RetrieveACSToken();
                client.Headers.Add("Authorization", token);
                client.Headers.Add("Content-type", "text/xml");
                var url = new Uri("http://traffictheory.azurewebsites.net/UserService.svc/Users");
                //var url = new Uri("http://localhost:4000/UserService.svc/Users");//
                Stream stream = client.OpenRead(url);
                StreamReader reader = new StreamReader(stream);
                String response = reader.ReadToEnd();
                Console.Write(response);

            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
            }
              Console.ReadLine();
        }

        private static string RetrieveACSToken()
        {
            var acsHostName     = ConfigurationManager.AppSettings.Get("ACSHostName");
            var acsNamespace    = ConfigurationManager.AppSettings.Get("ACSNamespace");
            var username        = ConfigurationManager.AppSettings.Get("ServiceIdentityUserName");
            var password        = ConfigurationManager.AppSettings.Get("ServiceIdentityCredentialPassword");
            var scope = "http://traffictheory.azurewebsites.net/"; 
            //var scope = "http://localhost:4000/";// 
            // request a token from ACS
            WebClient client = new WebClient();
            client.BaseAddress = string.Format("https://{0}.{1}", acsNamespace, acsHostName);
            NameValueCollection values = new
            NameValueCollection();
            values.Add("wrap_name", username);
            values.Add("wrap_password", password);
            values.Add("wrap_scope", scope);
            byte[] responseBytes =
            client.UploadValues("WRAPv0.9", "POST", values);
            string response =
            Encoding.UTF8.GetString(responseBytes);
            string token = response
            .Split('&')
            .Single(value =>
            value.StartsWith("wrap_access_token=",
            StringComparison.OrdinalIgnoreCase))
            .Split('=')[1];
            var decodedToken = string.Format("WRAP access_token="{0}"", HttpUtility.UrlDecode(token));
            return decodedToken;
        }

I face two problems now when i want to use it from my Metro App. First one is unrelated to the service and is about the WebAuthenticationBroker.

1) When i use

WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
                WebAuthenticationOptions.None,
                new Uri("https://s-innovations.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2ftraffictheory.azurewebsites.net%2f"),
                new Uri("https://s-innovations.accesscontrol.windows.net")
            );

I am able to log in using, LiveID, Facebook ect. Not google because ACS dont include the ID correctly. But I dont get any kind of token back or Claims. I only get:

https://s-innovations.accesscontrol.windows.net/v2/wsfederation?wa=wsignin1.0 https://s-innovations.accesscontrol.windows.net/v2/facebook?cx=cHI9d3NmZWRlcmF0aW9uJn...cmFmZmljdGhlb3J5LmF6dXJld2Vic2l0ZXMubmV0JTJmJmlwPUZhY2Vib29rLTM1NTk5MjQ2NzgxNzc5OQ2&code=AQDagvqoXQ.......

How do I get the claims like in the end of this movie: http://channel9.msdn.com/Events/BUILD/BUILD2011/SAC-858T His app works!

2) The console app shown above get authenticated and get the token to pass to the service when calling the API, how do i get this token from within the metro app.

UPDATE

I created the controller as suggested:

[HttpPost]
public ActionResult End()
{
    return Json("Hello World");
}

I have put in a break point to see if it get it. No hit yet.

    WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
WebAuthenticationOptions.None,
new Uri("https://traffictheory.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a48451%2f"),
new Uri("http://localhost:909090/Federation/End"));

On my Relying Party Application i ahave

Realm http://localhost:909090/
Return Url: Nothing  (have tried http://localhost:909090/Federation/End )

The response data contains : http://localhost:909090/Federation/End right now.

UPDATE 2

I also tried with an api controller as you shown in another post:

public class FederationController : ApiController {

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

    return response;
}
public string Get()
{
    return "hello world";
}
protected virtual string ExtractBootstrapToken()
{
    return "Hello World";
}

}

Now the login screen just hang and ends with a service you looking for is not ready right now (or something like that).

acs return url http://localhost:48451/api/Federation

        WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
WebAuthenticationOptions.None,
new Uri("https://traffictheory.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a909090%2f"),
new Uri("http://localhost:909090/api/federation/end"));

解决方案

The WebAuthenticationBroker simply keeps browsing until the next requested page is the one specified by the callbackUri parameter. At that point it returns the final URL to you so if you want to get anything back it needs to be encoded in that URL.

In the ACS control panel for the relying party you need to specify a return url that is somewhere on your site. For example https://traffictheory.azurewebsites.net/federationcallback. Then create a controller to handle accept a post to that URL. The post will have a form field wresult which is some xml that will contain the token returned from ACS.

You can then send the token back to the WebAuthenticationBroker by redirecting to https://traffictheory.azurewebsites.net/federationcallback/end?token={whatever you want to return}

You would then need to change the usage of the authentication broker to the following:

var webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
            WebAuthenticationOptions.None,
            new Uri("https://s-innovations.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2ftraffictheory.azurewebsites.net%2f"),
            new Uri("https://traffictheory.azurewebsites.net/federationcallback/end")
        );

// The data you returned
var token = authenticateResult.ResponseData.Substring(authenticateResult.ResponseData.IndexOf("token=", StringComparison.Ordinal) + 6);

My controller for handling the authentication callback post looks like this.

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();
    }
}

The BootstrapToken() extenion method is part of the wif.swt NuGet package. By default WIF doesn't save anything to the bootstrap token property you need to enable it by including the saveBootstrapTokens="true" attribute on the <service> element under <microsoft.identityModel> in your web.config. Mine looks like this:

<microsoft.identityModel>
    <service saveBootstrapTokens="true">
        <audienceUris>
            <add value="http://localhost:3949/" />
        </audienceUris>
        <federatedAuthentication>
            <wsFederation passiveRedirectEnabled="true" issuer="https://xyz.accesscontrol.windows.net/v2/wsfederation" realm="http://localhost:3949/" reply="http://localhost:3949/" requireHttps="false" />
            <cookieHandler requireSsl="false" path="/" />
        </federatedAuthentication>
        <issuerNameRegistry type="Microsoft.IdentityModel.Swt.SwtIssuerNameRegistry, Wif.Swt">
            <trustedIssuers>
                <add name="https://readify.accesscontrol.windows.net/" thumbprint="{thumbprint}" />
            </trustedIssuers>
        </issuerNameRegistry>
        <securityTokenHandlers>
            <add type="Microsoft.IdentityModel.Swt.SwtSecurityTokenHandler, Wif.Swt" />
        </securityTokenHandlers>
        <issuerTokenResolver type="Microsoft.IdentityModel.Swt.SwtIssuerTokenResolver, Wif.Swt" />
    </service>
</microsoft.identityModel>

阅读全文

相关推荐

最新文章