Skip to content

Instantly share code, notes, and snippets.

@LindaLawton
Last active April 16, 2026 23:15
Show Gist options
  • Select an option

  • Save LindaLawton/cff75182aac5fa42930a09f58b63a309 to your computer and use it in GitHub Desktop.

Select an option

Save LindaLawton/cff75182aac5fa42930a09f58b63a309 to your computer and use it in GitHub Desktop.
Curl bash script for getting a Google Oauth2 Access token
# Tutorial https://www.daimto.com/how-to-get-a-google-access-token-with-curl/
# YouTube video https://youtu.be/hBC_tVJIx5w
# Client id from Google Developer console
# Client Secret from Google Developer console
# Scope this is a space seprated 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=http://127.0.0.1&scope=[Scopes]&response_type=code
# Exchange Authorization code for an access token and a refresh token.
curl \
--request POST \
--data "code=[Authentcation code from authorization link]&client_id=[Application Client Id]&client_secret=[Application Client Secret]&redirect_uri=http://127.0.0.1&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
@bmsrox
Copy link
Copy Markdown

bmsrox commented Nov 6, 2017

Hi ... I've been trying to use that, but show an error
{ "error" : "invalid_request", "error_description" : "Required parameter is missing: grant_type" }

@ChanakyaSrinivas
Copy link
Copy Markdown

ChanakyaSrinivas commented Nov 29, 2017

Hi All,

How to authenticate gmail user for google calendar using curl statements?

can you please help me out

@LindaLawton
Copy link
Copy Markdown
Author

LindaLawton commented Jul 17, 2018

Note it also works using

curl -d client_id=vpdthl4ms0soutcrpe036ckqn7rfpn.apps.googleusercontent.com -d client_secret=uxpj6hx1H2N5BFqdnaNhIbie -d grant_type=authorization_code -d redirect_uri=urn:ietf:wg:oauth:2.0:oob -d code=4/AABvK4EPc__nckJBK9UGFIhhls_69SBAyidj8J_o3Zz5-VJN6nz54ew https://accounts.google.com/o/oauth2/token

now links to How to connect to the Google Drive API using cURL?

@eruffaldi
Copy link
Copy Markdown

Similar but with all the steps and macro replacements
https://gist.github.com/eruffaldi/98cfb6cc5b11a3778ac9dcb507ac75f4

Copy link
Copy Markdown

ghost commented Mar 26, 2019

Hi All,
I was tried the script, but I am getting the
{
"error": "invalid_grant",
"error_description": "Bad Request"
}

Then I changed the grant_type=client_credentials and tried. But again get the error that pasted below.

curl
--request POST
--data "code=4/GQEg70zaxHAuRhhd6A1RB_6LIxwwBV8ak5xRP-nZIBTjuvt4g3fTWyU&client_id=954040553015-bphgid2596t65i91827omteq778cp7gj.apps.googleusercontent.com&client_secret=Sn3giYFFPMCNteKC--938xsP&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=client_credentials"
https://accounts.google.com/o/oauth2/token

Respose:
{
"error": "unsupported_grant_type",
"error_description": "Invalid grant_type: client_credentials"
}

Also, tried LindaLawton's curl command that pasted below and getting the error.

curl -d client_id=954040553015-bphgid2596t65i91827omteq778cp7gj.apps.googleusercontent.com -d client_secret=Sn3giYFFPMCNteKC--938xsP -d grant_type=authorization_code -d redirect_uri=urn:ietf:wg:oauth:2.0:oob -d code=4/GQEg70zaxHAuRhhd6A1RB_6LIxwwBV8ak5xRP-nZIBTjuvt4g3fTWyU https://accounts.google.com/o/oauth2/token

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

@viniciusd
Copy link
Copy Markdown

Got invalid_grant as well. The reason is that the given authorization code can only be used once.

If one performs a malformed request with the code, it is now lost and you should retrive a new one.

I am performing those steps using httpie, so it looks like:

http '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'
# This is gonna give you a Redirect, you should open that location on your browser and accept it manually
http -f POST 'https://accounts.google.com/o/oauth2/token' 'client_id=[Application Client Id]' client_secret=[Application Client Secret] 'code=[Authentcation code from authorization link]' grant_type=authorization_code redirect_uri=urn:ietf:wg:oauth:2.0:oob

@prdpjngd
Copy link
Copy Markdown

