If not, please refer to OAuth 2 Code Flow to configure your application.
Application basics
Note: you should store your client_id and (if not using PKCE) client_secret safely and access them via your environment. The below examples assume the presence of a .env file containing the variables CLIENT_ID and CLIENT_SECRET.
import urllib, requests, requests.auth
import os
CLIENT_ID = os.environ.get('CLIENT_ID')
CLIENT_SECRET = os.environ.get('CLIENT_SECRET')
AUTHORIZE_URL = "https://applications.frame.io/oauth2/auth"
TOKEN_URL = "https://applications.frame.io/oauth2/token"
# The scopes you've chosen for your app, space-delimited
SCOPE = "offline account.read asset.read"
# The callback URI for your app
REDIRECT_URI = "https://yourapp.domain/callback"Invoking the auth server
First, your application will need to call the Frame.io auth server, which will then redirect the user to a login page.
import uuid
from urllib.parse import urlencode
def create_auth_url():
credentials = {
'response_type': 'code',
'redirect_uri': REDIRECT_URI,
'client_id': CLIENT_ID,
'scope': SCOPE,
'state': str(uuid.uuid4())
}
url = (AUTHORIZE_URL + "?" + urlencode(credentials))
return urlThe callback
The auth server will then make a GET request to your REDIRECT_URI, which in turn will need to call the TOKEN_URL. This callback will be slightly different depending on whether or not your application is configured to use PKCE.
Without PKCE
If you're not using PKCE, your callback must include an Authorization header that includes your CLIENT_ID and CLIENT_SECRET.
def callback():
state = request.args.get('state')
scope = request.args.get('scope')
code = request.args.get('code')
error = request.args.get('error')
if error:
return "Error: " + error
# Set up for client authorization and set up the data you need to send.
client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET)
post_data = {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI,
"state": state,
"scope": SCOPE
}
# Send a POST request with the data you need to receive an access token.
# If everything goes well, it will be returned to you and you can use it with
# Frame.io.
response = requests.post(TOKEN_URL, auth=client_auth, data=post_data)
return response.textWith PKCE
If you're using PKCE, your callback must not include an Authorization header, but must include your CLIENT_ID in its POST request body when calling back to the TOKEN_URL.
def callback():
state = request.args.get('state')
scope = request.args.get('scope')
code = request.args.get('code')
error = request.args.get('error')
if error:
return "Error: " + error
# If using PKCE, you must include the CLIENT_ID in your request body
post_data = {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI,
"state": state,
"scope": SCOPE
"client_id": CLIENT_ID
}
# Send a POST request with the data you need to receive an access token.
# If everything goes well, it will be returned to you and you can use it with
# Frame.io
# If using PKCE, use the below request with no auth
response = requests.post(TOKEN_URL, data=post_data)
return response.textSuccessful response
If your callback is successful, you will receive a JSON response that looks like this:
{
"access_token":"BEARER_TOKEN",
"expires_in":3600,
"refresh_token":"REFRESH_TOKEN",
"scope":"account.read offline",
"token_type":"bearer"
}You can now use the access_token to make API calls to Frame.io on the logged-in user's behalf, and the refresh_token to request a new access_token after this token expires.