I'm using Firebase to do a small project and while testing things I discovered I can do cURL requests from any server to my Firebase Database (tested on an online php tester), so I'm considering this is a security flaw for my project and I have been looking for a method to add some kind of password for cURL requests, but I found nothing, at least nothing I could understand. I know firebase have rules to manage who can read or write on my database, but I didnt find something that could filter requests by server or only allow requests that have an special password sent as parameter.
So my question is if there is a way to do something like that I could use on my project so only cURL requests made for me would work.
Here it is one of my cURL requests, in case it helps for resolving my problem.
$url = "https://mydatabase.firebaseio.com/profile/messages/".$_COOKIE['cookiename'].".json";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
Thanks in advance for helping me out.
UPDATE: I found this, I think it could be the thing I need, but Im missing the part where I tell the database to ask for the access token. https://firebase.google.com/docs/database/rest/auth
One solution is to use the Firebase Auth REST API.
In particular, "you can sign in a user with an email and password by issuing an HTTP POST request to the Auth verifyPassword endpoint", see here.
Then you can use the user's uid in your Firebase security rules, in order to protect your database.
You should read and understand the documentation for the REST API. If you want to bypass security rules that would normally apply to web and mobile users, you will need to generate an OAuth token for a service account that has permissions to access your database, and use that in your requests.
If you don't want public access to your database, you will have to set up security rules to limit that. To stop all public access, your rules should be:
{
"rules": {
".read": false,
".write": false
}
}
Related
I used instagram public api (adding __a=1 to parameters of an url) to get a post detail (caption ,imageUrl, postType, likes, comments , viewsCount). But it seems that Instagram banned that recently and returned a 403. It also asks for login when I try to directly open a post by its usrl.
I tried to use the instagram private api (https://mgp25.github.io/) for getting post details, but after some requests instargam banned that too:
"throttled by instagram because of too many api requests"
Do you have any offer for an alternative?
Actually it is not really banned but now redirects with 302 to auth page. It seems like auth is required when Instagram account and query geoIPs are different. Alternative is to use official API. No scraping can be done, because the profile link now also requires authentication. You can do authenticated scraping but you are limited to 200 queries ( that Instagram sends to get data) per hour.
Instagram blocked all public endpoints with some limitations and hit rate. Now you need to send the user's session to get the response.
Did you notice the same endpoint returning the JSON response when you are logged in on Instagram in the same browser? Yes, that because whenever you are hitting the URL like "https://www.instagram.com/anything/?__a=1", your browser sending the live and valid sessionid to Instagram. Since you are logged in hence Instagram served you well.
Ever you wonder why the same endpoint started to work again after changing the Internet connection from Wifi to Mobile hotspot or try with another internet service provider.
It's because your IP got blocked and no more free hot babes for you until you are logged in.
Below is the PHP code to give a try with sessionid.
<?php
// keyword or user name
$hashtag = $username = "msevylynch";
// $endpoint = "explore/tags/$hashtag"; // hashtag search
$endpoint = $username; // user search
// login in insta account and copy session from browser's cookie tab
$sessionid = '<YOU-SESSION-ID-PICK-FROM-BROWSER-AFTER-LOGIN>';
$ch = curl_init();
https://www.instagram.com/explore/tags/msevylynch/?__a=1
curl_setopt($ch, CURLOPT_URL, "https://www.instagram.com/{$endpoint}/?__a=1");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Cookie: ds_user='.$username.'; igfl='.$username .'; sessionid=' . $sessionid,
'User-Agent: Instagram 7.16.0 Android'
));
$response = curl_exec($ch);
header('Content-Type: application/json');
echo $response;
?>
Still no luck then it means Instagram blocked you or your IP for some time due to
hitting endpoint too early or very fast programmatically
denied the presented challenge
seems it's an automated hit
password is changed
you are logged out
or your internet bill is over due .. ha ha ha
Thank you for the reading this long, much apriceated.
Instagram is getting very strict with __a=1 endpoint. Your best bet in 2021 to get Instagram profile info is to use clean residential proxies
They require residential IPs to access ?__a=1 pages without login. https://webscraping.ai works for it if you use proxy=residential parameter. An example of such a request:
curl "https://api.webscraping.ai/html?api_key=test-api-key&proxy=residential&url=https%3A%2F%2Fwww.instagram.com%2Finstagram%2F%3F__a%3D1"
I used instagram public api (adding __a=1 to parameters of an url) to get a post detail (caption ,imageUrl, postType, likes, comments , viewsCount). But it seems that Instagram banned that recently and returned a 403. It also asks for login when I try to directly open a post by its usrl.
I tried to use the instagram private api (https://mgp25.github.io/) for getting post details, but after some requests instargam banned that too:
"throttled by instagram because of too many api requests"
Do you have any offer for an alternative?
Actually it is not really banned but now redirects with 302 to auth page. It seems like auth is required when Instagram account and query geoIPs are different. Alternative is to use official API. No scraping can be done, because the profile link now also requires authentication. You can do authenticated scraping but you are limited to 200 queries ( that Instagram sends to get data) per hour.
Instagram blocked all public endpoints with some limitations and hit rate. Now you need to send the user's session to get the response.
Did you notice the same endpoint returning the JSON response when you are logged in on Instagram in the same browser? Yes, that because whenever you are hitting the URL like "https://www.instagram.com/anything/?__a=1", your browser sending the live and valid sessionid to Instagram. Since you are logged in hence Instagram served you well.
Ever you wonder why the same endpoint started to work again after changing the Internet connection from Wifi to Mobile hotspot or try with another internet service provider.
It's because your IP got blocked and no more free hot babes for you until you are logged in.
Below is the PHP code to give a try with sessionid.
<?php
// keyword or user name
$hashtag = $username = "msevylynch";
// $endpoint = "explore/tags/$hashtag"; // hashtag search
$endpoint = $username; // user search
// login in insta account and copy session from browser's cookie tab
$sessionid = '<YOU-SESSION-ID-PICK-FROM-BROWSER-AFTER-LOGIN>';
$ch = curl_init();
https://www.instagram.com/explore/tags/msevylynch/?__a=1
curl_setopt($ch, CURLOPT_URL, "https://www.instagram.com/{$endpoint}/?__a=1");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Cookie: ds_user='.$username.'; igfl='.$username .'; sessionid=' . $sessionid,
'User-Agent: Instagram 7.16.0 Android'
));
$response = curl_exec($ch);
header('Content-Type: application/json');
echo $response;
?>
Still no luck then it means Instagram blocked you or your IP for some time due to
hitting endpoint too early or very fast programmatically
denied the presented challenge
seems it's an automated hit
password is changed
you are logged out
or your internet bill is over due .. ha ha ha
Thank you for the reading this long, much apriceated.
Instagram is getting very strict with __a=1 endpoint. Your best bet in 2021 to get Instagram profile info is to use clean residential proxies
They require residential IPs to access ?__a=1 pages without login. https://webscraping.ai works for it if you use proxy=residential parameter. An example of such a request:
curl "https://api.webscraping.ai/html?api_key=test-api-key&proxy=residential&url=https%3A%2F%2Fwww.instagram.com%2Finstagram%2F%3F__a%3D1"
I am trying to securely login a user via their Google account.
I am at the stage that I retrieve the userID and oAuthToken using this cordova plugin.
Now I am at the point where I need to send these credentials to my server and then on the server side validate the integrity of the token. Essentially I am trying to perform this part of the process.
I am confused as to which token I should try to verify using the Google client api. Should I use the userID or the oAuthToken ?
The documentation mentions validating the userID but I find this strange. Wouldn't this mean that if anyone gets my user id they can essentially break into my server ? The user id never changes (correct me if I am wrong here) so it seems insecure to validate on this. Wouldn't it make more sense to validate the oAuthToken which is set to expire ? Or does the user ID also expire ?
Any advice would be welcome.
Thanks,
Fido
Edit:
For anyone interested. My confusion arose due to not understanding fully three tokens which the google api can return: userId, oAuthToken, and idToken.
Briefly:The userId is returned with most api calls identifying the user. This appears to be constant. The oAuthToken in my case was returned when I accessed the google api as an Android client. The tokenId is returned when accessing the api as a web client. So those wishing to do server side validation using a mobile retrieved token should access the api as a web client. The token returned can then be validated server side using code similar to the accepted answer below.
you need to validate the IdToken, never send the userId on an open line. the IdToken expires quickly and it is virtually impregnable to brute force impersonation attacks.
this php snippet receives an HTTP request that starts with idtoken=, validates your token serverside and returns either the complete array or user email:
<?php
$inputRaw = file_get_contents('php://input');
$idToken= substr($inputRaw,8);
$fp = fopen('twoStepOutput.txt', 'a');
$url = 'https://www.googleapis.com/oauth2/v3/tokeninfo?id_token='.$idToken;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$json = json_decode($response, true);
curl_close($ch);
$userEmail = $json["email"];
$clientId = $json["azp"];
//fwrite($fp, date("YmdHis")."\r\n$idToken\r\n");
fwrite($fp, date("YmdHis")."\r\n");
fwrite($fp, "email Confirmed by GOOGLE:[$userEmail]\r\n");
//print_r($json); // returns array console readable
print_r($clientId); // returns google client id for verification (without transfering user data)
fclose($fp);
?>
just in case you are in doubts, this is what an IdToken looks like:
eypZCI6OiJSUzI1JhbGciNiIsImtIjk4MzQxMzgyMWJmMzhiNTJlM4OTI2YTllMTc0YTc5MWMwNGMifQ.eyJpc3MiOi3VizExYJhY2NvdW50cy5nb29nbGUuY29tIiwicmEIjoiMTAzNDUyNjAwODM5NzY3MjU2MDE0IiwiYXpwIjoiMTA3OTMxMTEyNTc1OS1lYWJhbWV0b2ZldjIwY28zbGQ5b2o1YWQwMzFuZG9nMC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidG9ueWdpbGJyQGdtYWlsLmNvbSIsImF0X2hhc2giOiJaSkhxbUZHcnR5Y29kdEhhOGJvMEYWY1NTk2NzUsImV4cCVBIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImF1ZCI6IjEwNzkzMTExMjU3NTkt1ldG9mZXYyMGNvM2xkOW9qNWFkMDMxbmRvZzAuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJpYXQiOjE0MzZWFiI6MTQzNjU2MzI3NSwibmFtZSI6IlRvbnkgR2lsIiwicGljdHVyZSI6Imh0dHBzOi8vbGg0Lmdvb2dsZXVzZXJjb250ZW50LmNvbS8tQVREckRSbF9UdFEvQUFBQUFBQUFBQUkvQUFBQUFBQUFBRncvOVdDQnZkYlpUTEEvczk2LWMvcGhvdG8uanBnIiwiZ2l2ZW5fbmFtZSI6IlRvbnkiLCJmYW1pbHlfbmFtZSI6IkdpbCIsImxvY2FsZSI6ImVuIn0.L4peW11TD0bDOlvYKNY60ieZ1sbZfW9gEImcuxVA5f9U_4N49Io1CFXoGKmEPR_ij4q38tF2drPMOKijQePwlrxDui37ubzAdVkuksCJUobzjD1_eccF_8GldP5Y1_XsU8xrZeEnfabfiYpr-VwoLzIeNNUdy9SUbUWjMHNcvf4dGFMzE_SONHr57igjHK3rGkbvLo-UduFngm3e-EL0YR2zOKOVj1Qs8g8_qpWgkn8XABTme1thmuU8OfC-HaF9_B2Zk2UCsnOu4ApiYZk3DPIKgeX6AF11kYnzgvciYheWeddly0foT4G00C7w_wgtd-LSRw0XZltec_MPMa2QSA
I was trying to get the feeds of friends' fan pages with a cURL and to post a like via app.
The cURL GET works fine, but when it comes to liking the object (that has for sure likes enabled because it's facebook), all I get is a boolean (and no action).
I had seen on SO that you post a like with
($access_token, "https://graph.facebook.com/$post_id/likes", 'POST')
However, it is not working (it says either that the app has no permissions to do that, or that I need a valid url).
I have tried all possible solutions but nothing seems to work. The profile is mine, the access token too, and I gave publish_stream permissions to my own app.
After having given a try to the SDK PHP Likbrary, I tried a direct cURL post, with the following code:
function likeit($url){
//open connection
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, $url);
curl_exec($ch);
curl_close($ch);
}
The execution i a puzzle. When it does not return an OAuth Exception it returns boolean and stops there (there is no way for me to "like" the post I want to like). The last attempt (but I've tried them all, even the whole url in some tests) is
foreach ($feeds->data as $feed_data)
$message = $feed_data->message;
$title = $feed_data->name;
$link = $feed_data->link;
$id = $feed_data->id;
$myaccesstoken = "longlastingaccesstokenstring";
$post=likeit($myaccesstoken, "https://graph.facebook.com/$post_id/likes", 'POST');
Does anybody have a suggestion on how to do this? It seems trivial and yet there is no way for me to accomplish it. Thank you so much in advance!
I've found a solution, and thus am posting it here for future reference (hoping it is helpful for anybody with the same problem):
the only problem was that after the new permissions with facebook I needed to re-authorize my app.
After that, it is possible to post a like with the SDK facebook library, normally:
$facebook->api("/$id/likes", 'post', array(
'access_token' => $myaccesstoken));
No need to use cURL directly. Hope this helps someone with the same question.
I'm building a PHP application from scratch (using Kohana3 framework). I'm going to architect it so that I can use an API to access the data internally. At the same time, I want to eventually offer it to the public.
I plan on using the RESTful access method. However, I'm having a hard time finding clear information on how to properly secure the API. In other words, how do I implement API signatures and access?
You could try frapi. It will quickly allow you to build your RESTful API, which you can then use for your application, and at a later date expose the same API publicly.
OAuth would be a good choice. So would a single key/value pair. You might also want to look at Mashape but not entirely sure it fits what you are trying to do.
I think a good place to start would be reading over general information about digital signing. Wikipedia is a great resource http://en.wikipedia.org/wiki/Public_Key_Infrastructure or http://en.wikipedia.org/wiki/X.509.
On a basic level I would give each client a private Key. In the client library I would encrypt the key. When a client makes a request verify that the key is the one that you issued to that particular client.
Take a look at 3scale (http://www.3scale.net/) to do this - it handles authentication, access control, policies, rate limits etc. and is free for significant traffic. We have a PHP module to plugin to the system to enable these features. (Disclaimer - I work there - but hope it's useful!)
Your question is a bit bigger than this; but I can offer one small observation about REST.
I have found with REST, that is that it is best to use artificial keys for the underlying data model, rather than natural keys.
For example, consider the RESTfull url: https://server/yourApp/viewUser/1234.html this would show the user with id 1234. However if you used natural keys you might have a URL something like this https://server/yourApp/viewUser/Bob.html or worse if instead of Bob its "Bob X" or "Bob?key=Value". You don't want to have to think about generating invalid URLs.
I have made a PHP REST API using CodeIgniter with Basic Authentication, (providing "company id" and "API Key" as username/password). Later we found that it was necessary to provision session keys that were directly related to an API Key, only with an expiration time.
Basically, we queried different types of data in our datastore (nosql variety :) depending on what the "method" was provided in the URL. We accessed this by using the "segment" ability provided by CodeIgniter.
Then we wrapped each response with a "json_encode" that was returned and we also used an HTTPS connection for security.
For the client class we wrapped everything in calls such $client->get_my_data($api_key), with a layer underneath using PHP Libcurl, which works really well to provide the Basic Auth.
Hope this helps,
CURL_GET
private function curl_get($url, $apikey, $co)
{
$curl_handle = curl_init();
curl_setopt($curl_handle, CURLOPT_URL, $url);
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl_handle, CURLOPT_USERPWD, $co.":".$apikey);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_DNS_USE_GLOBAL_CACHE, FALSE);
$buffer = curl_exec($curl_handle);
$error = curl_error($curl_handle);
curl_close($curl_handle);
// check for success or failure
if (empty($buffer)) {
//echo 'Something went wrong :( error: '.$error.'<Br>';
} else {
return $buffer;
}
}