Facebook OAuth: custom callback_uri parameters
Asked Answered
H

6

81

I'd like to have a dynamic redirect URL for my Facebook OAuth2 integration. For example, if my redirect URL is this in my Facebook app:

http://www.mysite.com/oauth_callback?foo=bar

I'd like the redirect URL for a specific request be something like this, so that on the server, I have some context about how to process the auth code:

http://www.mysite.com/oauth_callback?foo=bar&user=6234

My redirect gets invoked after the authorization dialog is submitted, and I get back an auth code, but when I try to get my access token, I'm getting an OAuthException error back from Facebook. My request looks like this (line breaks added for clarity):

https://graph.facebook.com/oauth/access_token
    ?client_id=MY_CLIENT_ID
    &redirect_uri=http%3A%2F%2Fwww.mysite.com%2Foauth_callback%3Ffoo%3Dbar%26user%3D6234
    &client_secret=MY_SECRET
    &code=RECEIVED_CODE

All of my parameters are URL-encoded, and the code looks valid, so my only guess is that the problem parameter is my redirect_uri. I've tried setting redirect_uri to all of the following, to no avail:

  1. The actual URL of the request to my site
  2. The URL of the request to my site, minus the code parameter
  3. The URL specified in my Facebook application's configuration

Are custom redirect URI parameters supported? If so, am I specifying them correctly? If not, will I be forced to set a cookie, or is there some better pattern for supplying context to my web site?

Halidom answered 24/6, 2011 at 3:55 Comment(0)
H
107

I figured out the answer; rather than adding additional parameters to the redirect URL, you can add a state parameter to the request to https://www.facebook.com/dialog/oauth:

https://www.facebook.com/dialog/oauth
    ?client_id=MY_CLIENT_ID
    &scope=MY_SCOPE
    &redirect_uri=http%3A%2F%2Fwww.mysite.com%2Foauth_callback%3Ffoo%3Dbar
    &state=6234

That state parameter is then passed to the callback URL.

Halidom answered 24/6, 2011 at 16:28 Comment(10)
But state parameter can only contains number characters, isn't it?Ornithosis
No, it can contain any arbitrary data. At the time I wrote this, I was putting a whole JSON object in that parameter (URL-encoded, of course).Halidom
The state is intended for a random unguessable hash to prevent CSRF. Is there a way to resolve this?Swell
Interesting, their documentation didn't make mention that it was for CSRF originally. However, this doesn't change the fact that it seems to be the only way they give to pass arbitrary data. I suppose you could make your state parameter a JSON structure containing both a nonce and your state data, or the nonce only to use for looking up the rest of the information.Halidom
Great Answer..! I used this for facebook. But how do we do the same for twitter. It is not working :(Ballinger
Perhaps a bit old, but the state param is explained here: developers.facebook.com/docs/facebook-login/…Unplumbed
Why should I store custom redirect params in state?Beliabelial
auth0 allows extra query params in callback urls, but sadly facebook and twitter don't :(Paroxysm
Is this not a security risk? An actor can authenticate their Facebook account and then modify the state param in the redirect Uri to connect their Facebook to someone else's account in your system. Incorrect?Deville
Great point @Efraim; you'd definitely want to include some kind of token that the callback can use to confirm that the request isn't forged.Halidom
T
12

If, for any reason, you can't use the option that Jacob suggested as it's my case, you can urlencode your redirect_uri parameter before passing it and it will work, even with a complete querystring like foo=bar&morefoo=morebar in it.

Tannenberg answered 27/4, 2012 at 9:7 Comment(3)
Could you give an example?Swell
It used to work for me this way and then just stopped; now "sharing" the state parameter for both XSRF protection as well as my own ID is the solution for me.Louella
This does not work anymore, at least not in my case. It is only returning the first query string parameter when redirecting back from authentication.Purge
V
4

I was trying to implement a Facebook login workflow against API v2.9 following this tutorial. I tried the solutions described above. Manuel's answer is sort of correct, but what I observed is url encoding is not needed. Plus, you can only pass one parameter. Only the first query parameter will be considered, the rest will be ignored. Here is an example,

  1. Request a code via https://www.facebook.com/v2.9/dialog/oauth?client_id={app-id}&redirect_uri=http://{url}/login-redirect?myExtraParameter={some-value}

  2. You'd get a callback for your url. It will look like http://{url}/login-redirect?code={code-from-facebook}&myExtraParameter={value-passed-in-step-1}. Note that facebook would make a callback with myExtraParameter. You can extract the value for myExtraParameter from callback url.

  3. Then you can request access token with https://graph.facebook.com/v2.9/oauth/access_token?client_id={app-id}&client_secret={app-secret}&code={code-from-facebook}&redirect_uri=http://{url}/login-redirect?myExtraParameter={value-extracted-in-step-2}

Additional parameter passed in step 1 after the first query parameter will be ignored. Also make sure to not include any invalid characters in your query parameter (see this for more information).

Verse answered 11/7, 2017 at 4:58 Comment(2)
Maybe the Facebook server is being forgiving, but you absolutely should URL-encode redirect_uri; it is not valid to have an unencoded second ? in the URL nor &s, since it makes the parameter list ambiguous. If you URL-encode, you don't have to worry about avoiding "invalid characters" in the parameter. Your additional parameters are probably "ignored" because of your lack of encoding & (how could it differentiate between it being a parameter separator or part of callback_uri otherwise?)Halidom
@Verse I have added my callback url in ` Valid OAuth Redirect URIs` of Facebook login product under Client OAuth Settings without adding additional parameters. It is not working in my case URL Blocked: This redirect failed because the redirect URI is not whitelisted in the app’s Client OAuth Settings. Make sure Client and Web OAuth Login are on and add all your app domains as Valid OAuth Redirect URIs.Forethoughtful
R
-1

You're best off specifying a unique callback for each oAuth provider, /oauth/facebook, /oauth/twitter etc.

If you really want the same file to respond to all oAuth requests, either include it in the individual files or setup a path that will call the same file on your server using .htaccess redirects or something similar: /oauth/* > oauth_callback.ext

Rumrunner answered 13/6, 2016 at 4:22 Comment(0)
P
-1

You should set your custom state parameter using the login helper as such:

use Facebook\Facebook;
use Illuminate\Support\Str;

$fb = new Facebook([
    'app_id' => env('FB_APP_ID'),
    'app_secret' => env('FB_APP_SECRET'),
    'default_graph_version' => env('FB_APP_VER'),
]);

$helper = $fb->getRedirectLoginHelper();

$permissions = [
    'public_profile',
    'user_link',
    'email',
    'read_insights',
    'pages_show_list',
    'instagram_basic',
    'instagram_manage_insights',
    'manage_pages'
];

$random = Str::random(20);

$OAuth2Client = $fb->getOAuth2Client();

$redirectLoginHelper = $fb->getRedirectLoginHelper();

$persistentDataHandler = $redirectLoginHelper->getPersistentDataHandler();

$persistentDataHandler->set('state', $random);

$loginUrl = $OAuth2Client->getAuthorizationUrl(
        url('/') . '/auth/facebook',
        $random,
        $permissions
    );
Presuppose answered 2/4, 2020 at 4:46 Comment(0)
C
-1

Hey if you are using official facebook php skd then you can set custom state param like this

$helper = $fb->getRedirectLoginHelper();
$helper->getPersistentDataHandler()->set('state',"any_data");
$url = $helper->getLoginUrl($callback_url, $fb_permissions_array);
Curhan answered 18/11, 2020 at 16:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.