curl -d client_id=vpdthl4ms0soutcrpe036ckqn7rfpn.apps.googleusercontent.com -d client_secret=uxpj6hx1H2N5BFqdnaNhIbie -d grant_type=authorization_code -d redirect_uri=urn:ietf:wg:oauth:2.0:oob -d code=4/AABvK4EPc__nckJBK9UGFIhhls_69SBAyidj8J_o3Zz5-VJN6nz54ew https://accounts.google.com/o/oauth2/token

TRYED IT WORKed

@esmaeilpour
Copy link
Copy Markdown

esmaeilpour commented Dec 24, 2020

@viniciusd 👍

@CPQE
Copy link
Copy Markdown

CPQE commented Apr 21, 2021

Doesn't work for me, returns "prepare_token_request() got multiple values for argument 'grant_type'.

@LindaLawton
Copy link
Copy Markdown
Author

LindaLawton commented Apr 22, 2021

@pilchita
Copy link
Copy Markdown

No work for me, i see this error:

Se produjo un error en la autorización
Error 400: redirect_uri_mismatch
The redirect URI in the request, urn:ietf:wg:oauth:2.0:oob, can only be used by a Client ID for native application. It is not allowed for the WEB client type. You can create a Client ID for native application at https://console.developers.google.com/apis/credentials/oauthclient
Más información

@LindaLawton
Copy link
Copy Markdown
Author

LindaLawton commented Jan 18, 2022

@pilchita You created web application credentials. For this to work you need to create credentials for a native application. Try watching this How to create an installed client.

Or this Understanding Oauth2 with curl

@pilchita
Copy link
Copy Markdown

Forgive my English, I want to use curl to create email accounts in the domain of the company where I work and so I can automate this process. I have read the documentation and some things I do not understand, I will follow your instructions to make it work.

I think I am confused when specifying the type of application, should I indicate that it is a desktop application or a web application?

Regards,

@LindaLawton
Copy link
Copy Markdown
Author

its a desktop application . If you have google workspace you should be using a service account with another programming language. Using curl for that is going to make things harder for you.

@pilchita
Copy link
Copy Markdown

Linda thanks for your help.

