I'm sending request from wordpress server to another server API to get data.
I have a cookie contains session_id as:
{ [0]=> object(WP_Http_Cookie)#501 (7) { ["name"]=> string(10) "session_id" ["value"]=> string(40) "b439e58064**********************" ["expires"]=> int(1679384140) ["path"]=> string(1) "/" ["domain"]=> string(20) "sub.domain.vn" ["port"]=> NULL ["host_only"]=> bool(true) }
when i pass this cookie to function wp_remote_request, im authorized and get data from the API. When i pass cookie to function Requests::request_multiple and var_dump($responses), i get 'Unauthorized' but session_id cookie attached to the request.
Please help me explain the differences of Cookie in wp_remote_request and Requests::request_multiple to solve this.
Related
I am using REST API in my app to communicate with a Firebase RTDB, and trying to use a Google Access Token to authenticate my requests.
My issue is that with even the most permissive Rules on the database, I get HTTP error 401 in response to queries that try to authenticate.
For example, say I try to put some data in my database with the following command, I get 401 in return (all the values within < > are placeholders):
curl -XPUT -d '{ "UserID" : "<GOOGLE_UID>", "UserName" : "Clicksurfer", "CompletionMoves" : 8, "CompletionTime" : 16.21979 }' https://<FIREBASE_URL>.firebaseio.com/Level2/<GOOGLE_UID>.json/?access_token=<GOOGLE_ACCESS_TOKEN>
401
The strangest part is, when I abandon the use of access token altogether the query works:
curl -XPUT -d '{ "UserID" : "<GOOGLE_UID>", "UserName" : "Clicksurfer", "CompletionMoves" : 8, "CompletionTime" : 16.21979 }' https://<FIREBASE_URL>.firebaseio.com/Level2/<GOOGLE_UID>.json
200
As I said, I am currently using the most permissive rules for debugging:
{
"rules": {
".read": true,
".write": true
}
}
Any idea what might be causing this? Thanks in advance
EDIT:
I use the Google Play Games plugin for Unity in my project, among other things to get the AuthCode.
In order to do this, I needed to do a couple of things:
When building the config for Google Play Games during startup, I made sure to call the RequestServerAuthCode(false) method
Have the user login after Google Play Games sets up
Make sure that the relevant ClientID was supplied to Unity (in this case, it is a web client that has auth permissions on my Firebase rtdb).
This all looks like this:
public class GPGSAuthentication : MonoBehaviour
{
public static PlayGamesPlatform platform;
void Start()
{
if (platform == null)
{
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().RequestServerAuthCode(false).Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.DebugLogEnabled = true;
platform = PlayGamesPlatform.Activate();
}
Social.Active.localUser.Authenticate(success =>
{
if (success)
{
Debug.Log("GSPS - Logged in successfully");
}
else
{
Debug.Log("GSPS - Falied to login");
}
});
}
}
Now that we've done this, we can call PlayGamesPlatform.Instance.GetServerAuthCode() in order to get the AuthCode.
I traded in my AuthCode for an Access Token by sending a POST request to https://www.googleapis.com/oauth2/v4/token. In my query, I supply 4 fields:
client_id, which has the ID of the previously used client (where we got the AuthCode from).
client_secret, which has the correlating secret.
grant_type, which is always with the value "authorization_code"
code, which has the value of the AuthCode we got.
In response, I get a 200 response with 4 parameters:
access_token, the token I (fail to) use when authenticating against my Firebase rtdb.
token_type, the type of the aforementioned token.
expires_in, the amount of time before the token expires (I presume in seconds unit)
refresh_token, a token which can be used in order to get a new access_token without having to keep the Google user connected.
I then supply this access_token value to the queries I send to my DB, and promptly get the 401 error.
//body its like this
{
"to":
"/topics/NEWS"
,
"data":{
"extra_information": "This is some extra information"
},
//notification that i need to give
"notification":{
"title": "ChitChat Group",
"text": "You may have new messages",
"click_action":"ChatActivity"
}
}
The 401 error pertains that your Authorization Key is invalid or incorrect.
When using Postman, add a key= prefix for the value of Authorization, like so:
key=AAA...
See below for a tutorial on Sending Downstream FCM Messages using Postman.
Also, for your notification message payload, text isn't one of the valid parameters, I think you were looking for message instead.
Sending Downstream Messages using Postman
To do this in Postman, you simply have to set the following:
Set request type to POST
In the Headers, set the following:
Content-Type = application/json
Authorization = < Your FCM Server Key > (See your Firebase Console's Cloud Messaging Tab)
Set the payload parameters in the Body (*in this example, we used the raw option, see screenshot (2)*)
Send the request to https://fcm.googleapis.com/fcm/send
Screenshots:
(1)
Note: Always keep your Server Key a secret. Only a portion of my key is visible here so it should be fine.
(2)
(3)
Notice that the request was a success with the message_id in the response.
Wrong:
Authorization:AIzaSyDDk77PRpvfhh......
Correct:
Authorization:key=AIzaSyDDk77PRpvfhh......
Full example:
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{ "data": {
"score": "5x1",
"time": "15:10"
},
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}
While the answers above are still correct, you may choose to use HTTP v1. This requires Bearer instead of key= and uses an Oauth2 access token instead of a server key string. To view HTTP v1 specifications, please refer to the link below:
https://firebase.google.com/docs/cloud-messaging/migrate-v1
I was also getting same error in PHP , solved with below header :
$header = array("authorization: key=" . $this->apiKey . "","content-type: application/json");
Executing Angular2 http call to the offline server doesn't provide much info in it's "error response" object I'm getting in the Observable's .catch(error) operator or subscription error delegate (they are both share the same info actually). But as you can see on the screen shot of the console there's actual error was displayed by zone.js somehow.
So, how can I get this specific error info (net::ERR_CONNECTION_REFUSED)?
Thanks.
Whenever server do not respond, response.status will be always equal to 0 (zero)
{
type: 3, //ResponseType.Error
status: 0, // problem connecting endpoint
}
Also note, when you are performing CORS request, but origin (url in browser) is not authorized (not in allowed list of host names configured in remote endpoint) the response would be similar to above, with exception to type attribute which will be equal to 4 = ResponseType.Opaque...
This means, connection was made, but for instance, OPTIONS request returned with headers which do not contain origin or HTTPS request was performed from HTTP origin.
You can handle the error messages so they are easier to read. This can definitely be expanded on too:
public Get() {
return this.http.get(this.URL).map(this.extractData)
.catch(this.handleError);
}
public extractData(res: Response) {
let body = res.json();
return body || {};
}
public handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
Check out this part of the docs on error handling.
Without digging in the code, my expectation is that if the server is unreachable, then no response can be returned from the server. Therefore the Response object remains its initialized state.
I would like to use Guzzle to create request.
My settings looks like this:
$request = $client->createRequest('GET', 'https://api.parse.com/1/classes/class');
$request->setHeader('Content-Type', 'application/json');
$request->setHeader('X-Parse-Application-Id', 'id');
$request->setHeader('X-Parse-REST-API-Key', 'key');
$response = $client->send($request);
And always, I get
Client error response
[status code] 401
[reason phrase] Unauthorized
[url] https://api.parse.com/1/classes/class
I'm sure I have correct ID and KEY. Also, there is no API call in debug toolbar.
when i access the url it prompts me with basic auth
so i think you have to do sth like
$request->setAuth($user, $pass);
before sending
Here's the situation: the user is able to sign into a MVC application from another website. That website is not ASP.NET-based. It could be PHP, JSP or Websphere... or anything
I have tried doing this:
[HttpPost]
public string RemoteLogOn(string userName, string password)
{
if (userName != null && password != null)
{
if (MembershipService.ValidateUser(userName, password))
{
FormsAuthentication.SetAuthCookie(userName, false);
return "success";
}
else
{
return "failed";
}
}
else
{
return "failed";
}
}
Calling the MVC app at the /RemoteLogOn URI (posting the request using PHP and cURL) works. The "success" string is returned. However, it seems that the cookie is not generated properly - when I returned to the MVC site and check User. Identity.Name, null is returned.
What is the right way to allow user to log in via. a web service?
Edit How do I properly set the returned cookie.
PS. This is just a trial POC; eventually we'll use SOAP or REST and try to improve the security.
Here's the PHP code that did the calling
<?php
$url = "http://localhost:54134/Account/RemoteLogOn";
$fields = array(
"userName" => "asd1234",
"password" => "****"
);
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
//execute post
$result = curl_exec($ch);
echo '<pre>'.print_r($result, true).'</pre>';
//close connection
curl_close($ch);
</php>
Debugging the app shows the user name and password are passed in properly to the MVC side.
OK what you need to do is save the cookie that comes back from your cURL request and make sure it gets sent with subsequent requests.
This is how to set where to store cookies (and include in subsequent requests) in PHP:
curl_setopt($ch, CURLOPT_COOKIEJAR, 'mycookiefile');
You'll need the cookie filename to be constant through the process, so I would suggest using a variable and initialising it thus:
$cookieFile = tempnam("/tmp", "CURLCOOKIE");
You can get more details on this at the PHP documentation site:
http://www.php.net/manual/en/function.curl-setopt.php
This becomes a curl and PHP question then. I do not know curl and know little PHP but should be easy:
Take the authorisation cookie by checking the value of Set-Cookie header
parse the value which is in the format of .ASPXAUTH=<Cookie Value> and get the cookie value
Set the cookie in PHP
In all subsequent calls, get the value of the cookie from client and send to server using curl
curl_setopt($ch, CURLOPT_COOKIEJAR, '/some/path/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/some/path/cookies.txt');
This should do the trick. As you need to store the cookies and send them back. Otherwise each request would be treated as if its coming from a completely different user.