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"));
See Question&Answers more detail:
os