Get permanent authorization for python code using the BoxSDK
I have some python code which purpose is to, using the BoxSDK, download all files in a folder, generate some new Summary files and upload those files to a different output folder.
I’m accomplishing this with the methods:
client.folder(folder_id=input_folder_id).get_items()
client.folder(output_folder_id).upload_stream(t_buffer, f"{cliente.name}_Demo.csv")
on the Developer console I generated a Custom App, with “Server Authentication (with JWT)” as the Auth method, and after adding it to the admin console have been able to work with it perfectly fine using the developer tokens.
After testing and developing for a bit I finally got the code to where it needs to be, now its time to move away from the 1 hour developer tokens and get into a more permanent authorization.
But this is where my problems began as I have not been able to get this to work.
After reading the documentation on how to select an Auth method OAuth 2.0 seemed like the correct choice, as my box application will only have one user (Myself), and said user account is where I want to get and upload all my files from, this account is already set up with all my files so this seemed like the best choice.
After reading the Setup with OAuth 2.0 page i tried to get it working but I have not been able to do so.
I Created a new Custom App, this time with the “User Authentication (OAuth 2.0)” Auth method, added in my Redirect URI as http://localhost:5000/oauth2callback, gave the proper permissions under Application Scopes, and added it to the admin console, noting that this time it was added under “User Authentication Apps”.
Then I made a small Flask application:
from flask import Flask, request
import requests
URL="https://account.box.com/api/oauth2/authorize"
URL2 = "https://api.box.com/oauth2/token"
PARAMS = {
"client_id" : "_",
"redirect_uri": "http://localhost:5000/oauth2callback",
"response_type":"code"
}
data = {
"client_id" : "_",
"client_secret": "_",
"grant_type":"client_credentials"
}
app = Flask(__name__)
@app.route("/")
def getAuth():
r = requests.get(URL, params=PARAMS)
return r.text
@app.route("/oauth2callback")
def callback():
data["code"] = request.args.get("code")
r = requests.post(URL2, data=data)
print(data["code"])
return r.text
if __name__ == '__main__':
app.run(debug = True)
Just with the purpose of huosing the Box auth web portal and do the necesary steps to get my token.
I ran it , and everything seemed to work, the portal poped up, I logged in into my box account and clicked the button that said “Grant access to box”, and got a response with my AuthToken
but the token response I got seemed a bit weird.
"GET /oauth2callback?code=_ HTTP/1.1"
As it was missing a Refresh token, but I paid it no mind and just thought that I would deal with that latter.
But when I tried ruining the same code that was working with the developer tokens I could not get it to work, it kept telling me that It was not able to find the folder with the id I provided:
Context Info: {'errors': [{'reason': 'invalid_parameter', 'name': 'folder', 'message': "Invalid value 'd_'. 'folder' with value 'd_' not found"}]}
Its not and Auth error, but it seems like the hole OAuth 2.0 thing did not work.
I then thought maybe I was doing something wrong and decided to try using postman, as it has a easy to use OAuth 2.0 portal, but when I tried that, the Auth Failed, the postman console telling me
“Error: The client credentials are invalid”
What am I doing Wrong?
-
Hello,
I think your grant_type is wrong. It shouldn't say client_credentials... it should be authorization_code like it says on the reference page.... can you try this and report back?
Thanks,
Alex, Box Developer Advocate
-
Hi,
you tried to do many things manually, when SDK already provides everything. I rewrote your flask app to make it working. I added printing all items in root folder to make sure it works. If you have any questions or this code snippet won't work for you let us know.
Regardsfrom boxsdk import OAuth2, Client
from flask import Flask, request, redirect
app = Flask(__name__)
AUTH = OAuth2(
client_id='YOUR CLIENT ID',
client_secret='YOUR CLIENT SECRET'
)
@app.route("/")
def get_auth():
auth_url, csrf_token = AUTH.get_authorization_url('http://localhost:5000/oauth2callback')
return redirect(auth_url, code=302)
@app.route("/oauth2callback")
def callback():
AUTH.authenticate(request.args.get("code"))
client = Client(AUTH)
root_folder = client.root_folder()
list_of_items = ""
for item in root_folder.get_items():
list_of_items += f'{item.name}, '
return list_of_items
if __name__ == '__main__':
app.run(debug=True) -
Hi, thank you for replying, yes I actually got it working using the SDK, but I also ran into a bunch of issues after getting it to work.
The auth_url that I got only worked sometimes.
Sometimes I would get the correct windows asking me for access to my box Files but others I got redirected the box main portal with a “We could not find what you were looking for “ message.
But even the times when it worked properly it was not exactly what I was looking for, as it only provided an hour-long access token as opposed to what I am looking for which is a bit more of a permanent solution.
I tried getting the permanent access using a different method “RSA Keys”:
config = JWTAuth.from_settings_file('Path to my config json file')
client = Client(config)but as far as I can tell this only gives me access to the files that are on my (currently empty) Service account, not the ones in my main box account where everything is located.
What am I doing wrong? I just want my python code to be able to download and upload files to my box account, without me needing to give it permission each time, as the whole point of the code is for it to run without human intervention on a daily basis.
-
Hi,
The problem you are experiencing may be due to scope of the user model you are using. To clarify, Box has a couple different of user models that we use for different use cases:Service Account- A Service Account represents the application you created in a Box Enterprise. It can only be accessed programmatically similar to an App User, and a Service Account can also be used to create App User accounts. You can read more about Service Accounts here.
App User- An App User is very similar to a Service Account in that they are accessed programmatically, but you can create multiple App User accounts. You can read more about App Users here.
Managed Users- A managed user represents a member of an enterprise and has an associated login email/password. This is also your personal account. You can read more about managed accounts here.
To bring it all back, we have a few different user models here. The Service Account that you are authenticating as is separate from your personal user account. Each user account has its own separate files and folders. You can access content in another managed account in a few ways:- Taking actions on behalf of user by authenticating As-User
- Collaborating the account onto the content you want them to have access to.
I think in your case making calls as user will be the best fit. This is a code snippet you can use:
config = JWTAuth.from_settings_file('path to config')
client = Client(config)
user_to_impersonate = client.user(user_id='your managed user id')
user_client = client.as_user(user_to_impersonate)
for item in user_client.root_folder().get_items():
print(item)Remember to set proper scopes with Dev Console in Configuration tab:
- In section App Access Level - select App + Enterprise Access
- In section Advanced settings - check Make API calls using the as-user header checkbox
Don't forget to save and submit your settings in Authorization tab and then get an admin approval.
投稿コメントは受け付けていません。
コメント
4件のコメント