Facebook auth redirection problem - Location header

I have a problem with facebook auth. I am using the regular flow for oauth. It works fine for twitter and google but on some devices facebook keeps failing. Instead of being redirected to the specified redirect url, users are redirected to Facebook - log in or sign up or Facebook - log in or sign up (on mobile devices)

https://graph.facebook.com/oauth/authorize?client_id=[myclientid]&redirect_uri=[mysite]api/auth/facebook&scope=email

it displays the authentication flow, but when it redirects back to api/auth/facebook (with the code) I got the following:

Request URL:[mysite]api/auth/facebook?code=[code]
Request Method:GET
Status Code:302 Moved Temporarily
Response Headers
view source
Cache-Control:private
Content-Type:text/html
Date:Thu, 01 Oct 2015 22:48:25 GMT
Location:Facebook - log in or sign up
Server:Microsoft-IIS/7.0
Set-Cookie:ss-id=m2NgNmWzyox4USxo1i3x; path=/; HttpOnly
Set-Cookie:ss-pid=0wTjJXu8XmTXzE2B4C7q; expires=Mon, 01-Oct-2035 22:48:25 GMT; path=/; HttpOnly
[cookie information]
Set-X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
X-Powered-By:ServiceStack/4.042 Win32NT/.NET

I see the location header there “Facebook - log in or sign up” (I am being redirected there instead of the redirect_url)

I have set the right redirect on web.config.

Why is the redirection failing? Why am I getting a 302 moved temporarily?

Here are the different ways ServiceStack looks for the redirect url: c# - How do I redirect after authentication in ServiceStack - Stack Overflow

When you say:

Where is the redirect url being specified?

1 Like

I am using the Continue parameter:

http://[mysite]/api/auth/facebook?continue=http://[mysite]/api/perfil?format=json

It works on some cases, but specifically on mobile browsers ( I am using this to authenticate users on my app) it redirects to http://m.facebook.com

Edit: for twitter and google it works. I am using the continue parameter because, even setting the Redirect Urls on the web.config, it was not working without it.

On a mobile browser on android it fails and redirects to m.facebook.com. I am able to reproduce this behavior on desktop by omitting the continue parameter and starting the flow here:

https://graph.facebook.com/oauth/authorize?client_id=[clientid]&redirect_uri=http://[mysite]/api/auth/facebook&scope=email

when it gets to api/auth/facebook, the location header contains facebook.com/#s=1 and it gets redirected.

Ok but you need to add the Continue parameter to specify what you want to redirect to.

So now what’s needed to reproduce this with the Continue parameter? What mobile browser does it not work with?

You can also intercept and change the successful url by specifying a custom SuccessRedirectUrlFilter on the AuthProvider, e.g:

    new FacebookAuthProvider { 
        SuccessRedirectUrlFilter = (authProvider, url) => "http://new.url"
    };

It is happening on chrome for Android. I have 2 different flows: the website and the Android/Iphone application (phonegap).
The only difference, the redirect url. For the website is an internal page, for the app is a service that returns a json.
I set the CallbackUrl on web.config for the second case, but I use the Continue parameter just to make sure.

Based on your documentation, the Continue parameter is the first one being considered to redirect:

The Continue QueryString, FormData or Request DTO variable when making the request to /auth
The Session.ReferrerUrl Url
The HTTP Referer HTTP Header
The CallbackUrl in the AuthConfig of the current AuthProvider used

When opening this Url on a browser on Android

http://[mysite]/api/auth/facebook?continue=http://[mysite]/api/perfil?format=json

The Continue parameter is omitted, and it redirects to m.facebook.com

Where in the SuccessRedirectUrlFilter in the order of precedence? Because I need a way to have 2 different flows.

Right now i have

 new FacebookAuthProvider(appSettings),

Can I add SuccessRedirectUrlFilter to the web.config?

Thanks!

More information. I was able to debug the android chrome flow, and compare against desktop chrome to see the differences.

Desktop: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36

Mobile: user-agent:Mozilla/5.0 (Linux; Android 5.1; MotoE2(4G-LTE) Build/LPI23.29-15) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36

For some reason the Continue parameter gets lost in the mobile flow.

When it redirects to api/auth/facebook?code=[code] The Location parameter on the response headers is different on both. On Desktop (right one):

Location:http://[mysite]/api/perfil?format=json#s=1

on Mobile

Location:Facebook - log in or sign up

I assume this is the problem,

SuccessRedirectUrlFilter Is a delegate as shown above, it has the last final say. It passes in the url it wants to redirect to which you can inspect and change by returning a different url to redirect to.

Yes the Location HTTP Response header is what’s tells the browser what url to redirect to, that’s not the problem that’s the symptom, it’s going to redirect to the final url in the HTTP Response Location Header. For some reason it’s getting lost on Android.

I’ve tested this in iOS and it redirects to the JSON url, so it looks like this is limited to Android, please use the SuccessRedirectUrlFilter to look at the url and force the JSON url for https://m.facebook.com/#s=1

BTW I’ve just tested your last link in and Android Emulator and I’m now seeing the JSON response as well, if you’ve changed something it appears to be working now.

Hi

I still haven’t changed it. It does not happen on every android, but on some models (people using the app report that on some motorola, sony xperia among others).

The SuccessRedirectUrlFilter sounds like the solution for this issue and I think I understand how it works, but I am not sure where do I implement it. Is there documentation for it? or Could you help me with a code snippet?

is it in the apphost?

var appSettings = new AppSettings();

        Plugins.Add(new AuthFeature(
            () => new CustomUserSession(),
            new IAuthProvider[] {
            new TwitterAuthProvider(appSettings),
            new FacebookAuthProvider(appSettings),
            new GoogleOAuth2Provider(appSettings) 
        }));

Thanks a lot, I really appreciate you taking the time to review this.

Right there in the registration of the Facebook Provider:

new FacebookAuthProvider(appSettings) { 
    SuccessRedirectUrlFilter = (authProvider, url) => "http://new.url"
},

It worked!! Thank you so much.

Just one more detail: I noticed that the first place where servicestack looks to redirect is not Continue, but somewhere else, I assume a cookie. Because, if I go to

www.mysite.com/auth/facebook?Continue=www.mysite.com/facebook_page

it works. But after doing that, if i sign out and try to login with another social network, let say:

www.mysite.com/auth/twiter?Continue=www.mysite.com/twitter_page

Instead of taking me to twitter_page, it still takes me to facebook_page.

I mention this because, with the SuccessRedirectUrlFilter the redirection works, but the value being stored in the cookie is still m.facebook.com. So, if i log out and try to log in again with twitter, I will be redirected to m.facebook.com.

Is this behavior after you’ve logged out first (i.e. /auth/logout) or after you’re already authenticated?

At the time when authenticating the url is initially stored in your Session.ReferrerUrl which holds what url to redirect to after the OAuth redirects.

It happened while being already authenticated. Wil look for a better logout implementation. Thanks again!