Skip to content

Instantly share code, notes, and snippets.

@LindaLawton
Last active August 8, 2023 14:08
Show Gist options
  • Star 59 You must be signed in to star a gist
  • Fork 20 You must be signed in to fork a gist
  • Save LindaLawton/cff75182aac5fa42930a09f58b63a309 to your computer and use it in GitHub Desktop.
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
@prashantrbs
Copy link

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
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

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

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

Thanks @jay!

@LindaLawton
Copy link
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

phlbnks commented Jan 31, 2023

Works perfectly - thanks!

@rohanmenon96
Copy link

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
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

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

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

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