I am using Firebase Auth Rest API. I have code written in PHP to add the user to the database and firebase authentication. The information I store is kind, idToken, email, refreshToken, expiresIn, localId. It all works great!
Now when I am trying to delete the user from database it works fine but does not delete the user from the firebase authentication. Please find the code below for sign up and deleting the user.
The errors I get is either
CREDENTIALS_TOO_OLD_LOGIN_AGAIN (or)
INVALID_ID_TOKEN.
FIREBASE_KEY is my firebase key and in the $data I am passing the user idToken
/*
* User Sign Up
*/
function user_signup($data){
$response = true;
$data = json_encode($data);
$url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=".FIREBASE_KEY;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$jsonResponse = curl_exec($ch);
if(curl_errno($ch))
{
$response = false;
}
curl_close($ch);
return $jsonResponse;
}
/*
* User Delete
*/
/* function user_delete($data){
$response = true;
$data = json_encode($data);
$url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/deleteAccount?key=".FIREBASE_KEY;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$jsonResponse = curl_exec($ch);
if(curl_errno($ch))
{
$response = false;
}
curl_close($ch);
return $jsonResponse;
} */
There are two ways to interact with the Firebase REST APIs:
By authenticating your requests with a user's ID token, with the same permissions and limitations as if they would interact with your application on their own
By authenticating with the credentials of a Service Account, which gives you full access to your application, without any limitations.
To delete a user, you can use both methods, but when using a user's ID token, you have to authenticate as the user (effectively impersonating them) before being able to perform any actions on behalf of said user.
The better solution would be to use an Admin SDK to perform that task. By authenticating your requests to the Firebase REST APIs with Service Account Credentials as described in
Add the Firebase Admin SDK to Your Server, you will be able to perform administrative tasks (like deleting a user from the authentication database) more easily.
Here are the steps to get started with Service Account based authentication:
Generate Service Account credentials on https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk
Use the Google Auth Library for PHP to be able to make authenticated calls the Google/Firebase APIs https://github.com/googleapis/google-auth-library-php#call-the-apis
When you have created an HTTP client with the help of the Auth library, you can call this API endpoint to delete the user
$client->post('https://www.googleapis.com/identitytoolkit/v3/relyingparty/deleteAccount', [
'json' => [
'localId' => 'uid-of-user-to-delete'
]
]);
The localId parameter is not documented on https://firebase.google.com/docs/reference/rest/auth/#section-delete-account, but it's used from within the official admin SDK and works.
Using an Admin SDK (https://firebase.google.com/docs/admin/setup#initialize_the_sdk) would be the recommended way to perform administrative tasks like this. Official SDKs exist for Node.js, Java, Python, Go and C# - I maintain an unofficial one for PHP that you can find at https://github.com/kreait/firebase-php. With it, you could perform the same task like this:
// kreait/firebase-php ^5.0
$factory = (new Factory)->withServiceAccount('service_account.json');
$auth = $factory->createAuth();
$auth->deleteUser('uid-of-user-to-delete');
// kreait/firebase-php ^4.0
$serviceAccount = ServiceAccount::fromJsonFile('service_account.json');
$firebase = (new Factory())
->withServiceAccount($serviceAccount)
->create();
$firebase->getAuth()->deleteUser('uid-of-user-to-delete');
On a side note:
I would consider storing a user's ID token in a separate database a security risk: if your database gets compromised, attackers gain access to your user's ID tokens and can use those who aren't expired yet to access your application.
The recommended flow to pass a user from your frontend (web, mobile) to your backend (server) is:
Use a Firebase Client SDK in your frontend, e.g. in your web application
Let the user sign in to Firebase in the frontend via the client SDK, and when a user successfully signed in, retrieve the ID token on your client, send it to your backend and verify the ID token on your backend.
Once you've verified the ID token, you can extract the Firebase ID of your user from the ID token and save it to your database, e.g. in a table that maps your local user id to the Firebase User ID without the need to store their full ID token (= full credentials)
Related
Currently I am trying to get reviews from https://play.google.com/store/apps/details?id=com.rosterelf.android.phone&hl=en by following https://developers.google.com/android-publisher/api-ref/rest/v3/reviews/list documentation.
I am using the PHP (cURL) method but I am keep getting an error saying --- Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential.
Below are my steps what I have done / tried so far.
Created one Api KEY, OAuth 2.0 Client ID and Service Account in Google Developer Console.
Enabled the Google Play Android Developer API and Google Play Custom App Publishing API too.
Going at my browser https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&redirect_uri=REDIRECT-URI&client_id=CLIENT-ID
It gives me the code in response and then to be able to get access_token, I am using below PHP cURL code which is also working fine.
<?php
$client_id = 'CLIENT-ID';
$redirect_uri = 'REDIRECT-URL';
$client_secret = 'CLIENT-SECRET';
$code = 'CODE';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://accounts.google.com/o/oauth2/token");
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'code' => $code,
'client_id' => $client_id,
'client_secret' => $client_secret,
'redirect_uri' => $redirect_uri,
'grant_type' => 'authorization_code'
));
$data = curl_exec($ch);
var_dump($data);
exit;
And in response, I am successfully able to get the access_token.
Now I am trying to go directly to this page in browser https://www.googleapis.com/androidpublisher/v3/applications/com.rosterelf.android.phone/reviews?access_token=ACCESS-TOKEN but it keeps saying me...
Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project
-> I have checked the roles and permissions and it has owner as a permission in service account.
-> My REDIRECT-URI also the same URL throughout this process.
I event tried this URL to fetch the reviews https://androidpublisher.googleapis.com/androidpublisher/v3/applications/com.rosterelf.android.phone/reviews/review?access_token=ACCESS-TOKEN but having the same error.
Can someone please guide me what am I missing from here and why I am getting here and what exactly I should do from here on to get the reviews ?
Any help or suggestions will be highly appreciated.
Thanks in advance.
This is an example for that API using the official client library. I believe this code is for service account authentication. The service account will need to be properly configured see using_a_service_account How to create service account credetinals just remember to enable the proper library.
<?php
require_once 'google-api-php-client-2.2.2\vendor\autoload.php';
putenv('GOOGLE_APPLICATION_CREDENTIALS=client_secret.json');
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(Google_Service_AndroidPublisher::ANDROIDPUBLISHER);
$android_publisher = new Google_Service_AndroidPublisher($client);
$response = $android_publisher->reviews->listReviews('appname');
echo "<pre>";
var_dump($response);
We are planning interaction between php script to ruby on rails server and vice-versa.
Whenever I do curl post data from php script, on rails server notification displays - "Can't verify CSRF token authenticity".
I am passing authenticity_token in post parameters. We need to how to use this token in secure manner on rails server.
<?php
class active_merchant{
private $endpoint_url; // server address or url where data is to be posted.
private $params; // form fields
private $fields_count; // count of fields in credit card
public function __construct(){
$this->endpoint_url = "http://localhost:8080/activemerchant/index";
$token = md5('random');
$this->params = array('name'=>'test','authenticity_token'=>$token);
}
/* function curl_post
makes a curl post to the end point url
global variables
*/
public function curl_post(){
try{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->endpoint_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($this->params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$response = curl_exec($ch);
print_r($response);
//return $response;
}catch(Exception $e){
throw new Exception($e->getMessage(),$e->getCode(),$e->gtLine());
}
}
}
$active_merchant = new active_merchant();
$active_merchant->curl_post();
?>
Rails code -
class ActivemerchantController < ApplicationController
protect_from_forgery except: :index
def index
Rails.logger.debug params.inspect
puts params.inspect
self.response_body = "Hello, world!"
end
end
Can anyone tell us how can we keep our authenticity_token random ,consistent and secure between two servers (php and ruby on rails).
If are using the rails controller as an API, protecting with CSRF tokens doesn't make sense. As the name Cross-Site Request Forgery tokens say, they prevent your app from being accessed from anywhere other than the views generated by the same web app.
So, you should disable CSRF in your case and use the authenticity token.
Answering your question with how to securely use this authenticity token on rails app, if you have any user management, assign authenticity tokens to users and find user with a sent token and you know if that user is allowed to make that request. If you don't have a user management, create a database table for authenticity tokens and validate the requests based on what you have in database.
You could write a custom before_filter in application_controller and perform the authentication or authorization based on the authenticity_token in the request.
P.S, if you are worried about the authenticity_token being visible for attackers in the network while sending requests, use https.
If Rails app is used as an API server, then simply add protect_from_forgery with: :null_session in appropriate controller.
I'm trying to create an application on LinkedIn that's using OAuth2 for authentication and am running into some errors. The client runs on an iOS device and uses an oAuth library to make a call to LinkedIn's servers. My iOS client successfully gets the authorization_code. The client application then passes that authorization_code to my server, which attempts to connect to linkedIN again and get the access_token. This step consistently fails, I get the following error from LinkedIn: {"error":"invalid_request","error_description":"missing required parameters, includes an invalid parameter value, parameter more than once. : client_id"}
My POST method to LInkedIN does contain the client_id, it only contains it once, and I've triple checked the values for all the parameters, they are correct. I've also reset the access multiple times from https://www.linkedin.com/secure/settings and I've even created additional applications on LinkedIn, I keep getting the same result.
I've checked other responses, such as this one: unable to retrieve access token linkedin api and tried the suggestions: revoke keys, request new keys etc, nothing seems to be working.
Here is my server code:
$tokenURL = 'https://www.linkedin.com/uas/oauth2/accessToken';
$redirectURL = 'https://staging.textsuggestions.com';
$clientId = '75a4ezqh741sup';
$clientSecret = 'XXXXXXXX';
$tokenArguments = array("grant_type" => "authorization_code",
"code" => $code,
"redirect_uri" => $redirectURL,
"client_secret" => $clientSecret,
"client_id" => $clientId);
// send the request to the server getting data
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $tokenURL);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $tokenArguments);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (!empty($response["error"])) {
error_log("Error is: " . $response["error"]);
exit (0);
} else {
// no error, get the access_token and do stuff with it
$timeout = $response["expires_in"];
$access_token = $response["access_token"];
}
Ok I realized what I was doing wrong, the client application library that I was using was generating the full access token (not the auth code). So I was trying to pass in the access token in the place of the auth code. The error that I was getting from Linked In was certainly misleading and I should have checked the client library I was using more carefully.
Have you tried to check your code against this code sample?
https://developer.linkedin.com/documents/code-samples
Check that the POST headers include "Content-Type": "application/x-www-form-urlencoded".
My goal is to make a LinkedIn company updates feed on a website using the Linkedin PHP REST API or JavaScript api. This feed needs to be available to any user visiting my website, however, all the codes samples I can find are asking me to redirect visiting users to Linkedin for OAuth so I can get an access token to make API calls. This is not what I need.
How can I make API calls for my company for any anonymous user coming to my site (without any redirection to LinkedIn)? This must be possible. I have registered an application already on Linkedin and received:
API Key: XXXXX
Secret Key: XXXXX
OAuth User Token: XXXXX
OAuth User Secret: XXXXX
A related question is what are the OAuth User Token and OAuth User secret for that were supplied to me when I registered my Linkedin application?
If you already have a token then check the part in the documentation about fetching the profile, it works exactly the same for company updates, just different url: https://developer.linkedin.com/documents/code-samples
Here's the PHP code required to obtain company updates:
$token = "<your_access_token>";
$url = "https://api.linkedin.com/v1/companies/<company_id>/updates";
$headers = array(
'Authorization: Bearer ' . $token,
'x-li-format: json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Use the code in the link from the other answer to obtain an access token for your client.
What I have:
Twitter app created at twitter and PHP app at localhost
What I want:
post tweets/update statuses via twitter API from only(!) the app account.
No twitter#anywhere, no user login, nothing fancy.
What I tried:
https://github.com/abraham/twitteroauth with access tokens from the dev.twitter.com website, returned
"POST data is not available with this
token"
or something like that.
code snippet I found on some website:
// Define credentials for the Twitter account
define('TWITTER_CREDENTIALS', 'username:password');
// Set up CURL with the Twitter URL and some options
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://twitter.com/statuses/update.xml?status=test_status');
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Twitter uses HTTP authentication, so tell CURL to send our Twitter account details
curl_setopt($ch, CURLOPT_USERPWD, TWITTER_CREDENTIALS);
// Execute the curl process and then close
$data = curl_exec($ch);
curl_close($ch);
// If nothing went wrong, we should now have some XML data
echo '<pre>'.htmlentities(print_r($data, true)).'</pre>';
returned
"Basic authentication is not
supported"
That big code snippet uses basic authentication, which is no longer supported by Twitter. Disregard it.
OAuth is now required by Twitter instead, which is what abraham's twitteroauth library uses. You will have to log in/authenticate using this, at least once.
You will also have to first register your app with Twitter, to receive your own Consumer Key and Consumer Secret. Then you'll be able to start using Twitter's API via twitteroauth.
Okay I've found what's the problem.
By default, Twitter sets all apps to read-only, so even when you login via PHP, you can't send POST/UPDATE. What you need to do is go to your application settings (the one where you set app name, description and avatar) and before avatar there's a "default access type", switch it to
Read, Write, & Direct Messages
and voila.
to test the app use this snippet
$twitter = new \TwitterOAuth('consumer_key', 'consumer_secret',
'(oauth_token', 'oauth_token_secret');
$twitter->get('account/verify_credentials');
$twitter->post('statuses/update', array('status' => 'test status'));
Oh and you don't need to do the login stuff with your app, you get the required tokens under "My access Token" menu.