Already create a service account and provide permissions (https://www.googleapis.com/auth/admin.directory.user // https://www.googleapis.com/auth/cloud-platform).

{
"type": "service_account",
"project_id": "xxxxxxxxxx",
"private_key_id": "xxxxxxxxxxxxxxxxxx",
"private_key": ""
"client_email": "[email protected]",
"client_id": "xxxxxxxxxxxxxxxxxxxxxxxxx",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/api-admin-kiu-email%40api-manage-users.iam.gserviceaccount.com"
}

With that information I can’t generate a token using curl, postman or httpie?

Regards,

@LindaLawton
Copy link
Copy Markdown
Author

LindaLawton commented Jan 18, 2022

I know for a fact that your not going to be able to do it with postman. Im not sure that curl is able to do the encoding needed if you manage to create a valid JWT with curl i would love to see the code. heres a link to the documentation https://developers.google.com/identity/protocols/oauth2/service-account

this looks like it might help to https://techdocs.akamai.com/iot-token-access-control/docs/generate-jwt-rsa-keys

maybe one of these if i have time i might give it a try.

@prashantrbs
Copy link
Copy Markdown

prashantrbs commented Jan 30, 2022

When i hit curl command i am getting below url

curl --request POST --data "code=4/0AX4XfWiu_WHUUrStOBoyK4G4Q6fhQqJXdETW9rKveglB5ik3K5HvjyQqHyA&scope=https://mail.google.com&client_id=288234510771-cv3hjbluppni7pn79cp8l9j46ls8ildp.apps.googleusercontent.com&client_secret=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&redirect_uri=http//localhost&grant_type=authorization_code" https://accounts.google.com/o/oauth2/token

Error:

{
"error": "invalid_request",
"error_description": "\nYou can\u0026#39;t sign in to this app because it doesn\u0026#39;t comply with Google\u0026#39;s OAuth 2.0 policy for keeping apps secure.\n\nYou can let the app developer know that this app doesn\u0026#39;t comply with one or more Google validation rules.\n "
}

Some one please help

@LindaLawton
Copy link
Copy Markdown
Author

LindaLawton commented Mar 5, 2022

Google has recently made a change that breaks this script How to authorize a curl script to Google Oauth after OAuth out-of-band oob flow is deprecated?. I have a question up on Stack overflow to see if it can be fixed or not.

The solution was to use http://127.0.0.1 instead.

@Akianonymus
Copy link
Copy Markdown

I know for a fact that your not going to be able to do it with postman. Im not sure that curl is able to do the encoding needed if you manage to create a valid JWT with curl i would love to see the code. heres a link to the documentation https://developers.google.com/identity/protocols/oauth2/service-account

Here is a bash function to generate jwt, needs openssl to craete the payload data and jq to extract values from json. Wrote this function recently for some google drive stuff

###################################################
# Generate rs256 jwt just with cli commands and shell
# Specifically for gdrive service accounts usage
# Globals: None
# Arguments: 2
#   ${1} = service account json file contents ( should contain client_email and private key )
#   ${2} = SCOPE for gdrive ( if not given then global var SCOPE is used )
# Result: print jwt
# Refrences:
#   https://stackoverflow.com/questions/46657001/how-do-you-create-an-rs256-jwt-assertion-with-bash-shell-scripting
#   Inspired by implementation by Will Haley at:
#     http://willhaley.com/blog/generate-jwt-with-bash/
###################################################
_generate_jwt() {
    declare json="${1:?Error: Give service json file contents}" \
        scope="${2:-${SCOPE}}" aud="https://oauth2.googleapis.com/token" \
        header='{"alg":"RS256","typ":"JWT"}' \
        algo="256" scope payload_data iss exp iat rsa_secret signed_content sign

    if iss="$(jq .client_email <<< "${json}")" &&
        rsa_secret="$(jq .private_key <<< "${json}")"; then
        rsa_secret="$(printf "%b\n" "${rsa_secret}")"
    else
        printf "Error: Invalid service account file.\n" && return 1
    fi

    iat="$(printf "%(%s)T\\n" "-1")" exp="$((iat + 3400))"

    b64enc() { : "$(openssl enc -base64 -A)" && : "${_//+/-}" && : "${_//\//_}" && printf "%s\n" "${_//=/}"; }

    payload_data='{"iss":"'${iss}'","scope":"'${scope}'","aud":"'${aud}'","exp":'${exp}',"iat":'${iat}'}'

    {
        signed_content="$(b64enc <<< "${header}").$(b64enc <<< "${payload_data}")"
        sign="$(printf %s "${signed_content}" | openssl dgst -binary -sha"${algo}" -sign <(printf '%s\n' "${rsa_secret}") | b64enc)"
    } || return 1

    printf '%s.%s\n' "${signed_content}" "${sign}"
    return 0
}

P.S: Also answered your post on stackoverflow

@jay
Copy link
Copy Markdown

jay commented Jan 16, 2023

The out-of-band method no longer works which is why the script is broken. I have some scripts that use the loopback method on desktop and are working as of this posting.

@oshliaer
Copy link
Copy Markdown

Thanks @jay!

@LindaLawton
Copy link
Copy Markdown
Author

LindaLawton commented Jan 17, 2023

@jay you can use http://127.0.0.1 instead of urn:ietf:wg:oauth:2.0:oob and it works fine.

@phlbnks
Copy link
Copy Markdown

phlbnks commented Jan 31, 2023

Works perfectly - thanks!

@rohanmenon96
Copy link
Copy Markdown

Why is there a consent screen for the first step to get the code? How would I possible click the Accept in a server environment? Could anyone please help me out if possible.

@LindaLawton
Copy link
Copy Markdown
Author

@rohanmenon96 you wouldn't do this on a server you would do it on your local machine. A server doesn't have a browser window. Get a refresh token then store it and upload that to your server

@linhdv96
Copy link
Copy Markdown

linhdv96 commented Jun 8, 2023

unrelated but it's worth the reference,
get access_token using google/apiclient library in Laravel(php8),
This access_token works with any project in 1 firebase

https://github.com/linhdv96/cUrl-firebase-remote-config

@aglines
Copy link
Copy Markdown

aglines commented Jul 19, 2023

Found a good link, Goog OAUth2 Playground helped generate the refresh token with correct scope, etc. Doc here, link is in the doc:
https://developers.google.com/google-ads/api/docs/oauth/playground

@ww7
Copy link
Copy Markdown

ww7 commented Dec 4, 2024

@mymirai-nikki
Copy link
Copy Markdown

I'm looking for full curl automation that didn't require to go to the consent screen to grab the code, is there a way to achieve pure, full and complete curl automation?

@LindaLawton
Copy link
Copy Markdown
Author

LindaLawton commented Apr 16, 2026

@mymirai-nikki you wont find that. Oauth2 requires user consent. The only thing to do that would be a service account pat token, and i have never had the time or inclination to try and code service account authorization in curl as it requires to much security magic.

Edit: gemini seems to have a few ideas one using the google cloud console logged in on your machine, the other is some fancy stuff using curl directly. If you get it to work let me know i would love to see the code working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment