Error response client_not_active when trying to obtain access token using curl - rest

I'm going step-by-step Nest REST Quick Guide and now blocked with error response during attempts to obtain an access token.
Response is:
{"error":"client_not_active","error_description":"client is not active","instance_id":"here_is_something_looks_like_guid"}
I've checked Error Messages Guide, and it helps me a lot to understand that "Client not active". Useful, huh?
So which client and how to activate it?
I have a home simulator working, also I've registered a so-called 'product', which I want to develop (so I have Product ID, Product Secret, Authorization URL and Access Token URL).
[Upd]
For all operations I've used curl.
However with Firefox addon which sends POST data I'm able to obtain the access_token. So I keep the question, but so far will stick to browser.

This means the your product/client has been deactivated, most likely due to a violation of the Terms of Service. Is the problem consistently occurring?

Related

Is there a way to utilize an API without a client key?

Trying to access the API for Shortboxed: https://api.shortboxed.com/ using Visual Studio Code. I saw that on the website there is no way to generate a key, and not completely accustomed to the use of APIs, I ask if there is a way to access the data with just the API domain.
The following images are of my code, most likely this is an error in that.
It depends on the way the API was developed. Many APIs will use authentication/authorization (not the same thing exactly, but grouped together here to keep things simple). This involves the sender of the HTTP request identifying themselves, often by including a client key or token.
You'll know if the API answers unauthenticated or unauthorized requests by calling it. If you get a 2xx response (200, 204, etc) then you were allowed to. If the API's developer sticks to the HTTP spec strictly, they will return a status code like 401 Unauthorized (https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400). You can often find this information in the API docs so that you don't have to try things out to figure it out from scratch.
So at this point, it's up to that particular API's public documentation to describe its authentication/authorization to you so you know how you can call it.
I notice you say:
I saw that on the website there is no way to generate a key
So if you've already consulted their documentation and it says that you shouldn't need a key to call the API, but you get a response code like 401, you should contact their support to find out what may be going wrong.
Also worth mentioning that this will work the same no matter the HTTP client. Visual Studio Code, curl, Insomnia, Postman, a web browser (as long as it supports CORS), etc.

How can I create a HTTP/Rest request to upload something to Google Drive

