I have code from Google that successfully uses the google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file
API to open a browser and create a Google API Oauth2 token which is stored in a file and used in API calls:
from google_auth_oauthlib.flow import InstalledAppFlow
def get_credentials():
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists(TOKEN_FILENAME):
creds = Credentials.from_authorized_user_file(TOKEN_FILENAME, SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file( CREDENTIALS_FILENAME, SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(TOKEN_FILENAME, 'w') as token:
token.write(creds.to_json())
return creds
The CREDENTIALS_FILENAME
is a JSON file that is downloaded from the Google OAuth console.
Airtable supports OAuth but it does not download an easy-to-use credentials file. But I am still able to get all of the key parameters. I put these into a JSON file and tried Google's code, but it didn't work.
Here are the key paramters I tried:
{"installed":
{"client_id":"****",
"auth_uri":"https://airtable.com/oauth2/v1/authorize",
"token_uri":"https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
"client_secret":"*****",
"redirect_uris":["http://localhost"]}}
Well, my client ID is correct. The http://localhost
is what Google uses. The Google InstalledAppFlow.from_client_secrets_file
runs a local webserver on a random port to get the response from the redirected web browser. Unfortunately, from_client_secrets_file
doesn't allow me to specify a port.
I've tried other OAuth2 libraries with Airtable but can't get any of them to work either. I have lots of code. Most of it requires that I copy a URL from the console, paste it into my browser, then take the redirect URL (which produces an error) and paste it into the console.
This code gets quite far:
from oauthlib.oauth2 import WebApplicationClient
from requests_oauthlib import OAuth2Session
import secrets
import base64
import hashlib
def generate_pkce_pair():
""" Generate a code_verifier and code_challenge for PKCE. """
code_verifier = base64.urlsafe_b64encode(secrets.token_bytes(32)).rstrip(b"=").decode('utf-8')
code_challenge = base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode('utf-8')).digest()).rstrip(b"=").decode('utf-8')
return code_verifier, code_challenge
def main():
client_id = '****'
redirect_uri = 'https://localhost:8080/'
scope = ['schema.bases:read']
# Generate PKCE code verifier and challenge
code_verifier, code_challenge = generate_pkce_pair()
# OAuth2 client
client = WebApplicationClient(client_id)
oauth = OAuth2Session(client=client, redirect_uri=redirect_uri, scope=scope)
# Authorization URL
authorization_url, state = oauth.authorization_url(
url='https://airtable.com/oauth2/v1/authorize',
code_challenge_method="S256",
code_challenge=code_challenge
)
print("Please go to this URL and authorize:", authorization_url)
# Get the authorization code from the callback URL
redirect_response = input('Paste the full redirect URL here: ')
# Fetch the access token
token_url = "https://api.airtable.com/oauth/token"
token = oauth.fetch_token(
token_url=token_url,
authorization_response=redirect_response,
client_secret=None,
code_verifier=code_verifier)
print("Access token:", token)
if __name__ == '__main__':
main()
Giving me this:
Redirecting to a localhost:8080
URL which can't be read. That's okay, I paste in the redirect URL directly into the console, but then get this error:
oauthlib.oauth2.rfc6749.errors.CustomOAuth2Error: ({'type': 'INVALID_API_VERSION'})
And I can't figure out how to specify the API version.
So I need to either:
1 - Specify a valid redirect_uri to airtable that works with the Google library, or
2 - Specify the API version for the OAuth2Session
call.
To answer question 2, according to the documentation
So, change your
to