I’ve been working on orchestrating an ETL load process from text files stored in the Cloud based file management tool, Box. Working with Python for the first time, I’ve found it to be an extremely flexible and straightforward language to use for such a task. There’s even a Box SDK that provides direct access to the bulk of the services needed to manage files in Box.
However, the Box API uses OAuth2.0 for authentication. Part of the process for permitting access to the Box API is to present the user with a web page, requesting permission to access the Box account. This does not fit well with an automated orchestration process.
I’ve written a small Python script that uses the keyring Python module as secure storage for the authorisation and refresh tokens required to connect to Box. Using the Box SDK, the tokens are refreshed automatically when they expire and you’ll see in the code below how I leverage the Box SDK to retain the tokens indefinitely in the secure key store. After “priming” the store with an initial set of tokens, the script will maintain the tokens automatically, provided it runs within the 60 day periods before the refresh token expires. Note that you’ll need to install the Box SDK and keyring Python modules, using PIP, prior to running the script. You’ll also need to specify the client_id and client_secret values from your Box Developer App in the script below.
"""An example of Box authentication with external store"""
from boxsdk import OAuth2
from boxsdk import Client
CLIENT_ID = 'specify your Box client_id here'
CLIENT_SECRET = 'specify your Box client_secret here'
"""Reads authorisation tokens from keyring"""
# Use keyring to read the tokens
auth_token = keyring.get_password('Box_Auth', 'email@example.com')
refresh_token = keyring.get_password('Box_Refresh', 'firstname.lastname@example.org')
return auth_token, refresh_token
def store_tokens(access_token, refresh_token):
"""Callback function when Box SDK refreshes tokens"""
# Use keyring to store the tokens
keyring.set_password('Box_Auth', 'email@example.com', access_token)
keyring.set_password('Box_Refresh', 'firstname.lastname@example.org', refresh_token)
"""Authentication against Box Example"""
# Retrieve tokens from secure store
access_token, refresh_token = read_tokens()
# Set up authorisation using the tokens we've retrieved
oauth = OAuth2(
# Create the SDK client
client = Client(oauth)
# Get current user details and display
current_user = client.user(user_id='me').get()
print('Box User:', current_user.name)
if __name__ == '__main__':
The key here, if you’ll pardon the pun, is in the store_tokens function. This is invoked automatically by the Box SDK, whenever it detects the expiration of the access token. The SDK will automatically request new tokens, using the active refresh token, and pass those two new token values back to the pass back function defined in the OAuth2 object initialisation. In the example above, we use the keyring module to store the values securely with the Windows Credential Manager. Before invoking any methods, we read these values and use them in the authentication constructor. Great stuff!