1

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?

pinoyyid
  • 21,499
  • 14
  • 64
  • 115
TheCrafter
  • 1,909
  • 2
  • 23
  • 44
  • there are no short examples, only long ones and they are in the Google documentation. You need to understand and implement OAuth before you attempt to talk to Drive – pinoyyid Aug 30 '15 at 09:36
  • @pinoyyid In google docs I found examples only for Java, C#, Javascript, etc... – TheCrafter Aug 30 '15 at 09:45
  • Search for Google Oauth and you'll see fragments of the rest api. Eghttps://developers.google.com/identity/protocols/OAuth2WebServer?hl=en. Remember, do NOT go anywhere near Google Drive until you know enough OAuth to fetch an access token. – pinoyyid Aug 30 '15 at 13:59

1 Answers1

2

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:

  1. refresh_token - Used to get more access_tokens and never expires
  2. 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.

  1. Obtain a OAuth 2.0 client ID through the Google Developers Console

  2. Obtain an access token from the Google Authorization Server

  3. Send the access token to an API

  4. 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 ;)

Community
  • 1
  • 1
Luke Cauthen
  • 690
  • 8
  • 19
  • For #4: Well, I would include an access token if I could. The problem is that it is not so easy to get one. As I understand, you first have to prompt the user to login in his google account and then you somehow get the token. But I don't fully understand how this works. – TheCrafter Sep 03 '15 at 16:02
  • I made a pretty long edit that you should take a look at. – Luke Cauthen Sep 03 '15 at 16:33
  • Thanks for your answer Luke!! I think that might help me (even thought I'm still wondering how can I get the first access token). I will try again in a couple of days, trying all those that you said and I will give feedback here. note: In case you didn't understand, I'm trying to do everything by simple http requests. Without using any of the major languages that google provides libraries for. I am using haskell. – TheCrafter Sep 04 '15 at 20:20
  • As you can see here https://developers.google.com/accounts/images/webflow.png after user login I am supposed to take back an authorization code. And here's my problem. How am I supposed to do that on my own? Do I have to listen for a connection or something? No clue. – TheCrafter Sep 04 '15 at 20:24
  • I don't think you can authenticate a user over http alone. You are going to have to use some other method to get the `refresh_token` then you can use http requests for anything else you want to do. You also need to make sure you understand the difference between `access_token` and `refresh_token` because that is an important distinction. – Luke Cauthen Sep 04 '15 at 21:18
  • I just hoped I wouldn't have to restrict myself with using C# or Java or Javascript etc... That's why I was looking for the possibility of using http alone. – TheCrafter Sep 04 '15 at 21:35
  • You could probably do it using the Android API in java. You can't do it with just Javascript and I have no idea about C# – Luke Cauthen Sep 08 '15 at 13:55
  • With C# is possible. And easy. I've done it in the past. Its a lot like Java anyway. – TheCrafter Sep 08 '15 at 17:41
  • Well then use C# to get the refresh token then you can use it to make http requests. For example I got my refresh token with PHP and am using it with http requests made in server side javascript. (Just as an example) – Luke Cauthen Sep 08 '15 at 19:00
  • That's what I'm gonna do probably. I was just hoping to avoid using C# or Java. – TheCrafter Sep 08 '15 at 22:55