I'm using the JS library https://apis.google.com/js/platform.js to log in my user to pass a token to my backend:
gapi.auth2.getAuthInstance().signIn().then(() => {
var user = gapi.auth2.getAuthInstance().currentUser.get();
var authResp = user.getAuthResponse();
var bodyFormData = new FormData();
bodyFormData.append('google_token', authResp.access_token);
When I receive the access token on my server I try use the php client library to generate the rest of the client:
$google = new google();
$google->setAuthConfig('client_secrets.json');
$google->setAccessType('offline');
$google->createAuthUrl();
$google->getRefreshToken();
$google->setAccessToken($thePOSTedAccessToken);
$service = new Google_Service_MyBusiness($google);
The issue is no matter what I do I cannot get my refresh token from client.auth after I create the $client->createAuthUrl(); . So this either means I'm not doing the client properly in php or something else is wrong. I'm asking this question because I've followed all documentation and looked extensively why I'm not receiving my refresh.
You can't mix things like this. If the authorization code was created using JavaScript you will not be able to get a refresh token as JavaScript does not support refresh tokens.
If you want a refresh token then you will need to authorize the user using a server-side language and not a client-side language.
When you you run the code the first time, the user will be displayed with a consent screen. If they consent to your access then you get a code returned. This is an authorization code.
In the example below you can see how the authorization code is exchanged for an access token and refresh token.
Only after $client->authenticate($_GET['code']); is called will $client->getAccessToken(); and $client->getRefreshToken(); work.
Also once the code has been run once, if you try to authorize the user again you will not get a new refresh token, Google assumes that you saved the refresh token they already sent you. If you didn't save it, you would then need to revoke the user's access either using the revoke command in the library or by going to the user's Google account and revoking the application that way.
Sorry, all I have on hand is a web version; not sure if you're running this command-line or web-based.
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to session.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
I have a chrome extension that only runs on Facebook and I am trying to send data that the extension gathers to a MySQL database that I have on my GoDaddy website server. I keep getting the error message "Failed to load resource: the server responded with a status of 500 (Internal Server Error)". I wasn't sure what the issue is since I'm just getting into web development.
Here is my code for the content script on my chrome extension:
var dummyUrl = new URL ("http://www.bbc.com/news/world-us-canada-41081629");
console.log("dummyUrl: " + dummyUrl);
//Create XMLHttpRequest Object
var xhttp = new XMLHttpRequest();
//Send request
xhttp.open("POST", "https://pocketchange.social/data.php", true);
xhttp.send(dummyUrl);
And here is my PHP file on my webserver that is running a query to send the data to my database:
<?php
$mysqli = new mysqli("localhost", "Jarid", "Database", "myURL");
//Check connection
if(mysqli === false) {
die("ERROR: Could not connect" . $mysqli->connect_error;
}
//Print host information
echo "Connection successful. Host info: " . $mysqli->host_info;
//Escape user inputs
$url = $mysqli->real_escape_string($_REQUEST['url']);
$description = $mysqli->real_escape_string($_REQUEST['description']);
$keywords = $mysqli->real_escape_string($_REQUEST['keywords']);
$content = $mysqli->real_escape_string($_REQUEST['content']);
$language = $mysqli->real_escape_string($_REQUEST['language']);
//Execute query
$query = "INSERT INTO url_data (url, description, keywords, content, language) VALUES ('$url', '$description', '$keywords', '$content', '$language')";
//Checking to see if values were inserted properly
if($mysqli->query($query) === true) {
echo "Data successfully inserted.";
}
else {
echo "ERROR could not execute query" . $mysqli->error;
}
$mysqli->close();
?>
Is my issue mainly that I'm trying to send data to a completely different server? I'm not super clear on how all of these pieces communicate with each other (ie how does the chrome extension know how to connect to the GoDaddy server, and how exactly is the php file sending data to the database, etc.)
Thanks in advance.
Regarding the "500 (Internal Server Error)", this highlighted SO post could give you some idea.
The 500 code would normally indicate an error on the server, not
anything with your code. Some thoughts
Talk to the server developer for more info. You can't get more info directly.
Verify your arguments into the call (values). Look for anything you might think could cause a problem for the server process. The process
should not die and should return you a better code, but bugs happen
there also.
Could be intermittent, like if the server database goes down. May be worth trying at another time
You can check the post for some possible answer as well.
Hope this helps.
I trying to send data to socket.io server from controller. In this part of code:
else {
$user = User::find(Auth::user()->id);
$user->decrement('points', $game->price);
$game->owner_team == 1? $team = 2 : $team = 1;
$game->update(['join_user_id'=> Auth::user()->id, 'join_team' => $team, 'status' =>1]);
// here send info about new player to socket.io server
return redirect('/user/game/'.$request->game_id);
}
I need to notify the server, to refresh the page for others user, when this part of code was executed. I need to know how send info from controller.
Is it possible to send optinal parameters to my twilio twiml file and use them in a php script? Its because im using a generated userid in my phonegap app. If the call is connected i want to send the user id to twiml and check in the php if the call was "completed" and set then values in a mysql db for the userid.
Somethinglike:
Twiml:
<Response>
<Dial action="http://blabla.com/dial.php" method="POST">
555-5555
</Dial>
</Response>
JavaScript:
$("#dialButton").click(function() {
params = { "userid" : $(userid).val()};
connection = Twilio.Device.connect(params);
});
Php:
$user = $_POST["userid"];
Is this the right way?If not how can i solve the problemt?
Here are the attributes that will be sent to the action URL:
https://www.twilio.com/docs/api/twiml/dial#attributes-action-parameters
It looks like it doesn't contain the userID (I assume you mean accountSID or subaccountSID?).
According to this article (https://www.twilio.com/blog/2011/05/how-to-track-and-report-your-twilio-usage.html) you may want to use the StatusCallback paramater when making a call, I don't know how that plays with what's going on with your phonegap application, I'm not familiar with that technology.
https://www.twilio.com/docs/api/rest/making-calls#post-parameters-optional
I hope this helps or at least gets you in the direction you need to go.
I need to set an Authorization header to an HTML5 EventSource. As Server Sent Events seems to be disused since Websockets appeared, I cannot find any useful documentation. The approach I have already found is to pass the authorization data within the url... but I don't like this method.
I am using AngularJS and set interceptors on $httpProvider, but the EventSource is not intercepted by AngularJS, so I cannot add any header.
I realize your post was over a year ago, but I found myself in the same boat with now good answers. I'm hoping this may help someone, or at least give them some ideas...
Cookies seem easy enough, but what happens if someone is blocking cookies? I would have to prompt them to enable cookies to use the site. At that point they start to wonder if they can trust the site since they disabled cookies for 'security reasons'. All the while, I want cookies enabled for security reasons!
Using AJAX, one can easily POST authentication data over SSL, but that's just not possible with SSE. I've seen many posts where people then say, "just use the querystring", but I don't want to compromise a customer's security by sending the auth data in plain text (example.com/stream?sessionID=idvalue) which someone could snoop.
After racking my brain for a couple hours I realized that I CAN accomplish the the overall goal without compromising the customer's auth data. Just to clarify, I haven't discovered some way to POST when establishing an EventSource connection, but it does allow the browser to securely pass an authentication token with the EventSource each time it reconnects. They key is to get the desired sessionID/token into the lastEventID.
The user can authenticate as usual with a username/password (or by AJAX POSTing a token you keep in localstorage). The AJAX auth process will pass back a JSON object with a short-lived-token (expires in 60 seconds, or when used) which would be saved in your desired backend (eg: mySQL) along with a longer-lasting token. At this point you initiate your SSE connection like:
qString = "?slt=" + "value-that-expires-within-seconds";
streamURL = "http://example.com/stream.php";
var streamSource = new EventSource(streamURL + qString);
streamSource.addEventListener('auth',function(e) {
var authStatus = JSON.parse(e.data);
if (authStatus.session !== 'valid') {
qString = "";
streamSource.close();
}
})
In the corresponding PHP you would do something like this:
header("Content-Type: text/event-stream\n");
ob_end_flush();
ob_start();
if (isThisShortLivedTokenValid($_GET["slt"])) {
// The short-lived-token is still valid... so we will lookup
// the value of the corresponding longer-lasting token and
// IMMEDIATELY invalidate the short-lived-token in the db.
sendMsg($realToken,'auth','session','valid');
exit;
} else if (isThisRealTokenValid($_SERVER["HTTP_LAST_EVENT_ID"])){
while (1) {
// normal code goes here
// if ($someCondition == 'newDataAvailable') sendMsg($realToken,'chat','msg-id','msg-content');
}
} else {
http_response_code(404); // stop the browser from reconnecting.
exit; //quit the PHP script and don't send anything.
}
function sendMsg($id, $event, $key, $val) {
echo "{" . PHP_EOL;
echo "event: " . $event . PHP_EOL;
echo "id: $id" . PHP_EOL;
echo 'data: {"' . $key . '" : "' . $val . '"}' . PHP_EOL;
echo "}" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
function isThisShortLivedTokenValid($sltValue) {
//stuff to connect to DB and determine if the
//value is still valid for authentication
return $dbResult == $sltValue ? TRUE : FALSE;
}
SSE connects with the short-lived-token, PHP validates against the short-lived-token and deletes it from the DB so it will never be able to AUTH again. This is somewhat similar when you get texted a 6-digit code to login to online banking. We use PHP to push the REAL token (that expires much later) which we retrieved from the database as the event ID. It's not really necessary for Javascript to do anything with this event-- the server will end the connection automatically, but you can listen to the event if you want to do more with it.
At this point, the SSE connection has ended since PHP finished the script. However, the browser will automatically reestablish the connection (usually with 3 seconds). This time, it will send the lastEventId... which we set to the token value before we dropped the connection. On the next connection, this value will be used as our token and the app will run as expected. It's not really necessary to drop the connection as long as you start using the real token as the event-ID when you send messages/events. This token value is transmitted completely encrypted over SSL both when the browser receives it, and in every subsequent connection to the server. The value that was transmitted 'in the clear' was expired within seconds from when we receive & used it and it can no longer be used by anyone that discovers it. If someone does attempt to use it they will receive a 404 RESPONSE.
If you already use the event-stream ID for some other purpose, this may not work 'out of the box' unless you concatenate the auth-token and the previously used value, and split it into variables so it's transparent to the rest of the app. Something like:
// when sending data, send both values
$sseID = $token_value . "_" . $previouslyUsedID;
sendMsg($sseID,'chat','msg-id','msg-content');
// when a new connection is established, break apart the values
$manyIDs = explode("_", $_SERVER["HTTP_LAST_EVENT_ID"])
$token_value = $manyIDs[0]
$previouslyUsedID = $manyIDs[1]
EventSource doesn't have an API for sending HTTP headers to server. I was struggling with this problem too when I was building realtime-chat using SSE.
However I think cookies will be sent automatically if your SSE server is the same server as your authentication server.
This polyfill adds Authorization Header support: https://github.com/Yaffle/EventSource/
So you can do:
new EventSource("https://domain/stream", { authorizationHeader: "Bearer ..." });
The window.EventSource doesn't seem to support passing additional headers yet. Good news is there are some other popular implementations of EventSource that support additional headers. Some of them are as follows:
eventsource
event-source-polyfill
const eventSource = new EventSource(resoureUrl, {
headers: {
'Authorization': 'Bearer ' + authorizationToken
}
});
eventSource.onmessage = result => {
const data = JSON.parse(result.data);
console.log('Data: ', data);
};
eventSource.onerror = err => {
console.log('EventSource error: ', err);
};
If you use this fork of the event-source polyfill you will be able to add authorization headers similarly to the way rafaelzlisboa describes:
https://github.com/AlexGalays/EventSource#923b9a0998fcfd7753040e09aa83764b3cc0230d
Ï don't know if you can provide the authentication header as a second argument like in rafaelzlisboa's example, I got it to work by creating a headers object, and putting my authorization header in there, like this:
new EventSource("https://domain/stream", { headers: { Authorization: Bearer.... }});
the other way to pass auth token is through the URL as query param, but you should take security in consideration. Also add support of authorization through query param on the sever side.
I solved this by additional rest before sse call, this rest is ordinary rest will require the same security protocol that we need for SSE call and get and OTP in response.
And send this OTP to see call query param and validate this OTP in Web filter and replace it with authentication header.
I went through quite a few posts in an attempt to figuring out if the auth token be sent in the EventSource() call. Although there are polyfill alternatives that allow adding headers : https://github.com/whatwg/html/issues/2177
while others mentioned sending auth token over ssl.
Instead of using polyfill EventSource() or sending the auth token in the query params over ssl, send a eventSource identifier (eventSrcUUID) in the params of EventSource url over ssl as follows :-
On user authentication, eventSrcUUID is generated along with the sseEmitter on the server and place in a sseEmitterMap.
Client retrieves the eventSrcUUID from the response and invokes the EventSource() call with the eventSrcUUID in the param. On the server, the sseEmitterMap is referenced to retrieve the the eventSrc object. The sseEmitter object saved in session data is used to send event notifications to client.