when trying to get access to a page that requires authentication with this code:
my $browser = LWP::UserAgent−>new;
my $url = 'http://www.unicode.org/mail−arch/unicode−ml/y2002−m08/0067.html';
my $response = $browser−>get($url);
an expected error is generated:
Error: Basic realm="Unicode−MailList−Archives"
401 Authorization Required
at http://www.unicode.org/mail−arch/unicode−ml/y2002−m08/0067.html
and this is taken care with:
$browser−>credentials(
'www.unicode.org:80',
'Unicode−MailList−Archives',
'unicode−ml' => 'unicode'
);
But my problem is how to use authentication when it is optional but not required. For example if I want to enter to http://www.coolstuffinc.com/user_main.php, if im logged in it takes me to my user page and if I am not it takes me to the home page.
How can I do so it uses my credentials to enter to the user page.
As always, do like you do if you were browsing: Navigate to the login form, fill it out, submit it, then visit the page you really want to visit.
Logging in will provide you with a cookie that will automatically be submitted in later requests. This is how the site knows who is logged in.
Related
If I programmatically create a Facebook test user, the login_url for the new user doesn't work. Fetching the login_url returns a 404 error.
Pared-down example (in Python). The last two lines are where the problem shows up:
import requests
from urlparse import parse_qs
APP_ID = "<Facebook App ID>"
APP_SECRET = "<Facebook Client Secret>"
# Get app access token - this works
response = requests.get('https://graph.facebook.com/oauth/access_token',
params={'grant_type': "client_credentials",
'client_id': APP_ID, 'client_secret': APP_SECRET})
app_access_token = parse_qs(response.content)['access_token'][0]
# Create test user - this works
response = requests.post('https://graph.facebook.com/%s/accounts/test-users' % APP_ID,
data={'access_token': app_access_token, 'installed': "true"})
test_user = response.json()
login_url = test_user['login_url']
print login_url # http://developers.facebook.com/checkpoint/test-user-login/...
# Get cookied for login - see https://stackoverflow.com/a/5370869/647002
session = requests.Session()
session.get("https://www.facebook.com/", allow_redirects=True)
# Login test user - THIS FAILS
response = session.get(login_url)
print response.status_code # 404
Others have noted that you must first fetch the Facebook homepage before test user's login_url will work. We ran into that same problem, and I've included that workaround above without any luck. [Edit: added the _fb_noscript=1 query param, required starting mid-2015 for non-JavaScript test clients.] [Edit 8/2017: now removed _fb_noscript=1; no longer required, and sets a noscript cookie that makes some later FB auth requests return 500.]
I also tried opening the login_url directly in a browser:
If I'm not already logged into Facebook, I get a generic Facebook 404 page.
If I'm already logged into my developer account, Facebook warns that I'll be logged in as a platform test user, and then allows me into the test user's account.
That last point seems to confirm that the test user is being created properly and that I have the correct login_url. But of course, that's no help for automated testing. (We don't want to run tests logged into my developer account.)
Is there some other way the test user's login_url is meant to be used for automated testing?
A Facebook developer support engineer has confirmed that the test-user login_url can no longer be used for automated login of a test user, due to security changes. Apparently it's meant for manual testing.
I am, however, able to achieve automated login of a programmatically-created Facebook test user by posting to Facebook's normal login form. It seems like all you need are the email and password returned from the create-test-user API. (No other login form fields seem to be needed, though you'll still need to pick up the cookies first.)
The code below is working for me now (replacing the last two "this fails" lines of code from the original question):
# Login test user - THIS WORKS
response = session.post("https://www.facebook.com/login.php",
data={'email': test_user["email"],
'pass': test_user["password"]})
print response.status_code # 200
I haven't found this documented anywhere, and Facebook may change their login form in the future, so YMMV.
I'm utilizing the Facebook PHP SDK on its own. I do not want to use the JS SDK at all.
Because getUser(); from the SDK can return a user id even if the user is not logged in, I have opted for using a try/catch statement to check if the user is logged in.
try
{
$me = $CI->facebook->api('/me');
$CI->our_fb['is_fb']='YES';
echo "hello";
}
catch(FacebookApiException $e)
{
echo "catch";
}
This statement is included in the global include file of all of my files (for simplicity).
So, depending on the situation, I generate a Facebook login URL. The expected functionality is that the user logins to Facebook, authorises the app, is returned to the redirect URI set in the login URL at which point the try statement will execute, and $CI->our_fb['is_fb'] will be set.
This is however not happening.
If the user is already logged into Facebook and the app is authorised, it works perfectly. SUCCESS
If the user is not logged into Facebook, once redirected the variable is not set. FAILURE
If the user is logged in but the app is NOT authorised after redirect the variable is not set. FAILURE.
In the latter two cases if you simply refresh the page, the variable is set - SUCCESS. Refreshing the page is however unnecessary/pointless extra effort.
My problem is that if you need to login to FB/or authorise the app e.g the first time you login with FB, you have an additional unneeded refresh, and I don't know why.
I suspect it is something to do with the cookie/session? Which saves the access token that I assume is returned/passed to the SDK automatically not being set at the same time?
Anyone got any ideas?
If you're having an app on facebook (tab or canvas). PHP SDK only get the User ID on initial loading of a page because a signed_request is sent with the request to your app.
But, when the app refreshes, the signed_request is lost (as it's facebook who send it).
So, in this case, you can append the signed_request to every URLs your use in your app - but that's really not optimal as the signed_request won't be regenarated - neither refreshed.
Your only real option is to rely on the JS SDK to set cookie correctly and allow getUser to work as expected. This is required because you're considered as a third-party app in Facebook (being in an iframe) and most browser will block you from setting cookies - so you need a work around handled by the JS SDK for you. You can search for cross-domain cookies or third-party cookie for explanation about the workarounds, but these workaround only work via JS scripting and iframe management.
Also, be sure to setup the JS SDK correctly: channel file, cookie allowed, and send P3P headers (for IE).
You can also check this related question: A proper approach to FB auth
About website, the same mostly stays (but you have no signed_request). At this point, seriously consider using the JS SDK as it's way easier. Or else, you can make sure your app flow follow these guidelines: https://developers.facebook.com/docs/concepts/login/login-architecture/
The way I am seeing this is, you are trying to avoid that refresh if the user is not logged in and precedes to log in after the page has initially loaded.
So what you can do is make an ajax request to another page on your site, say for example id.php, which just loads the php sdk and echo $userid; and then you can grab the user id after login without the refresh.
Basically the cookie is used to save the signed request and session is used to save 'state', 'code', 'access_token', 'user_id'. If the above are present PHP SDK uses them, no matter if they are valid or not.
I think your problem lies in the CODE sent by facebook. Specifically these lines in base_facebook.php:
if ($code && $code != $this->getPersistentData('code')) {
$access_token = $this->getAccessTokenFromCode($code);
...
protected function getAccessTokenFromCode($code, $redirect_uri = null) {
if (empty($code)) {
return false;
}
if ($redirect_uri === null) {
$redirect_uri = $this->getCurrentUrl();
}
...
Because CODE is issued for specific url sometimes there is such situation: Visitor arrives on www.example.com. He givies permissions and is redirected to example.com/login. But the code is not valid there, so the getUserAccessToken returns false. When you refresh the page you get same urls and everything's fine.
You're on the right track of not using getUser() because as I wrote above it's taken from the session if available.
I got some problem with my testing app
$params = array(
'scope' => 'read_stream, publish_stream'
);
$loginUrl = $facebook->getLoginUrl($params);
echo "<script type='text/javascript'>top.location.href = '$loginUrl';</script>";
This is the code I use to send user who has not logged in yet to login
via facebook auth dialog.
The problem is after login using facebook auth dialog
user will be redirected to my site which is not in facebook app.
How can I send user back to facebook app after login using auth dialog ?
Please help
You can use the redirect_uri parameter of getLoginUrl() to tell facebook where you want to send the user after authorization ends (let it be success or failure).
There's a number of restrictions on what you can use there, basically you got three options:
URL under your application's domain.
The canvas path of the application (if it has one): https://apps.facebook.com/YOUR_APP_NAMESPACE
Any page url that has your application installed: https://www.facebook.com/PAGE_USERNAME/app_YOUR_APP_ID
By default, the php sdk takes the current url as redirect_uri. The documentation about these are under the oauth dialog's documentation of the same parameter.
Was google-ing about the same issue and found a solution,so thought might as well answer her.
simply add the following code in the main page.
$config['appBaseUrl'] = "http://apps.facebook.com/your_app_name/";
if(isset($_GET['code']))
{
header("location:" . $config['appBaseUrl']);
exit;
}
$config is the array that i pass while creating the facebook object. In this context,its not necessary to create an array though.
facebook, as usual does not work as expected.
on calling
$facebook->getLogoutUrl($params);
using
$params = array( 'next' => 'http://mywebsiteurl.com/loggedout.php' );
The browser view is redirected to loggedout.php, which is good.
Except when the user proceeds to facebook.com they find they are still logged in, which is not good.
So, where do we go from here?
What am i doing wrong?
What did facebook do wrong?
it's because of the cookie. I did the following to fix this issue ...
in the params for the getLogoutUrl method you set your own logout URL:
$facebook->getLogoutUrl(array( 'next' => 'http://www.yourdomain.com/logOut/' ));
and in your logout file you reset the cookie:
setcookie('PHPSESSID', '', time()-3600, '/');
header('Location: http://www.yourdomain.com');
I have the same issue. After returning from the logout URL, calling $facebook->getUser() still returns the user's id.
I got around this by adding a query string to the 'next' parameter, which if set, I treat the user as if they were logged out.
I've had similar issues with the SDK, where using the getLogoutUrl(); with a next parameter does not ever get redirected back to the web-application.
So, I've given up on getting the users to be able to use that functionality to dis-connect my application. Now I just delete their access tokens from our system and tell them to manually de-authorise the application on the FB site - and provide a hyperlink to http://www.facebook.com/settings?tab=applications
I'm develpping a site and I put the facebook connect using PHP SDK 3.
The problem is that the page where facebook returns the results after the user authenticates and grants permission. for me after a user clicks "allow", it authenticates and then returns back to the same page (index) with a query string.
What I want is that if the user clicks "don't allow", he will be redirected to a certain page like login-fail.php, and if he grants permission he is redirected to login-success.php where his data will be processed and stored in the database.
any ideas?
You cannot specify a redirect URL in case of error. The best you can do is to set a redirect URL that will be the same for success or error :
$args['redirect_uri'] = "http://www.yoursite.com/after-dialog.php"
$url = $facebook->getLoginUrl($args);
If the user clicks "Don't allow", he will be redirected to the page after-dialog.php with the following GET parameters :
error = access_denied
error_reason = user_denied
error_description = The+user+denied+your+request.
If you really want to redirect him according the success of his login, you can track it at the top of the after-dialog.php file by :
if (isset($_GET['error'])) {
header('Location: http://www.yoursite.com/login-failed.php");
} else {
header('Location: http://www.yoursite.com/login-success.php");
}
Hope that helps !
EDIT: As you pointed out (in the comments of this answer) the comments in the code of the SDK say :
redirect_uri: the url to go to after a successful login
But the reference of the API says :
If the user presses Don't Allow, your app is not authorized. The OAuth Dialog will redirect (via HTTP 302) the user's browser to the URL you passed in the redirect_uri parameter.
and :
If the user presses Allow, your app is authorized. The OAuth Dialog will redirect (via HTTP 302) the user's browser to the URL you passed in the redirect_uri parameter.
I also ran some tests and the user is always redirect to redirect_uri, even if he clicks "Don't allow". It must be a typo in the code comments.
In my case I solved this problem with a checking of the parameter "error_reason", when an user click in Don't Allow, the url carry this parameter. You can see it in this page:
http://aplicacionesfacebookparadummies.blogspot.com/2011/09/obtener-datos-usuario-mediante-login.html