I want to create a command line tool to download and upload files to my Google Drive. I do not want to use any language that Google already provides api calls (Java, php, javascript, C#, etc..).
I will use Haskell but that is not relevant with the question.
What I want to do now is form a POST request to upload a file. My request now is something like this:
POST /upload/drive/v2/files?uploadType=media HTTP/1.1
Host: www.googleapis.com
Content-Type: */*
Content-Length: 5
Authorization: Bearer AIzaSy......jH683-FRO9GI
Cache-Control: no-cache
test1
and I get this response:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Invalid Credentials"
}
}
Next to Authorization: I put the API Key I created from Google Developer's console.
I figured I have to do more than one requests to make this work. First I have to get an auth code, then use that code to get an auth token and then use that token to my post request.
How can I make that happen? Can someone give me a short example?
There are several possible issues:
#1
You shouldn't be sending the API key with your requests.
#2
Your key might have expired. They only last for 60 minutes.
#3
Your access might have been revoked. (But in your case, if you are able to get an access token, then this is not the case)
#4
You did not include an access token in your request.
I think your problem is a result of #1 or #4, but I listed the other possibilities for reference.
Edit #1:
To address the comment, I will explain the process Google uses to authenticate requests. This question addresses some of the process but I am going to rewrite some of it in the context of this question. (The linked question was asked by me and then later answered by me)
There are two main items you need to make a request to a Google API:
refresh_token - Used to get more access_tokens and never expires
access_token - Used to send API calls (example: upload a file) and expires every 60 minutes.
In order to get either of these you have to follow certain steps.
Obtain a OAuth 2.0 client ID through the Google Developers Console
Obtain an access token from the Google Authorization Server
Send the access token to an API
Refresh the access token, if necessary
More specific information about this "general" process can be found here.
The tricky step is getting the refresh token because once you have that stored in a secure location, you can do anything with simple httpRequests.
To get a refresh token, a user has to agree to give your project access to certain features. This is called scopes in Google language. You can do this in many different ways (according to Google):
There are several ways to make this request, and they vary based on
the type of application you are building. For example, a JavaScript
application might request an access token using a browser redirect to
Google, while an application installed on a device that has no browser
uses web service requests.
The one thing they don't tell you is that, in your case, it doesn't matter what medium you use to get the refresh_token because you are only using one account. The Google Drive API isn't really designed to be used like a server. It is designed to be used by a developer that wants to store information on each of its user's accounts. Like if you had a picture app, you could have a feature that stores edited picture on someone's personal Google Drive account.
What you (and many others who have recently asked about) want to do is essentially use a Drive account as a server. That means that the medium through which you get your refresh_token does not have to be related to the medium in which you are using the Drive Account.
For example in my specific case, I wanted a way to store user pictures on a server for free for an android app. I am using this free service called Parse to act as my database server, but they give you very limited file storage in their free tier.
Because of this, I decided to try and figure out how to use Google drive accounts to expand my storage. I created a generic gmail account something like "hostingaccount#gmail.com" to be the host of the files (15g for free).
To get my refresh_token, I setup a php server to authenticate that one account. When someone goes to the page I setup, they are prompted to login and then grant access to my project to use their Google Drive account (Specific scope: https://www.googleapis.com/auth/drive). I then setup the script to print the refresh_token for that account on the screen. I copied that string an put it into my server when now I can easily send httpRequests to:
https://www.googleapis.com/oauth2/v3/token/ to get an access token and to:
https://www.googleapis.com/upload/drive/v2/files to upload files.
I link it at the top of this edit, but this answer shows you how to get a refresh token using my php method. I never spent the time to try an figure out how to get a refresh token any other way, but if you read my whole long answer I think I mention that I believe that this can also be done with the Android Google Drive API.
I have tried to help so many people with this problem, maybe I should just start a blog and make a tutorial about it ;)

Perl - Facebook Graph API

Time ago it was easy to make a distinction between desktop and web applications, but today while reading while the documentation I've noticed that this difference is less pronounced.
I'm using the Facebook::Graph module to create a desktop application, but still can not go beyond the stage of configuration. I'm stuck at authentication phase:
my $ q = Plack::Request->new($env);
$fb->request_access_token($q->query_param('code'));
(http://metacpan.org/pod/Facebook::Graph)
It keeps telling me "$ env is required".
Reading the documentation I've realized that Plack is only concerned with web applications.
(http://metacpan.org/pod/Plack::Request)
Can you confirm this? If not, how do I get past this step?
It would not be a problem getting the access_token using Mechanize and then making a GET request as described in the documentation, but I do not want to complicate my existence, so if there are other ways...
A bit late, but there's a workaround.
To get an access token, take a look here:
https://developers.facebook.com/docs/howtos/login/login-for-desktop/
Just create a client with Mechanize or whatever you want and login with the desidered credentials
Perform the request as described
Move on from the authorization page
Parse the response and get the token
$fb->access_token($token);
http://developers.facebook.com/docs/reference/api/application/ says:
Note: Applications that are configured as Native/Desktop apps will not be able to make API calls that require an application access_token.
So it's not a Plack, it's Facebook who requires your app to be web.
But if you may avoid access_token request, it might work.

How to pass Facebook Id from client to server securely

I have a Facebook canvas app. I am using the JS SDK to authenticate the user on the browser-side and request various information via FB.api (e.g. name, friends, etc.).
I also want to persist some additional user information (not held on Facebook) to the database on my server by making an ajax call:
{ userFavouriteColour: "Red" }
To save this on the server and associate with the correct user, I need to know the Facebook uid and this presents a problem. How do I pass the uid from the client to the server.
Option 1: Add uid to the ajax request:
{ uid: "1234567890",
userFavouriteColour: "Red" }
This is obviously no good. It would be trivial for anyone to make an ajax request to my web service using someone else's Facebook Id and change their favourite colour.
Option 2: On the server, extract the uid from a cookie:
Is this even possible? I have read that Facebook sets a cookie containing the uid and access token but do I have access to this cookie on my domain? More importantly, can I securely extract the uid form the cookie or is this open to spoofing just like option 1.
Option 3: User server-side authentication on the server:
I could use the server-side authentication to validate the user identity on my server. But will this work if I am already using client-side authentication on the browser? Will I end up with two different access tokens? I would like to make FB.api requests from the browser so I need the access token on the client (not just on the server).
This must be a very common scenario so I think I'm missing something fundamental. I have read a lot of the Facebook documentation (various authentication flows, access tokens, signed_request, etc.) and many posts on SO, but I still don't understand how client-side authentication and server-side authentication play nicely together.
In short, I want to know the user's identity on the server but still make requests to the Facebook api from the client browser?
(I am using ASP.NET and the Facebook C# SDK on the server)
EDIT: Added bounty. I was hoping to get a more deifnitive, official recommendation on how to handle this situation, or even an example. As said, I have already read a lot of the official FB docs on authentication flows but I still can't find anything definitive on how client-side and server-side authentication work together.
Option 1:
The easiest way I can think of is to include the accessToken in JS and pass it with the ajax call.
Option 2:
Using the same as option 1, but instead of sending just the accessToken, send the signedRequest.
On the server side you can decode it using (TryParseSignedRequest method) which will give you the UserID :-)
Note: signedRequest is encrypted with the application Secret. you are the only one who should know it, so you are safe on that end.
Disclaimer:
I have no coding experience in C#, but a little search in google gave me this:
Facebook C# SDK for ASP.NET
Making AJAX Requests with the Facebook C# SDK
It's very simple actually.
When the user loads you app use the server side authentication, get the access token and load the user data by issuing an api request from the server.
On the server side you'll have everything you need and it's sandboxed.
When the page renders for the user, using the js sdk get the user authentication data, you should be able to use FB.getLoginStatus since the user already went through the server side authentication.
Now on the client side you also have an access token which you can use to get the user data from the graph api.
The two tokens will be different, and will also have different expiration, but that should not be a problem, both token should work properly as you'd expect them to.
Since both sides have their own token and a way to make requests to the api, there's no need to send any fb data between them.
So the 3rd option you mentioned, to me, sounds the best, and it's really simple to implement that too.
Edit
All facebook SDKs are just wrappers for http request since the entire fb api is made on http requests.
The SDKs just give you easy and shorter access to the data with out the need to build the url yourself (with all the different possible parameters), make the request and parse the response.
To be completely honest, I think that stop providing a way for the C# SDK to support server side authentication is a very bad decision.
What's the point in providing a SDK which does not implement the entire api?
The best answer to your question, from my experience, is to use both server and client side authentication, and since the C# SDK does not support it, my advice to you is to create your own SDK.
It's not complicated at all, I already implemented it for python and java (twice), and since you'll be developing it for your own needs it can be tailored for your exact needs, unlike a public SDK which should support all possible options.
2nd Edit
There's no need to create a completely new SDK, you can just "extend" the ones you're using and add the missing parts that you need, like sever side authentication support.
I don't know if it's language specific but using both server-side and client-side authentication does no harm.
You can work on option 2 but yes, that will be also vulnerable to spoofing.
Doing option 3, you will be having a single access token for that user session, so that would be the best choice according to me since you always have chance of spoofing when passing user information from client side.
I had exactly the same question recently. It's option 2. Check this post from the Facebook blog.
To be honest I am not enough of a hacker to know if you could spoof the UID in the cookie, but this seems to be the 'official' way to do it.
EDIT: to the other question under option 2, yes, I believe you have to access this cookie on your domain.

Error code 100 (Can only call this method on valid test users for your app)

getting the error {"error":{"message":"(#100) Can only call this method on valid test users for your app","type":"OAuthException"}} whenever trying to write to any facebook end point. Reading (GET) works fine, writing (POST) fails. Does anybody know how to resolve this?
I have also opened a ticket on FB dev site:
http://developers.facebook.com/bugs/184198634991192?browse=search_4e93328871c8a3231774584
The problem does not occur is I would shoot the POST request from my browser as if I am the user.
The problem does occurs only when sending from our servers on behalf of the user from one of our dev machines which have other subdomain names instead of www (such as dev1.blablabla.com & dev2.blablabla.com, while the app is registered to www.blablabla.com).
So the question is, does facebook attempt to do a reverse DNS lookup on all write requests to verify the source?
I believe your requirement is to get the user details of the owner of Facebook access token (normally the currently logged in user)
For that you have to issue a GET request and not a POST request.
The reason why it works when fired from the browser is that when you submit a query through the address bar it is send as a GET request, and when sent from your server it is send as POST and fails producing the error message mentioned in your post.
Facebook doesn't do a reverse DNS lookup on your write request and not need to configure anything in your server related to it.
Hope the answer is clear enough for you.