Mohamad Massalha
Mohamad Massalha

Reputation: 125

get google Oauth2 access token using ONLY curl

I want to upload a pdf file to Google Drive using curl, for automated testing purposes.

I have created an account on Google Cloud Platform(got client ID and Secret) and enabled the Google Drive API.

All the methods to connect using OAuth2 involve a web browser or clicking some buttons, which I'm not intending to do.

Is there any way to make the whole process of authenticating using OAuth2 and getting an access token to be able to upload a file using it, using ONLY curl commands in the cmd terminal?

Thanks.

Upvotes: 12

Views: 13662

Answers (3)

Jay
Jay

Reputation: 329

Google's bearer tokens (OAuth 2.0 access_token) are ephemeral which means after, say, an hour they expire and need to be refreshed. Further, from what I've seen, Google's refresh issues a new bearer token and expiration.

I wrote some scripts that use perl, jq and curl to obtain a new bearer token and refresh an expired or about to expire bearer token. They are working as of this posting in 2023. I don't know of any way that you could do that just using curl, you would also need some scripting language.

(Note as of 2023 the out-of-band method in the selected answer no longer works. I have added a comment to the gist that answer links to.)

Upvotes: 0

Shaybc
Shaybc

Reputation: 3177

i wanted to do the same thing for some PC app (language doesn't matter Java / Node / Command line Curl / or even client side JavaScript)

i couldn't found a simple explanation (beside @DaImTo here), but it works only for native apps,

in order to create some/any app i had to use "Web Application" OAuth Client Application type, these are the steps i used:

  1. goto: Google Cloud console
  2. create new project (if you haven't already)
  3. enable Google Drive API for the project from here
  4. click on "Google Drive API" and press the "Enable API" button
  5. create "OAuth consent screen" (the screen a user see to allow your app to access their google drive data)
  6. add your site address to the redirect url table
  7. create credentials "OAuth Client ID" for "Web Application" from here
  8. make sure to save the "client ID" and "client secret" we will use them next

Now that you have a project, consent screen and a WebClient as an App developer, we need to act as a client and approve the app to access our Google Drive data like this:

  1. Goto: https://accounts.google.com/o/oauth2/auth?client_id=[YOUR CLIENT-ID]&redirect_uri=[YOUR SITE URL]&scope=https://www.googleapis.com/auth/drive&response_type=code&include_granted_scopes=true&access_type=offline&state=state_parameter_passthrough_value
  2. replace the values: [YOUR CLIENT-ID], [YOUR SITE URL]
  3. once you allow your app and a redirect to your site has occurred, copy from the url the: code=XXX parameter and save the XXX part aside as [YOUR CODE]

Once that's done, we can do again and again these next steps from command-line / code / whatever ...

  1. Get Access token by calling the next curl: curl --request POST --data "code=[YOUR CODE]&client_id=[YOUR CLIENT ID]&client_secret=[YOUR CLIENT SECRET]&redirect_uri=[YOUR SITE URL]&access_type=offline&grant_type=authorization_code" https://oauth2.googleapis.com/token

response should look like this:

{
  "access_token": "YYYY",
  "expires_in": 3599,
  "refresh_token": "ZZZZ",
  "scope": "https://www.googleapis.com/auth/drive",
  "token_type": "Bearer"
}

if you receive an error like this:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "parseError",
    "message": "Parse Error"
   }
  ],
  "code": 400,
  "message": "Parse Error"
 }
}

it probably means the file type is incorrect, if you receive an error like this:

{
  "error": "invalid_grant",
  "error_description": "Bad Request"
}

it usually means that the user has revoked the app permission (or code obtained in step 9 has expired), so simply repeat step 9

to upload the file using curl, do this:

  1. upload a file using the "access-token" from the response (YYYY part): curl -X POST -L -H "Authorization: Bearer YYYY" -F "metadata={name :'[FILE_NAME.EXT]'};type=application/json;charset=UTF-8" -F "file=@[FILE_NAME.EXT];type=application/javascript" "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"

replace the [FILE_NAME.EXT] with your file name and file extension, and run the command from the folder where the file reside (or add the path to the file), for example:

curl -X POST -L -H "Authorization: Bearer YYYY" -F "metadata={name :'myScript.js'};type=application/json;charset=UTF-8" -F "[email protected];type=application/javascript" "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"

this example uploads a javascript file, if you want to upload a different type - just replace the "application/javascript" with your file type, you can see accepted types here

in order to get the next access token, simply use the refresh token received in step 12 (the ZZZZ part) and use it in this curl command:

curl --request POST --data "access_type=offline&refresh_token=[ZZZZ]&client_id=[YOUR CLIENT ID]&client_secret=[YOUR CLIENT SECRET]&grant_type=refresh_token" https://oauth2.googleapis.com/token

Upvotes: 1

Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 117196

The following commands will show you how to authorize to Google using Curl. You are going to have to use the web browser at least once in order to get the refresh token once you have a refresh token you can just use the command to request a new one again after.

# Client id from Google Developer console
# Client Secret from Google Developer console
# Scope this is a space separated list of the scopes of access you are requesting.

# Authorization link.  Place this in a browser and copy the code that is returned after you accept the scopes.
https://accounts.google.com/o/oauth2/auth?client_id=[Application Client Id]&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=[Scopes]&response_type=code

# Exchange Authorization code for an access token and a refresh token.

curl \
--request POST \
--data "code=[Authentication code from authorization link]&client_id=[Application Client Id]&client_secret=[Application Client Secret]&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code" \
https://accounts.google.com/o/oauth2/token

# Exchange a refresh token for a new access token.
curl \
--request POST \
--data 'client_id=[Application Client Id]&client_secret=[Application Client Secret]&refresh_token=[Refresh token granted by second step]&grant_type=refresh_token' \
https://accounts.google.com/o/oauth2/token

Tips:

Upload is in two parts you need to upload your metadta, then a file stream of the actual file.

There is a difference between create and update. If its an existing file you will need to use update not create or your going to get a new file every time.

Code ripped from GoogleAuthenticationCurl.sh

service account

if you want fully hands free, then you should look into a service account, I cant help you do that in curl im not even sure its possible due to all the security and generation of tokens.

Refresh token expiration

THe official documentation for refresh tokens and their possible expiration

  • The user has revoked your app's access.
  • The refresh token has not been used for six months.
  • The user changed passwords and the refresh token contains Gmail scopes.
  • The user account has exceeded a maximum number of granted (live) refresh tokens. (There is currently a limit of 50 refresh tokens per Google Account per OAuth 2.0 client ID. If the limit is reached, creating a new refresh token automatically invalidates the oldest refresh token without warning. )

Upvotes: 11

Related Questions