Skip to content

Instantly share code, notes, and snippets.

@jhoerr
Last active May 30, 2017 21:15
Show Gist options
  • Save jhoerr/c86df1e90c439e629d7e3a9b02260a1c to your computer and use it in GitHub Desktop.
Save jhoerr/c86df1e90c439e629d7e3a9b02260a1c to your computer and use it in GitHub Desktop.
JWT file access across enterprises
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[OAuth 2 with JSON Web Tokens](https://developer.box.com/docs/authentication#section-oauth-2-with-json-web-tokens) (hereafter \"JWT\") is the preferred authentication method for server-to-server Box applications. Unlike [3-legged OAuth2](https://developer.box.com/docs/authentication#section-oauth-2), JWT auth is designed to work well in multi-process/multi-node environments and does not require human interaction. However, the application permissions for JWT apps in Box are coarse-grained with respect to working with existing enterprise accounts. In order for the app to access any *one* enterprise account, it must be granted access to *all* enterprise accounts. Thus while JWT auth is ideal for enterprise application development, this limitation renders it unsuitable for all but the most trusted administrative applications. \n",
"\n",
"*We would love to see Box add a JWT configuration option to restrict the application's access to a single enterprise account.* This would enable the development of server-based applications within decentralized departments that wish to manage and maintain their data in Box.\n",
"\n",
"In discussing this limitation with the platform team there was some question of whether JWT apps with 'As User' functionality could access data within other enterprises. The following script demonstrates that an application created in one enterprise (\"Source\") can access files and folders in another enterprise (\"Target\") if the application is configured to act on behalf of users, and a collaboration exists between a folder in Target and a user in Source. \n",
"\n",
"The JWT application has been configured with the following properties. To the best of our knowledge this represents the least-privilege configuration for acting on behalf of any single enterprise user.\n",
"\n",
"* **Authentication Method**: OAuth 2.0 with JWT (Server Authentication)\n",
"* **Application Access**: Enterprise\n",
"* **Application Scopes**: \n",
" - Read and write all files and folders stored in Box\n",
" - Manage users\n",
"* **Advanced Features**:\n",
" - Perform Actions as Users\n",
" - Generate User Access Tokens\n",
" \n"
]
},
{
"cell_type": "code",
"execution_count": 113,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Create an authentication object using the JWT parameters for the application.\n",
"\n",
"from boxsdk import JWTAuth\n",
"\n",
"auth = JWTAuth(\n",
" client_id='CLIENT_ID',\n",
" client_secret='CLIENT_SECRET',\n",
" enterprise_id='ENTERPRISE_ID',\n",
" jwt_key_id='JWT_KEY_ID',\n",
" rsa_private_key_file_sys_path='/path/to/private_key.pem'\n",
")\n",
"\n",
"# Execute the JWT authentication process\n",
"\n",
"token = auth.authenticate_instance()"
]
},
{
"cell_type": "code",
"execution_count": 114,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# Create an authenticated client that can interact with the Box Content API\n",
"\n",
"from boxsdk import Client\n",
"\n",
"client = Client(auth)"
]
},
{
"cell_type": "code",
"execution_count": 115,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\"Source\" user: jhoerr@umail-test.iu.edu\n"
]
}
],
"source": [
"# Fetch a user representing the \"Source\" user with whom a collaboration exists on a folder in the \"Target\" enterprise.\n",
"\n",
"collaborator = client.user(user_id='USER_ID')\n",
"token = auth.authenticate_app_user(collaborator)\n",
"collaborator = client.user().get()\n",
"\n",
"print ('\"Source\" user: ' + current_user.login)"
]
},
{
"cell_type": "code",
"execution_count": 116,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\"Target\" collab folder: Cross Enterprise Collab Test\n",
"Owned by \"Target\" user: jhoerr@iu.edu\n"
]
}
],
"source": [
"# As the \"Source\" user, fetch the \"Target\" collaboration folder metadata\n",
"\n",
"collab_folder = client.folder(folder_id='COLLAB_FOLDER_ID').get()\n",
"\n",
"print ('\"Target\" collab folder: ' + collab_folder.name)\n",
"print ('Owned by \"Target\" user: ' + collab_folder.owned_by['login'])"
]
},
{
"cell_type": "code",
"execution_count": 117,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\"Target\" collab file: Cross Enterprise Collab Test/Secret PHI Data.pdf\n",
"Owned by \"Target\" user: jhoerr@iu.edu\n"
]
}
],
"source": [
"# Again as the \"Source\" user, fetch metadata for a file within the \"Target\" collaboration folder\n",
"\n",
"collab_file = client.file(file_id='COLLAB_FILE_ID').get()\n",
"\n",
"print ('\"Target\" collab file: ' + collab_file.parent['name'] + '/' + collab_file.name)\n",
"print ('Owned by \"Target\" user: ' + collab_file.owned_by['login'])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment