So I'm using CodeIgniter framework and trying to get user friends. I have no problems with authentification, but when I try to get user friends using GET method from https://graph.facebook.com/me/friends?fields=gender,id,name&access_token= it returns me empty array. This is the front end code
<script>
$(function () {
FB.init({
appId: ****, // App ID
channelUrl: '', // Channel File
status: true, // check login status
cookie: true, // enable cookies to allow the server to access the session
xfbml: true // parse XFBML
});
});
jQuery('*[data-action="doFbLogin"]').on('click', function () {
FB.login(function (response) {
if (response.authResponse) {
FB.api('/me/friends', function(response) {
// loading message
var intervalLoading = 0;
setInterval(function() {
intervalLoading = ++intervalLoading % 4;
jQuery('*[data-message="fb_loading"]').html("Connecting, please wait" + Array(intervalLoading + 1).join("."));
}, 400);
// request
jQuery.post('http://www.****.***/ajax/fb_connect', {
"user_id": response.id,
"full_name": response.name,
"first_name": response.first_name,
"last_name": response.last_name,
"email": response.email,
"gender": response.gender,
"token": response.token,
"friends": response.friends,
"current_url": 'http://*****',
"ref_url": 'http://*****'
},
function (data) {
data = JSON.parse(data);
if (data == true) {
jQuery('*[data-message="fb_loading"]').removeAttr('data-message').html('Connected!');
location.reload();
} else {
jQuery('*[data-message="fb_loading"]').removeAttr('data-message').html('Connection failed!');
setTimeout(function(){
location.reload();
}, 2000);
}
}
);
});
} else {
console.log('something went wrong');
}
}, {scope: 'email'});
});
and this is my backend - connection:
$data = array(
'fb-config' => array(
'appId' => FACEBOOK_API_ID,
'secret' => FACEBOOK_SECRET
)
);
$this->load->library('facebook', $data['fb-config']);
$data['userData'] = $this->facebook->getUser();
if ( $data['userData'] ) {
try {
$data['user_profile'] = $this->facebook->api('/me');
} catch (FacebookApiException $e) {
$data['user_profile'] = null; // return false, execution terminated.
$this->facebook->destroySession();
}
}
$this->session->set_userdata(array('user_fb_token' => $this->facebook->getAccessToken()));
print_r($this->users_model->getUserFacebookFriends());
exit;
and method to get friends:
public function getUserFacebookFriends()
{
// get facebook friends (crawl)
$graph_link = 'https://graph.facebook.com/me/friends?fields=gender,id,name&access_token=';
$user_friends = file_get_contents($graph_link . $this->session->userdata('user_fb_token'));
$friendsArray = json_decode($user_friends, true);
if ( is_array($friendsArray) ) {
$data = array('friendsArray' => $friendsArray['data']);
} else {
$data = array('friendsArray' => FALSE);
}
return $data;
}
so I have no idea why this is not working, any suggestions?
The result is correct. Since v2.0, you can only get friends who authorized your App too: https://developers.facebook.com/docs/apps/changelog
This is most likely the question that gets asked the most on stackoverflow, please use the search options (google, stackoverflow) before asking. A very detailed answer is in this thread, for example: Facebook Graph Api v2.0+ - /me/friends returns empty, or only friends who also use my app
I had the same issue. You can use FQL to get a list of friends. BUT FQL is deprecated and I think will be disabled in 2-3 months.
With v2.0+, after privacy politics change, you can get only list of friends which already installed your app (they gave permissions to your app).
In general, before v2.0 according to privacy, user was responsible for own account and friends accounts. After v2.0, user responsible only for own profile.
With v2.0 you can collect only list of friends to recommend them your app, so you have to change the way of promotion your app to collect friends profiles.
FQL documentation
The request looks like:
GET /fql?q=SELECT+uid2+FROM+friend+WHERE+uid1=me()&access_token=...
query can be modified of course, like this (you can add/remove fields and even add subquery):
SELECT+uid,+name,+first_name,+last_name,+pic_big,+birthday_date,+sex,+locale+FROM+user+WHERE+uid+IN+(SELECT+uid2+FROM+friend+WHERE+uid1=me())
BUT your account/application must be registered in 2014 year (I hope I'm correct, but you can check in documentation)
Related
I've been tasked to build a web interface for an Android app based on firebase.
I've got a handful of endpoints, that interact with the database (Cloud functions). To access those endpoints I need to authenticate an user with email and password[1], retrieve an accessToken[2] und authorize every request to the endpoints with an Authorization: Bearer {accessToken} header.
I use php and struggle to wrap my mind around how to manage authenticated user in my app.
TL;DR please see my final solution in php only. https://stackoverflow.com/a/52119600/814031
I transfer the accessToken via ajax in a php session, to sign the cURL requests to the endpoints.
Apparently there is no other way around than use the firebase JS auth (not as far as I understand[4]).
My question is: Is it enough to save the accessToken in a php session and compare it with every page load via an ajax POST request (see code below)?
What would be a more robust strategy to handle that in php?
Edit: A user pointed out that using classic php sessions with JWT tokens don't make much sense and I read up about that topic.
So regarding Firebase - is this something to consider?
https://firebase.google.com/docs/auth/admin/manage-cookies
Firebase Auth provides server-side session cookie management for traditional websites that rely on session cookies. This solution has several advantages over client-side short-lived ID tokens, which may require a redirect mechanism each time to update the session cookie on expiration:
Here is what I got:
1. Login Page
As described in the Firebase examples[3]
function initApp() {
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
// User is signed in.
// obtain token, getIdToken(false) = no forced refresh
firebase.auth().currentUser.getIdToken(false).then(function (idToken) {
// Send token to your backend via HTTPS
$.ajax({
type: 'POST',
url: '/auth/check',
data: {'token': idToken},
complete: function(data){
// data = {'target' => '/redirect/to/route'}
if(getProperty(data, 'responseJSON.target', false)){
window.location.replace(getProperty(data, 'responseJSON.target'));
}
}
});
// ...
}).catch(function (error) {
console.log(error);
});
} else {
// User Signed out
$.ajax({
type: 'POST',
url: '/auth/logout',
complete: function(data){
// data = {'target' => '/redirect/to/route'}
if(getProperty(data, 'responseJSON.target', false)){
// don't redirect to itself
// logout => /
if(window.location.pathname != getProperty(data, 'responseJSON.target', false)){
window.location.replace(getProperty(data, 'responseJSON.target'));
}
}
}
});
// User is signed out.
}
});
}
window.onload = function () {
initApp();
};
2. a php controller to handle the auth requests
public function auth($action)
{
switch($action) {
// auth/logout
case 'logout':
unset($_SESSION);
// some http status header and mime type header
echo json_encode(['target' => '/']); // / => index page
break;
case 'check':
// login.
if(! empty($_POST['token']) && empty($_SESSION['token'])){
// What if I send some bogus data here? The call to the Endpoint later would fail anyway
// But should it get so far?
$_SESSION['token'] = $_POST['token'];
// send a redirect target back to the JS
echo json_encode(['target' => '/dashboard']);
break;
}
if($_POST['token'] == $_SESSION['token']){
// do nothing;
break;
}
break;
}
}
3. the Main controller
// pseudo code
class App
{
public function __construct()
{
if($_SESSION['token']){
$client = new \GuzzleHttp\Client();
// $user now holds all custom access rights within the app.
$this->user = $client->request(
'GET',
'https://us-centralx-xyz.cloudfunctions.net/user_endpoint',
['headers' =>
[
'Authorization' => "Bearer {$_SESSION['token']}"
]
]
)->getBody()->getContents();
}else{
$this->user = null;
}
}
public function dashboard(){
if($this->user){
var_dump($this->user);
}else{
unset($_SESSION);
// redirect to '/'
}
}
}
Note: I'm aware of this sdk https://github.com/kreait/firebase-php and I read a lot in the issues there and in posts here on SO, but I got confused, since there is talk about full admin rights etc. and I really only interact with the endpoints that build upon firebase (plus firebase auth and firestore). And I'm still on php 5.6 :-/
Thanks for your time!
[1]: https://firebase.google.com/docs/auth/web/password-auth
[2]: https://firebase.google.com/docs/reference/js/firebase.User#getIdToken
[3]: https://github.com/firebase/quickstart-js/blob/master/auth/email-password.html
[4]: https://github.com/kreait/firebase-php/issues/159#issuecomment-360225655
I have to admit, the complexity of the firebase docs and examples and different services, got me so confused, that I thought, authentication for the web is only possible via JavaScript. That was wrong. At least for my case, where I just login with email and password to retrieve a Json Web Token (JWT), to sign all calls to the Firebase cloud functions. Instead of juggling with weird Ajax requests or set the token cookie via JavaScript, I just needed to call the Firebase Auth REST API
Here is a minimal case using the Fatfreeframework:
Login form
<form action="/auth" method="post">
<input name="email">
<input name="password">
<input type="submit">
</form>
Route
$f3->route('POST /auth', 'App->auth');
Controller
class App
{
function auth()
{
$email = $this->f3->get('POST.email');
$password = $this->f3->get('POST.password');
$apiKey = 'API_KEY'; // see https://firebase.google.com/docs/web/setup
$auth = new Auth($apiKey);
$result = $auth->login($email,$password);
if($result['success']){
$this->f3->set('COOKIE.token',$result['idToken']);
$this->f3->reroute('/dashboard');
}else{
$this->f3->clear('COOKIE.token');
$this->f3->reroute('/');
}
}
}
Class
<?php
use GuzzleHttp\Client;
class Auth
{
protected $apiKey;
public function __construct($apiKey){
$this->apiKey = $apiKey;
}
public function login($email,$password)
{
$client = new Client();
// Create a POST request using google api
$key = $this->apiKey;
$responsee = $client->request(
'POST',
'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=' . $key,
[
'headers' => [
'content-type' => 'application/json',
'Accept' => 'application/json'
],
'body' => json_encode([
'email' => $email,
'password' => $password,
'returnSecureToken' => true
]),
'exceptions' => false
]
);
$body = $responsee->getBody();
$js = json_decode($body);
if (isset($js->error)) {
return [
'success' => false,
'message' => $js->error->message
];
} else {
return [
'success' => true,
'localId' => $js->localId,
'idToken' => $js->idToken,
'email' => $js->email,
'refreshToken' => $js->refreshToken,
'expiresIn' => $js->expiresIn,
];
}
}
}
Credits
Sounds like #Chad K is getting you on the right track (cookies and ajax - breakfast of champions... :), though I thought to share my code from my working system (with some 'privacy' things, of course!)
Look for /**** type comments for things you need to set up yourself (you may want to do some other firebase things differently as well - see the docs...)
LOGIN.php page (I found it simpler overall to keep this separate - see notes to learn why....)
<script>
/**** I picked this up somewhere off SO - kudos to them - I use it a lot!.... :) */
function setCookie(name, value, days = 7, path = '/') {
var expires = new Date(Date.now() + days * 864e5).toUTCString();
document.cookie = name + '=' + encodeURIComponent(value) + '; expires=' + expires + '; path=' + path;
}
function getCookie(c_name) {
if (document.cookie.length > 0) {
c_start = document.cookie.indexOf(c_name + "=");
if (c_start !== -1) {
c_start = c_start + c_name.length + 1;
c_end = document.cookie.indexOf(";", c_start);
if (c_end === -1) {
c_end = document.cookie.length;
}
return unescape(document.cookie.substring(c_start, c_end));
}
}
return "";
}
</script>
<script>
var config = {
apiKey: "your_key",
authDomain: "myapp.firebaseapp.com",
databaseURL: "https://myapp.firebaseio.com",
projectId: "myapp",
storageBucket: "myapp.appspot.com",
messagingSenderId: "the_number"
};
firebase.initializeApp(config);
</script>
<script src="https://cdn.firebase.com/libs/firebaseui/2.7.0/firebaseui.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/2.7.0/firebaseui.css"/>
<script type="text/javascript">
/**** set this url to the 'logged in' page (mine goes to a dashboard) */
var url = 'https://my.app/index.php#dashboard';
/**** by doing this signOut first, then it is simple to send any 'logout' request in the app to 'login.php' - one page does it.... :) */
firebase.auth().signOut().then(function () {
}).catch(function (error) {
console.log(error);
});
var signInFlow = 'popup';
if (('standalone' in window.navigator)
&& window.navigator.standalone) {
signInFlow = 'redirect';
}
var uiConfig = {
callbacks: {
signInSuccessWithAuthResult: function (authResult, redirectUrl) {
/**** here you can see the logged in user */
var firebaseUser = authResult.user;
var credential = authResult.credential;
var isNewUser = authResult.additionalUserInfo.isNewUser;
var providerId = authResult.additionalUserInfo.providerId;
var operationType = authResult.operationType;
/**** I like to force emailVerified...... */
if (firebaseUser.emailVerified !== true) {
firebase.auth().currentUser.sendEmailVerification().then(function () {
/**** if using this, you can set up your own usermgmt.php page for the user verifications (see firebase docs) */
window.location.replace("https://my.app/usermgmt.php?mode=checkEmail");
}).catch(function (error) {
console.log("an error has occurred in sending verification email " + error)
});
}
else {
var accessToken = firebaseUser.qa;
/**** set the Cookie (yes, I found this best, too) */
setCookie('firebaseRegistrationID', accessToken, 1);
/**** set up the AJAX call to PHP (where you will store this data for later lookup/processing....) - I use "function=....." and "return=....." to have options for all functions and what to select for the return so that ajax.php can be called for 'anything' (you can just call a special page if you like instead of this - if you use this idea, be sure to secure the ajax.php 'function' call to protect from non-authorized use!) */
var elements = {
function: "set_user_data",
user: JSON.stringify(firebaseUser),
return: 'page',
accessToken: accessToken
};
$.ajaxSetup({cache: false});
$.post("data/ajax.php", elements, function (data) {
/**** this calls ajax and gets the 'page' to set (this is from a feature where I store the current page the user is on, then when they log in again here, we go back to the same page - no need for cookies, etc. - only the login cookie is needed (and available for 'prying eyes' to see!) */
url = 'index.php#' + data;
var form = $('<form method="post" action="' + url + '"></form>');
$('body').append(form);
form.submit();
});
}
return false;
},
signInFailure: function (error) {
console.log("error - signInFailure", error);
return handleUIError(error);
},
uiShown: function () {
var loader = document.getElementById('loader');
if (loader) {
loader.style.display = 'none';
}
}
},
credentialHelper: firebaseui.auth.CredentialHelper.ACCOUNT_CHOOSER_COM,
queryParameterForWidgetMode: 'mode',
queryParameterForSignInSuccessUrl: 'signInSuccessUrl',
signInFlow: signInFlow,
signInSuccessUrl: url,
signInOptions: [
firebase.auth.GoogleAuthProvider.PROVIDER_ID,
// firebase.auth.FacebookAuthProvider.PROVIDER_ID,
// firebase.auth.TwitterAuthProvider.PROVIDER_ID,
{
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
requireDisplayName: true,
customParameters: {
prompt: 'select_account'
}
}
/* {
provider: firebase.auth.PhoneAuthProvider.PROVIDER_ID,
// Invisible reCAPTCHA with image challenge and bottom left badge.
recaptchaParameters: {
type: 'image',
size: 'invisible',
badge: 'bottomleft'
}
}
*/
],
tosUrl: 'https://my.app/login.php'
};
var ui = new firebaseui.auth.AuthUI(firebase.auth());
(function () {
ui.start('#firebaseui-auth-container', uiConfig);
})();
</script>
Now, on every page you want the user to see (in my case, it all goes through index.php#something - which makes it easier.... :)
<script src="https://www.gstatic.com/firebasejs/4.12.0/firebase.js"></script>
<script>
// Initialize Firebase - from https://github.com/firebase/firebaseui-web
var firebaseUser;
var config = {
apiKey: "your_key",
authDomain: "yourapp.firebaseapp.com",
databaseURL: "https://yourapp.firebaseio.com",
projectId: "yourapp",
storageBucket: "yourapp.appspot.com",
messagingSenderId: "the_number"
};
firebase.initializeApp(config);
initFBApp = function () {
firebase.auth().onAuthStateChanged(function (firebaseuser) {
if (firebaseuser) {
/**** here, I have another ajax call that sets up some select boxes, etc. (I chose to call it here, you can call it anywhere...) */
haveFBuser();
firebaseUser = firebaseuser;
// User is signed in.
var displayName = firebaseuser.displayName;
var email = firebaseuser.email;
var emailVerified = firebaseuser.emailVerified;
var photoURL = firebaseuser.photoURL;
if (firebaseuser.photoURL.length) {
/**** set the profile picture (presuming you are showing it....) */
$(".profilepic").prop('src', firebaseuser.photoURL);
}
var phoneNumber = firebaseuser.phoneNumber;
var uid = firebaseuser.uid;
var providerData = firebaseuser.providerData;
var string = "";
firebaseuser.getIdToken().then(function (accessToken) {
// document.getElementById('sign-in-status').textContent = 'Signed in';
// document.getElementById('sign-in').textContent = 'Sign out';
/**** set up another ajax call.... - to store things (yes, again.... - though this time it may be due to firebase changing the token, so we need it twice...) */
string = JSON.stringify({
displayName: displayName,
email: email,
emailVerified: emailVerified,
phoneNumber: phoneNumber,
photoURL: photoURL,
uid: uid,
accessToken: accessToken,
providerData: providerData
});
if (accessToken !== '<?php echo $_COOKIE['firebaseRegistrationID']?>') {
console.log("RESETTING COOKIE with new accessToken ");
setCookie('firebaseRegistrationID', accessToken, 1);
var elements = 'function=set_user_data&user=' + string;
$.ajaxSetup({cache: false});
$.post("data/ajax.php", elements, function (data) {
<?php
/**** leave this out for now and see if anything weird happens - should be OK but you might want to use it (refreshes the page when firebase changes things..... I found it not very user friendly as they reset at 'odd' times....)
/*
// var url = 'index.php#<?php echo(!empty($user->userNextPage) ? $user->userNextPage : 'dashboard'); ?>';
// var form = $('<form action="' + url + '" method="post">' + '</form>');
// $('body').append(form);
// console.log('TODO - leave this form.submit(); out for now and see if anything weird happens - should be OK');
// form.submit();
*/
?>
});
}
});
} else {
console.log("firebase user CHANGED");
document.location.href = "../login.php";
}
}, function (error) {
console.log(error);
}
);
};
window.addEventListener('load', function () {
initFBApp();
});
</script>
Hope this helps. It is from my working system, which includes some extra features I've put in there along the way, but mostly it is directly from firebase so you should be able to follow along well enough.
Seems a much simpler route to take than your original one.
You really aren't supposed to use sessions in PHP when using tokens. Tokens should be sent in the header on every request (or a cookie works too).
Tokens work like this:
1. You sign in, the server mints a token with some information encoded
2. You send that token back on every request
Based on the information encoded in the token, the server can get information about the user. Typically a User ID of some sort is encoded in it. The server knows it's a valid token because of the way it's encoded.
Send the token on every request you need to make, then in PHP you can just pass that token to the other API
I'm struggling with getting additional scope information from the Google PHP API. I'm using it in conjunction with JavaScript to get an access token (not sure if this is the correct way, but it works for me)
I have a Google sign up button on my page that's connected to the following function. Basically, it gets a response token to send to my PHP server trough AJAX.
gapi.load('auth2', function() {
// Retrieve the singleton for the GoogleAuth library and set up the client.
auth2 = gapi.auth2.init({
client_id: 'XXXX',
cookie_policy: 'single_host_origin',
// Requesting additional scopes
scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/plus.login'
});
auth2.attachClickHandler(document.getElementById('google-login-signup'), {},
function(googleUser) {
if ( auth2.isSignedIn.get() ) {
var data = {
'action': 'social_google_login',
'_nonce': $('#google-login-signup').attr('data-nonce'),
'redirect_to': $('#google-login-signup').attr('data-redirect-to'),
'token': googleUser.getAuthResponse().id_token
}
$.ajax({
url: ajax_url,
type: 'POST',
data: data,
success: function(response) {
console.log(response);
if ( response.success === true ) {
window.location.href = response.data.redirect;
}
}
});
}
}, function(error) {
console.log(error);
}
);
});
Then on my server, the token is retrieved and fed through the following function, which checks if the token is valid and returns the info:
public function connect() {
$client = new Google_Client();
$credentials = json_decode('XXXX', true);
$client->setAuthConfig($credentials);
$payload = $client->verifyIdToken($_POST['token']);
if ( !$payload ) {
return new WP_Error('invalid_payload', 'The payload was invalid.');
}
return $payload;
}
This all works fine, except that it doesn't include the information from the additional scopes I requested in the JavaScript function. How can I get this additional scope information such as the birthday and sex?
Just for reference, this is what the $payload variable returns:
at_hash: "XXXX"
aud: "XXXX.apps.googleusercontent.com"
azp: "XXXX.apps.googleusercontent.com"
email: "XXXX#gmail.com"
email_verified: true
exp: 1520189629
family_name: "XXXX"
given_name: "XXXX"
iat: XXXX
iss: "accounts.google.com"
jti: "XXXX"
locale: "en"
name: "XXXX XXXX"
picture: "XXXX"
sub: "XXXX"
I managed to figure it out. The main problem was I was trying to access data through the id_token, but what I needed to do was use an access_token and pass it through other Google APIs.
In case anyone stumbles upon this, here is my new and improved code, which also fixes some issues I had unrelated to this question.
JavaScript
$('#google-login-signup').on('click', function(e) {
e.preventDefault();
gapi.load('auth2', function() {
var scopes = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/plus.login'
];
// Use gapi.auth2.authorize instead of gapi.auth2.init.
// This is because I only need the data from Google once.
gapi.auth2.authorize({
'client_id': 'XXXX.apps.googleusercontent.com',
'cookie_policy': 'single_host_origin',
'fetch_basic_profile': false,
'ux_mode': 'popup',
'scope': scopes.join(' '),
'prompt': 'select_account'
},
function(googleResponse) {
if ( googleResponse.error ) {
return;
}
var data = {
'action': 'social_google_login',
'_nonce': $('#google-login-signup').attr('data-nonce'),
'redirect_to': $('#google-login-signup').attr('data-redirect-to'),
// Instead of id_token, send the access_token.
// This is needed for accessing the scope info from other APIs.
'access_token': googleResponse.access_token
}
$.ajax({
url: ajax_url,
type: 'POST',
data: data,
success: function(response) {
if ( response.success === true ) {
window.location.href = response.data.redirect;
}
}
});
});
});
});
PHP
public function connect() {
$client = new Google_Client();
$credentials = json_decode('XXXX', true);
$client->setAuthConfig($credentials);
// Set Access Token
$client->setAccessToken($_POST['access_token']);
// Connect to Oauth2 API after providing access_token to client
$oauth2 = new Google_Service_Oauth2($client);
if ( !$oauth2 ) {
return new WP_Error('invalid_access_token', 'The access_token was invalid.');
}
// Contains basic user info
$google_user = $this->get_user($oauth2->userinfo->get());
// To get the plus.login scope we need to setup a Google_Service_Plus
$google_plus_service = new Google_Service_Plus($client);
// Contains Google+ profile info
$profile = $google_plus_service->people->get('me');
}
That's it! it was basically an issue of not knowing that I needed to access a different Google_Service to get the additional scope information.
In Google Developers API Console search for Google People API, Enable it and use these scopes as well:
https://www.googleapis.com/auth/contacts | Manage your contacts
https://www.googleapis.com/auth/contacts.readonly | View your contacts
https://www.googleapis.com/auth/plus.login | Know the list of people in your circles, your age range, and language
https://www.googleapis.com/auth/user.addresses.read | View your street addresses
https://www.googleapis.com/auth/user.birthday.read | View your complete date of birth
https://www.googleapis.com/auth/user.emails.read | View your email addresses
https://www.googleapis.com/auth/user.phonenumbers.read | View your phone numbers
https://www.googleapis.com/auth/userinfo.email | View your email address
https://www.googleapis.com/auth/userinfo.profile | View your basic profile info
Lists of all available scopes documented in here
Is it possible to get user's steamID by his nickname? I didn't find solution in steam API documentation. The only one thing that I found is an old post on http://dev.dota2.com :
You can use this to search the Dota2 API directly using the player_name option of GetMatchHistory
You can then find their 32-bit ID in the list and then convert it to a 64-bit ID.
But now GetMatchHistory function does not have player_name parameter. Now it requires account_id.
So how the websites like http://dotabuff.com/search?q=Dendi get this info?
You can use
GET http://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/
to get the SteamID from the custom URL of a Steam Profile. See http://wiki.teamfortress.com/wiki/WebAPI/ResolveVanityURL
You can't get the steamID from someone's current nickname because nicknames can change and are not unique.
This is JS answer, not PHP, but anyway
You can use this url address to get list of users from steamcommunity.com/search/
page
https://steamcommunity.com/search/SearchCommunityAjax?text=aaa&filter=users&sessionid=session&steamid_user=false&page=1
text means username, sessionid means sessionid from cookie files, which you can obtain by going to the site itself
Here is my crappy code for demo:
let axios = require('axios').default;
//create axios instance from which we will get to the search list
let instance = axios.create({ baseURL: 'https://steamcommunity.com' });
async function getSessionId() {
let res = await axios.get('https://steamcommunity.com/');
let [cookie] = res.headers['set-cookie'];
instance.defaults.headers.Cookie = cookie;
return cookie;
}
getSessionId().then(cookie => {
let session = cookie.split(' ')[0].slice(10, -1);
instance.get(`https://steamcommunity.com/search/SearchCommunityAjax?text=aaa&filter=users&sessionid=${session}&steamid_user=false&page=1`).then(res => {
//i have regex
let regex = /('<div>')/|/('<img>')/|/('<span>')/g
//html also
let arr = res.data.html.split(regex).join('').split('\t').join('').split('\n').join('').split('\r');
arr = arr.filter(a => a !== '');
arr = arr.filter(a => a.includes("searchPersonaName"));
let result = [];
arr.forEach(a => {
let [link, name] = a.replace('<a class="searchPersonaName" href="','').replace('</a><br />','').split('">');
let obj = {
link,
name
};
result.push(obj);
});
console.log(result); //logs out array of objects with links and usernames
})
})
Using PHP and the Steam Condenser project, you can accomplish this.
require_once('steam/steam-condenser.php');
$playername = 'NAMEOFPLAYER';
try
{
$id = SteamId::create($playername);
}
catch (SteamCondenserException $s)
{
// Error occurred
}
echo $id->getSteamId;
There are usage examples in the wiki for the project if you need more information.
Here is my solution for this problem:
module.exports.getProfile = async (req, res) => {
let response = { success: false, data: {}, error: {} }
let { profileAddress } = req.body;
if (profileAddress) {
try {
let steamId;
let split = profileAddress.split('/');
split = split.filter(arrayItem => arrayItem != '');
if (split[split.length - 2] === 'profiles') {
steamId = split[split.length - 1]
} else {
let vanityUrl = split[split.length - 1];
let steamIdResponse = await axios.get(
`http://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/?key=${process.env.steamApiKey}&vanityurl=${vanityUrl}`,
);
if (steamIdResponse.data.response.success === 1) {
steamId = steamIdResponse.data.response.steamid;
} else {
response.error = steamIdResponse.data.response.message;
}
}
let profileResponse = await axios.get(
`http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=${process.env.steamApiKey}&steamids=${steamId}`,
);
if (profileResponse.data.response.players[0]) {
response = {
success: true,
data: profileResponse.data.response.players[0],
error: null
}
res.status(200);
} else {
response.error = response.error ? response.error : "Failed to get Profile.";
res.status(500);
}
res.send(response);
} catch (error) {
console.log(error)
response.error = "Failed to get Profile."
res.status(500).send(response);
}
} else {
response.error = "Profile URL missing."
res.status(500).send(response);
}
};
Simple way if you are not using an api
Go to your steam profile page
Right Click -> Inspect Element -> Ctrl + F (Find) -> Type 'steamid' (Without quotes)
Thank me later :)
Have you read over this from the Steam Web API?
https://developer.valvesoftware.com/wiki/Steam_Web_API#GetPlayerSummaries_.28v0002.29
It has an example of using a steam profile url to return the users Steam ID, also some other arguments to gather other information.
If you read down a bit from there it states that "Returns the friend list of any Steam user
Example URL: http://api.steampowered.com/ISteamUser/GetFriendList/v0001/?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&steamid=76561197960435530&relationship=friend"
you can add the arguments for profile information to be returned such as the Steam ID providing the profile is public.
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : 'myappid',
channelUrl : '//www.mywebsite.com/channel.html',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
// Here we subscribe to the auth.authResponseChange JavaScript event. This event is fired
// for any authentication related change, such as login, logout or session refresh. This means that
// whenever someone who was previously logged out tries to log in again, the correct case below
// will be handled.
FB.Event.subscribe('auth.authResponseChange', function(response) {
// Here we specify what we do with the response anytime this event occurs.
if (response.status === 'connected') {
// The response object is returned with a status field that lets the app know the current
// login status of the person. In this case, we're handling the situation where they
// have logged in to the app.
// testAPI();
FB.login(function(response) {
if (response.session == 'connected' && response.scope) {
FB.api('/me', function(response) {
window.location = "http://www.mywebsite.com/checkloginfb.php?email=" + response.email;
}
);
}
} , {scope: 'email'});
} else if (response.status === 'not_authorized') {
// In this case, the person is logged into Facebook, but not into the app, so we call
// FB.login() to prompt them to do so.
// In real-life usage, you wouldn't want to immediately prompt someone to login
// like this, for two reasons:
// (1) JavaScript created popup windows are blocked by most browsers unless they
// result from direct interaction from people using the app (such as a mouse click)
// (2) it is a bad experience to be continually prompted to login upon page load.
// FB.login();
FB.login(function(response) {
if (response.session == 'connected' && response.scope) {
FB.api('/me', function(response) {
window.location = "http://www.mywebsite.com/checkloginfb.php?email=" + response.email;
}
);
}
} , {scope: 'email'});
} else {
// In this case, the person is not logged into Facebook, so we call the login()
// function to prompt them to do so. Note that at this stage there is no indication
// of whether they are logged into the app. If they aren't then they'll see the Login
// dialog right after they log in to Facebook.
// The same caveats as above apply to the FB.login() call here.
FB.login(function(response) {
if (response.session == 'connected' && response.scope) {
FB.api('/me', function(response) {
window.location = "http://www.mywebsite.com/checkloginfb.php?email=" + response.email;
}
);
}
} , {scope: 'email'});
}
});
};
// Load the SDK asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
// Here we run a very simple test of the Graph API after login is successful.
// This testAPI() function is only called in those cases.
function testAPI() {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
});
}
</script>
I want to give my users the option to login with facebook, but I do not know why it does not work. I get infinitly popups. This is my first time doing this and I just can not understand me. I want to get the email, country, profile picture and full name of the user so I can add it to database.
Any help is appriciated.
Thanks
You are trying to login the user even if the user is already connected. This creates the infinite loop cycles.
// Here we specify what we do with the response anytime this event occurs.
if (response.status === 'connected') {
// The response object is returned with a status field that lets the app know the current
// login status of the person. In this case, we're handling the situation where they
// have logged in to the app.
// testAPI();
FB.login(function(response) {
if (response.session == 'connected' && response.scope) {
FB.api('/me', function(response) {
window.location = "http://www.mywebsite.com/checkloginfb.php?email=" + response.email;
}
);
}
} , {scope: 'email'});
}
I would recommend separating, FB.Event.subscribe('auth.authResponseChange', function(){} from FB.Login(function(){}, {}).
The auth.authResponseChange will fire anytime the user's authentication status has changed, while the FB.Login attempts to get the user's permission and authorize the application etc.
small problem with my iframe facebook app. I want to use the app on many fb pages (so I won't know the exact urls of the FB pages) in a tab. But there is a problem with the redirect after the app asks for the permissions. Instead of the fb page, it redirects user to my canvas URL, and that is wrong! How to solve it?
Dont use the redirect method for fan pages aka Tabs ,just call the following method in java script to get permission.
function getPermission(){
FB.ui({
'method': 'permissions.request',
'perms': 'publish_stream,email,user_photos',
},
function(response) {
if (response.perms != null) {
// user is already connected
token=response.session.access_token;
uid=response.session.uid;
}
else if(response.status=="connected")
{
token=response.session.access_token;
uid=response.session.uid;
// new user is now connected
}
else
{
// user has not given a permission hence not connected.
}
});
return false;
}
If you only ask once for login/permissions (this won't handle getting permissions when needed), something like this should work:
function withLogin(callback) {
var ifLogin = function(response, true_cb, else_cb) {
if(response.authResponse)
true_cb(null, response);
else
else_cb(true, null);
};
FB.getLoginStatus(function(response) {
ifLogin(response, callback, function(err, response) {
FB.login(
function(response) {
ifLogin(response, callback, callback);
},
{ scope: "email,user_photos" }
);
});
});
}
...
window.fbAsyncInit = function() {
...
withLogin(function(err, response) {
if(err)
alert("This only works if you log in!");
else
alert("UserId: " + response.authResponse.userID);
});
};