Reputation: 261
I'm attempting to implement the Web Api 2 built in external authentication using Angular JS for my front end. I have owin cors enabled with the following line:
app.UseCors(CorsOptions.AllowAll);
I'm successfully loading the external logins as they do in the SPA template with this api call - api/Account/ExternalLogins?returnUrl=%2F&generateState=true
I use the URL from the response when the user clicks the button which the calls this api
htp://localhost:31683/api/Account/ExternalLogin?>provider=Facebook&response_type=token&client_id=self&redirect_uri=http%3A%2F%2Flocalhost%3A>31683%2F&state=EqHaUDzzuXZcVSk7IC_gWkgF5P_TNTdIHn1Tqbv18CM1
As expected the User.Identity.IsAuthenticated is not yet authenticated so it returns the ChallengeResults (exactly like SPA template) which should redirect the user to the facebook login page. This is where my problem comes in. The response in Fiddler looks good, it has the location response header for the redirect to the facebook login page. However, when it tries to do the redirect I am getting the following CORS error:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
It appears as if my redirect request for the facebook login has a Origin header with a null value. I believe this Origin header is why its looking for a AllowCors response which facebook isn't giving. I'm not sure why the Origin header is on the redirect request, or if thats even the issue.
Below are screenshots of the chrome responses to the api call to my api/Account/ExternalLogin api and then the redirect call.
My ExternalLogin response:
The facebook redirect response. This is where the problem is I believe. NOTE THE ORIGIN HEADER ON THE REQUEST
Any help would be greatly appreciated. I've dumped many hours into this. Thanks.
Upvotes: 6
Views: 1346
Reputation: 31
After calling "api/Account/ExternalLogins?returnUrl=%2F&generateState=true" the provider objects returned each have a url that you need to make a standard GET request to.(Not an AJAX request)
//Iterate through result and pick the correct provider.name
results = results.filter(function(item){
return item.name === 'Facebook';
});
if(results && results[0])
{
var provider = results[0]
//INCORRECT
//$http({
//method:'GET',
//url: provider.url
//});
//CORRECT
window.location.href = provider.url;
}
Upvotes: 0
Reputation: 7339
This is not exactly an answer to your question, but, I think this might help you.
I had a similar (or same) problem trying to do that but using ASP.NET MVC 5.
When no CORS is used, the proccess you described works like a charm. I'm using it too. It's great! It works. The problem starts when CORS IS used.
After 2 days of pain and suffering, I found the specs about CORS from W3C. After reading, my conclusion is that unfortunately it's simple not possible to do that. Take a look at section 6.2 and section 7.1.
In this specific action, I'm using JSONP. No server-side modifications to do, no extra code, no more pain! I just had to change a bit of my angular code.
To this
$http.jsonp('http://localhost:56278/register/appregister?provider=Facebook&?callback=JSON_CALLBACK');
From this
$http({ url: 'http://localhost:56278/register/appregister', method: 'GET', params: { provider: provider } });
Exptected response
Upvotes: 4