I have a php application that accesses Asana API. I am able to create a project in Asana. However, the ajax call to the API class is returning a readystate=0.
While troubleshooting in firebug I also noticed that the network console has a 302, 400(??), and 200 status code. I thought 400 status code is related to invalid request or malformed url, but the project gets created anyway.
Any idea?
Update: More information.
I have a Ajax call to a php file which intern calls Asana API to getAuth code and tokens before calling the API services.
I believe I am getting the CORS warning and hence the readystate=0 and the 400 error. However because rest of my script proceeds with the token it was inserting records anyways. However, after the tokens expired (3600 sec), now I am unable to insert records. I know if I call the php file directly it works without the CORS error.
$.ajax({
type: 'POST',
url: "oa/asana.php",
data: {apiprovider:"asana",type:"addnewproject",notes:"notes",name:"name",id:"id",resource:"projects"},
//dataType:"json",
//contentType: "application/json",
success: function(data) {
console.log(data);
},
error: function( error )
{
console.log("asana api error");
console.log(JSON.stringify(error)) ;
},
async:true
});
my php code looks like this.
...$asana = new AsanaAuth(API_KEY,API_SECRET,callbackUrl);
if (!isset($_GET['code'])) {
$url = $asana->getAuthorizeUrl();
header('Location:' . $url);
} else {
$asana->getAccessToken($_GET['code']);
if ($asana->hasError()) {
echo 'Error response code: ' . $asana->responseCode;
}
else {
echo $asana->response;
}
}
Is there a better way to do this outside of Ajax call?
OK here's how I fixed it. Partly my understanding was wrong and I made a wrong assumption.
This is purely based on my application's need and this may not be applicable to all.
I have a settings page where the user clicks on the Asana app to authorize the connection. This is not a Ajax call but a hyperlink to a file which is also my redirect uri. Within this file I check if the user has already authorized if not I call authorize, get tokens and store the refresh token in the database for future use.
In the other parts of my application, when the user clicks on create an asana project, I check for the validity of the access token if it has expired, I refresh and get another token again.
Earlier, I was trying to call this from one page (which in a normal user flow will never happen -in my application). So right now there is no Ajax call for authorize but calling the refresh token, and Asana API endpoints are through Ajax and they work fine.
Hope this helps someone in future.
Related
I'm implementing OpenId Connect into my Yii2 app using the yii2-authclient library. I can login and exchange the code for a token with no problems. I've followed most of the code examples on the web and set a successCallback function that gets called once a user successfully logs in. It looks like this:
public function successCallback(ClientInterface $client)
{
$attributes = $client->getUserAttributes();
}
This code gets called, but calling getUserAttributes() results in the following error:
Exception – yii\authclient\InvalidResponseException
Request failed with code: 400, message:
{"error":"invalid_request","error_description":"Token not provided"}
The logs on the id server show a blank client and user, with an error of invalid_token.
I took a close look at the request I make and I see an access_token element. Any ideas what the problem might be? I can provide more information if necessary.
I figured it out. The problem was that the yii2-authclient library was sending the token as a GET parameter and the ID server was expecting it as a POST param. I upgraded the yii2-authclient library and that solved the problem since a recent change sends the parameter as POST instead of GET.
I have an Angular app that consumes an API I built in Laravel, and I use jwt-auth for token management and satellizer on the front end to send the token with each request.
My live environment (for both the front end and the API - which will be moved to a different server once the app is finished) at the moment consists of 2 AWS EC2 instances running nginx with a load balancer. Both servers have the same jwt secret key.
However, and at the moment I can't work out any pattern to it, I randomly get 400 "token_invalid" errors returned from my api. It is not one particular api route, nor is it on every load of the app. When I get a 400 error, from my /clients endpoint for example, other requests will have returned 200's. Next time, all will return 200's. The time after that I may get 200 returned for /clients but a 400 error for /users.
Could this be an issue with me using a load balancer? The jwt secret key, as I said, is the same on both servers - as all the code is in GIT.
I am not using the jwt.refresh middleware.
One other thing to mention is that I don't ever get 400 errors returned when running the app locally via Homestead, ony in production.
EDIT - it seems as though logging out (which clears both my user object (basic details only) and the token from local storage, clearing my cache, then logging back in most often causes the error - is this helpful?
Below is an example of one of my api calls.
App.js
.service('ClientsService', function($http, $q, __env) {
this.index = function () {
var deferred = $q.defer();
$http.get(__env.apiUrl + '/clients')
.then(function successCallback(response) {
console.log(response.data);
deferred.resolve(response.data);
},
function errorCallback(response) {
console.log(response);
});
return deferred.promise;
}
})
ClientsController.js
.controller('ClientsController', function(ClientsService, $stateParams, $mdDialog, $mdToast) {
var vm = this;
ClientsService.index().then(function(clients) {
console.log('ClientsCtrl init');
vm.clients = clients.data;
});
// other controller code
})
I'm really struggling to debug this, so any help would be much appreciated. If any more info is needed, please let me know.
https://github.com/tymondesigns/jwt-auth/issues/1583
solution: use the same jwt secret in .env file
I am new to CakePHP and am using version 2.7.5.
I followed the tutorial to create a basic REST service.
I now secured them using the basic auth tutorial.
Now, I have an AngularJS app over this REST service but need a way to prompt users to login or say their account does not have access to that resource.
Right now, when the REST call is made, and they do not have access, the response is a redirect HTML page to "/" or to logon. But I want the response in JSON with a message that says "access denied" or "session is up please logon.." etc.
I know it's the flash variable in cakephp but i am using AngularJS.
So my question is, where do I code in cakephp to send json response instead of HTML page redirect if a user does not have access to a certain rest url after logging in?
You can just return a response header back to the request with the correct status code(401).
if(!$authorized){
return header('HTTP/1.0 401 Unauthorized');
}
You can catch the error code in your request method, for example an ajax request
.error(status){
switch(status.code)
{
case 401:
//Unauthorized
break;
}
}
Code that I had written to fetch a Facebook page's posts using an app access token has suddenly stopped working. The JSON response's data object is an empty array. I'm not getting any error messages. When I try making the same request using an access token generated by the Graph API explorer, I get back a valid JSON response containing data. I've tried resetting my app's secret and generating a new access token, but I still get back an empty data object.
When I use the Facebook access token debugger, the only information returned is the App ID.
I generated my app access token by making a GET request to https://graph.facebook.com/oauth/access_token?client_id=<app_id>&client_secret=<app_secret>&grant_type=client_credentials
I don't have control over the page I'm trying to fetch data from, but I can contact the admin. Are there any permissions I should have them check?
Without any error messages or feedback, I'm at a loss on how to debug this. Does anyone have any advice?
This works perfectly.
Demo
token = 'valid_access_token';
page = '20531316728';
url = 'https://graph.facebook.com/'+page+'/feed?access_token="+token+"&fields=id,message&limit=10';
comments = [];
$.ajax({
'async': false,
'url': url,
'dataType': "json",
'success': function (data) {
$('.result').html(JSON.stringify(data));
},
'error': function(data){
$('.result').html(JSON.stringify(data));
}
});
I've successfully made my way through the LinkedIn OAuth process (using the REST API - OAuth 1.0a). However I'm having trouble with my first API call after the callback. I set the UserToken, UserTokenSecret and UserVerfier in the library I am writing, and this call this function to get my profile information:
public function getUserProfile()
{
$consumer = new OAuthConsumer($this->consumer_key, $this->consumer_secret, NULL);
$auth_token = new OAuthConsumer($this->getUserToken(), $this->getUserTokenSecret());
$access_token_req = new OAuthRequest("GET", $this->access_token_endpoint);
$params['oauth_verifier'] = $this->getUserVerifier();
$access_token_req = $access_token_req->from_consumer_and_token($this->consumer,
$auth_token, "GET", $this->access_token_endpoint, $params);
$access_token_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,
$auth_token);
$after_access_request = $this->doHttpRequest($access_token_req->to_url());
$access_tokens = array();
parse_str($after_access_request,$access_tokens);
# line 234 below
$access_token = new OAuthConsumer($access_tokens['oauth_token'], $access_tokens['oauth_token_secret']);
// prepare for get profile call
$profile_req = $access_token_req->from_consumer_and_token($consumer,
$access_token, "GET", $this->api_url.'/v1/people/~');
$profile_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,$access_token);
$after_request = $this->doHttpRequest($profile_req->to_url());
var_dump($after_request);
}
The function var_dumps a string, which is the basic synopsis of my profile:
string(402) " User Name etc. etc. http://www.linkedin.com/profile?viewProfile=&key=28141694&authToken=HWBC&authType=name&trk=api*a137731*s146100* "
That's good. However, the minute I refresh the page, the same function call fails with:
Undefined index: oauth_token, line number: 234
(this line marked with comment in above code block).
Then, of course, the var_dump reports this error from LinkedIn:
string(290) " 401 1310652477038 R8MHA2787T 0 [unauthorized]. The token used in the OAuth request is not valid. "
something to note:
the user token, secret, and verifier are persisted during the initial authorization callback (right before this function is called). So, they are the same during the first call (when it works, right after coming back from linkedin) and during a page reload (when it fails on line 234).
Also, I must admit I'm not 100% sure I understand everything that's going on in this function. I actually took examples from this tutorial (about a different service, not linkedin) http://apiwiki.justin.tv/mediawiki/index.php/OAuth_PHP_Tutorial and combined it with the information I gathered from the LinkedIn API documentation, spread throughout their developer site. Most notable was the addition of the 'verifier' which the tutorial did not use.
Any insight into this problem would be greatly appreciated. Thanks in advance.
-Nick
UPDATE
The only way I've been able to get this going is to do a new OAuth handshake every single time. Is this the way it's supposed to happen? I was under the impression that once I got my user token/secret and verifier, that I could then use these for continuous API calls until the token expired or was revoked.
As it is now, every time the page reloads I'm requesting a new user token, secret and verifier, then immediately calling to get the user profile (which succeeds). Next reload, I get a whole new key/secret and verifier. Seems like quite a lot of work for each call, and as I understood it, you should be able to perform offline operations with this method - and if I need new authorization each time, then I guess I can't do that?
Well. I've finally figured out what was going on so thought I'd post the answer here, just in case someone else runs into this.
The example that I was using as a guide was flawed. After the access token is retrieved, you should then create a new OAuthRequest object, instead of using the existing $access_token_req instance.
So this:
// prepare for get profile call
$profile_req = $access_token_req->from_consumer_and_token($consumer,
$access_token, "GET", $this->api_url.'/v1/people/~');
$profile_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,$access_token);
$after_request = $this->doHttpRequest($profile_req->to_url());
Should be changed to this:
$api_req = new OAuthRequest("GET", $this->api_url.$api_call);
// prepare for get profile call
$api_req = $api_req->from_consumer_and_token($consumer,
$access_token, "GET", $this->api_url.'/v1/people/~');
$api_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,$access_token);
$after_request = $this->doHttpRequest($api_req->to_url());