internal server error on XMLHttpRequest - javascript

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.

Related

Returning back refresh token for google Oauth 2 using php client

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));
}
?>

How to connect Server Sents Events (SSE) to a PHP MVC Controller

So I currently have a working SSE system, which sends out notifications to clients. For the EventSource I specify a direct script on the server notifs.php.
Simplified this looks like following:
client.js
$(window).on('pageshow',function(){
// Server Sent Events here
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("notifs.php");
source.onmessage = function(event) { ... };
}
});
And PHP side looks something like this:
notifs.php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
echo 'data: {"Foo": "Bar}'.PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
Now this works well, but I'd like to structure my whole project under the MVC design pattern, so instead of connecting the EventSource to "notifs.php" I'd like to have something like "/notification/notifs/", where notification is a Controller and notifs it's action.
Firefox tells me that it cannot create a connection to localhost/notification/notifs/. I would assume that this happens, because this is no real address on the server. While normal HTTP-requests go through a routing engine, this does not.
I wasn't able to find any information about this. Is it even possible to include the SSE endpoint in an object-oriented class?
Or do they always have to be in their own files?

HTTP Authorization Header in EventSource (Server Sent Events)

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.

chrome app TcpServer and php client

I'm use example from Google Team to create a TCP Server using Chrome App Extension API. Sample is work correctly and I connect via telnet and send commands.
When I'm trying to connect to this server from client and try send data. Client connected to server and send data, but server not receive data. Client on PHP, for test I'm using this example.
What I doing wrong?:(
Thx.
Solve: I'm resolve problem. In php script, after connect need delay. I'm using usleep function. All worked
Worked Example:
$fp = pfsockopen("ip", port, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "minimize";
usleep(125000);
$r = fputs($fp, $out);
sleep(1); //
$out = "restore";
$r = fputs($fp, $out);
usleep(125000);
fclose($fp);
}

$_SESSION variable empty when accessing from AJAX on different port [duplicate]

This question already has answers here:
jQuery Ajax on Different Port
(6 answers)
Closed 8 years ago.
I have created a site which has a PHP side to it this runs on port 80 (index.php), when I login it sets the session variable with the userid.
I then click a link which takes me to port 8080, this is a JavaScript file which carries out node.js processes (live.html).
From this node.js client file (live.html) I request the userid from a file called getUserSession.php which echos out the userId from the session.
When I run the AJAX request (live.html), it returns that the session userid is empty however if I manually insert the URL to the web browser it echos the user session (http://localhost:8080/getUserSession.php).
I have dumped the array into the response and it tells me that the $_SESSION variable is empty.
I also attempted to returned a plain text string test - this returns with no problem, so it seems to be an issue with accessing the session variable from a different port, and not the actual AJAX call itself.
UPDATE:
This is how I eventually resolved the problem.
I added this to the index.html file:
$.getJSON("`http://localhost:80/getUserSession.php?callback=?`", { username: "lazy"}, function(json){
username = json.message;
});
And added the following to the php file:
<?php
session_start();//start the session
$user2 = (string)$_SESSION['username'];
$callback = $_GET["callback"];
$user = $_GET["username"];
if($user == "lazy") {
$response = array("message" => $user2);
} else {
$response = array("message" => $user2);
}
echo $callback . "(". json_encode($response) . ");";
Still needs tidied up but it works. Thanks for the help
When you make the request to php from the browser, a session is created linked to the browser. When you make the request to php using node.js, a new session is created between php and that node.js request because node.js is not the same client as the web browser.
One workaround would be to pass the session token information to node.js so that node.js can request the php file as the same client, however i'm not sure if that's something you can do with php out-of-the-box. With coldfusion it's as simple as passing the cftoken and cfid if you're using the default settings for session management.

Categories

Resources