Skip to content

Instantly share code, notes, and snippets.

@ryu1kn
Last active March 18, 2024 14:19
Show Gist options
  • Save ryu1kn/c76aed0af8728f659730d9c26c9ee0ed to your computer and use it in GitHub Desktop.
Save ryu1kn/c76aed0af8728f659730d9c26c9ee0ed to your computer and use it in GitHub Desktop.
Getting GCP access token from a service account key JSON file

Getting GCP access token from a service account key

Use your service account's key JSON file to get an access token to call Google APIs.

Good for seeing how things work, including the creation of JWT token.

To create a JWT token, you can replace create-jwt-token.sh script with tools like step.

If you just want to get an access token for a service account, you can do the same thing with just gcloud command. cf Authorization and authentication.

Prerequisites

  • Have a GCP project and a service account.
  • The service account has a permission for the request.
    • e.g. For listing buckets, "https://www.googleapis.com/auth/devstorage.read_only"
  • The service account's key JSON file is downloaded (here, key.json).
  • Commands available: jq, openssl

Usage

Get an access token.

$ ./get-access-token.sh /path/to/key.json "https://www.googleapis.com/auth/devstorage.read_only"
ya29...

You can call a Google API with the token. Here since we've requested storage readonly, we list buckets.

$ curl "https://www.googleapis.com/storage/v1/b?project=<your_project_id>" \
    -H "Authorization: Bearer ya29..."

References

#!/bin/bash
set -euo pipefail
base64var() {
printf "$1" | base64stream
}
base64stream() {
base64 | tr '/+' '_-' | tr -d '=\n'
}
key_json_file="$1"
scope="$2"
valid_for_sec="${3:-3600}"
private_key=$(jq -r .private_key $key_json_file)
sa_email=$(jq -r .client_email $key_json_file)
header='{"alg":"RS256","typ":"JWT"}'
claim=$(cat <<EOF | jq -c .
{
"iss": "$sa_email",
"scope": "$scope",
"aud": "https://www.googleapis.com/oauth2/v4/token",
"exp": $(($(date +%s) + $valid_for_sec)),
"iat": $(date +%s)
}
EOF
)
request_body="$(base64var "$header").$(base64var "$claim")"
signature=$(openssl dgst -sha256 -sign <(echo "$private_key") <(printf "$request_body") | base64stream)
printf "$request_body.$signature"
#!/bin/bash
set -euo pipefail
key_json_file="$1"
scope="$2"
jwt_token=$(./create-jwt-token.sh "$key_json_file" "$scope")
curl -s -X POST https://www.googleapis.com/oauth2/v4/token \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' \
--data-urlencode "assertion=$jwt_token" \
| jq -r .access_token
@rekire
Copy link

rekire commented Apr 7, 2023

Based on the output of https://jwt.io/ the resulting JWT has syntax errors. There should be no = chars. However this helps me a lot to understand how I can build now myself the JWT without the huge google libs

@DinoChiesa
Copy link

DinoChiesa commented Nov 7, 2023

This is good stuff. And also, if you don't mind delegating to a tool, you can get a GCP Access token using the gcloud command line tool, with a couple of lines:

gcloud auth activate-service-account SERVICE_ACCOUNT@DOMAIN.COM --key-file=/path/key.json
gcloud auth print-access-token

Also, more on this theme: https://github.com/DinoChiesa/get-gcp-access-token

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