How can we store a JSON credential to ENV variable in python?

Question:

{
    "type": "service_account",
    "project_id": "project_id",
    "private_key_id": "private_key_id",
    "private_key": "-----BEGIN PRIVATE KEY-----n",
    "client_email": "email",
    "client_id": "id",
    "auth_uri": "uri_auth",
    "token_uri": "token_urin",
    "auth_provider_x509_cert_url": "auth_provider_x509_cert_url",
    "client_x509_cert_url": "client_x509_cert_url"
}

I tried encoding and decoding the JSON but it didn’t work

I even tried using /// in place of " "

So I am using sheets-api. What I want to achieve is loading the path-for-json-file from .env variable

scope=['https://spreadsheets.google.com/feeds',
      'https://www.googleapis.com/auth/drive',
      'https://www.googleapis.com/auth/drive.file',
      'https://www.googleapis.com/auth/spreadsheets'
      ]
credentials = ServiceAccountCredentials.from_json_keyfile_name(r"path-for-json-file", scope)
client = gspread.authorize(credentials)
Asked By: Subham

||

Answers:

Assuming your JSON file is creds.json

creds.json

{
    "type": "service_account",
    "project_id": "project_id",
    "private_key_id": "private_key_id",
    "private_key": "-----BEGIN PRIVATE KEY-----n",
    "client_email": "email",
    "client_id": "id",
    "auth_uri": "uri_auth",
    "token_uri": "token_urin",
    "auth_provider_x509_cert_url": "auth_provider_x509_cert_url",
    "client_x509_cert_url": "client_x509_cert_url"
}

main.py

import json

data = json.load(open('creds.json'))

f = open(".env", "x")

for key, value in data.items():
    f.write(f"{key.upper()}={value}n")

creds.env will be generated

TYPE=service_account
PROJECT_ID=project_id
PRIVATE_KEY_ID=private_key_id
PRIVATE_KEY=-----BEGIN PRIVATE KEY-----

CLIENT_EMAIL=email
CLIENT_ID=id
AUTH_URI=uri_auth
TOKEN_URI=token_urin
AUTH_PROVIDER_X509_CERT_URL=auth_provider_x509_cert_url
CLIENT_X509_CERT_URL=client_x509_cert_url

create_keyfile_dict() basically returns a dict called variable_keys

from dotenv import load_dotenv

load_dotenv()

def create_keyfile_dict():
    variables_keys = {
        "type": os.getenv("TYPE"),
        "project_id": os.getenv("PROJECT_ID"),
        "private_key_id": os.getenv("PRIVATE_KEY_ID"),
        "private_key": os.getenv("PRIVATE_KEY"),
        "client_email": os.getenv("CLIENT_EMAIL"),
        "client_id": os.getenv("CLIENT_ID"),
        "auth_uri": os.getenv("AUTH_URI"),
        "token_uri": os.getenv("TOKEN_URI"),
        "auth_provider_x509_cert_url": os.getenv("AUTH_PROVIDER_X509_CERT_URL"),
        "client_x509_cert_url": os.getenv("CLIENT_X509_CERT_URL")
    }
    return variables_keys

scope=['https://spreadsheets.google.com/feeds',
      'https://www.googleapis.com/auth/drive',
      'https://www.googleapis.com/auth/drive.file',
      'https://www.googleapis.com/auth/spreadsheets'
      ]
credentials = ServiceAccountCredentials.from_json_keyfile_name(create_keyfile_dict(), scope)
client = gspread.authorize(credentials)
Answered By: Rohith Nambiar

A simpler way using a single env variable

  • First encode your JSON in base-64 as follows:
import json
import base64
import os
from dotenv import load_dotenv, find_dotenv


service_key = {
    "type": "service_account",
    "project_id": "project_id",
    "private_key_id": "private_key_id",
    "private_key": "-----BEGIN PRIVATE KEY-----n",
    "client_email": "email",
    "client_id": "id",
    "auth_uri": "uri_auth",
    "token_uri": "token_urin",
    "auth_provider_x509_cert_url": "auth_provider_x509_cert_url",
    "client_x509_cert_url": "client_x509_cert_url"
}

# convert json to a string
service_key = json.dumps(service_key)

# encode service key
encoded_service_key = base64.b64encode(service_key.encode('utf-8'))

print(encoded_service_key)
# b'many_characters_here'
  • In your .env file, add an environment variable SERVICE_ACCOUNT_KEY with the value of encoded_service_key:
SERVICE_ACCOUNT_KEY = b'a_long_string'
  • Now to convert the encoded string back to JSON:
# get the value of `SERVICE_ACCOUNT_KEY`environment variable
load_dotenv(find_dotenv())
encoded_key = os.getenv("SERVICE_ACCOUNT_KEY")

# remove the first two chars and the last char in the key
encoded_key = str(encoded_key)[2:-1]

# decode
original_service_key= json.loads(base64.b64decode(encoded_key).decode('utf-8'))

print(original_service_key['private_key_id'])
# private_key_id

# credentials = ServiceAccountCredentials.from_json_keyfile_name(
#     original_service_key, scope)
# client = gspread.authorize(credentials)
Answered By: Bunny
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.