Closed ericasaw closed 2 years ago
Hi @ericasaw, ok let me explain what might have gone wrong in all cases:
Have you went through all steps from this page? Especially have you done step: App Authorization? JWT requires submitting your application and your Box enterprise admin approval. Without your app being approved you cannot use JWT auth.
Also the easiest and recommended way to use JWT auth is to just pass path to your config file as the only parameter. The class will extract all required fields. So the code that it is recommended to use will be:
auth = JWTAuth.from_settings_file('config.json') #generated from the box developer website
client = Client(auth)
user = client.user(user_id='#######') #my user ID
user_client = client.as_user(user)
Same issue as with JWT. Have you fulfil all Prerequisites described here? CCG also requires approving your application by the admin.
This is the only method which does not require admin approval (except developer token), but will require from you to press "Grant Access" button each time you want to use it. All required steps are described here: Overview. The redirect step depends on a framework you use. Some time ago I wrote a small flask app, which does Oauth authentication and list all files in your root folder. You may find it useful:
from 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)
To make it work you have to set http://localhost:5000/oauth2callback
value in the Dev Console as described here: Redirect URI
Also: Check what type of authentication have you chosen while creating your app. You should use the authentication type you selected. See: App creation steps.
To summarise: think which auth type do you want to use, create an app with authentication type you have chosen and try to go through all steps described in developer guides (https://developer.box.com/guides/authentication/). If this answer won't solve all your concerns, don't hesitate to ask again. Best, @lukaszsocha2
Hi Lukas, Thanks for the detailed response! For both the JWT and the CCG I have completed the set up for the app as described in the Box API documentation, obtained the app authorization, and it was approved by my organization, but I still cannot get either method to work. Your script for the Oauth2.0 is very helpful, I will try implementing the method and get back to you on if it works for me!
Hi @ericasaw, do you remember which authentication type have you chosen during app creation? If it was OAuth 2.0 then JWT and CCG won't work for you. @lukaszsocha2
Hi Lukas, The original Box CLI app I had set up is configured for OAuth 2.0 (just by following the directions here). The trial application I created & had approved was for the JWT Auth (by following the directions here). I don't think I ever generated one for the CCG which is probably why it has never worked for me. It's good to know that the app you make can only have one authentication method (other than developer). This will help me for troubleshooting!
Hi @ericasaw, have you managed to authenticate using any other method than developer token?
Hi Lukas, I am still having a bit of difficulty with the OAuth 2.0 example you have above. I've changed the Redirect URI like you've mentioned, but when I put the http://127.0.0.1:5000/ url in chrome, after clicking the grant access button I get an "Access to localhost was denied HTTP ERROR 403" message. I think this might have to do with MacOS using port 5000 regularly so I cannot use it for my application, do you know how I can change the port the flask runs on?
See example here https://www.codegrepper.com/code-examples/python/change+port+flask
Hi Lukas, Is it normal for the localhost website to have a continuous loading wheel after granting access or is something else meant to happen?
Hi Lukas, Maybe I should provide a more detailed example of what I'm trying to accomplish here is a script that I am testing with:
from boxsdk import OAuth2, Client
import _pickle as pickle
import glob
from flask import Flask, request, redirect
app = Flask(__name__)
auth = OAuth2( client_id='detzn3cmpd7wgjl9mk84af1mjerpnra1',
client_secret='9fyDak6LFP17i8aOkbESlF7olRXOyWfz')
@app.route("/")
def get_auth():
auth_url, csrf_token = auth.get_authorization_url('http://localhost:3000/oauth2callback')
return redirect(auth_url, code=302)
@app.route("/oauth2callback")
def callback():
auth.authenticate(request.args.get("code"))
client = Client(auth)
RRISA_items = client.folder(folder_id='163358064246').get_items()
general_folders = []
for item in RRISA_items:
#get the IDS for indata, outdata, and recipe
general_folders.append(client.folder(folder_id=item.id).get_items())
written = glob.glob("recipe_box_ids/*")
w_fn = [fn.split('_')[0] for fn in written[:-1]]
#in indata, outdata, or recipe get the date folder IDS
for file in general_folders[2]:
ID_organize = {}
if (file.name).split('.')[0] not in w_fn:
#set the key equal to the download link for the file so we dont even have to mess with the IDs, make the link perm
ID_organize[str(file.name)] = client.file(file.id).get_shared_link_download_url(access='open', unshared_at = None)
#dump the dictionary with filename and file download link
pickle.dump(ID_organize, open(f"recipe_box_ids/{(file.name).split('.')[0]}_recipe.pkl", "wb"))
I get the following error "TypeError: The view function for 'callback' did not return a valid response. The function either returned None or ended without a return statement." because I don't have a return for the callback function, but I don't really need one for my specific application. Or did I build the function wrong? should I just be returning the client to the script and then generating the permanent download links?
@ericasaw So maybe can you just make callback() return empty string? I also don't understand why don't you try to create new app with CCG or JWT auth method and get your app authenticated. The usage of these auth methods will be much easier than OAuth2 and won't require your interaction during authentication process.
Hi Lukas, Okay I can try with the other authentication methods, I was just trying the OAuth since I had an app for it and it takes my organization weeks sometimes to approve other apps. The app that I had created for JWT Auth is authorized by my organization, but still does not work with the example code you have provided, still with the "Code: access_denied_insufficient_permissions" error. I'm not sure how else to fix this particular issue for JWT Auth as I set everything up following the directions from the same link you recommended. Does the app have to be re-authenticated for each public/private key pair generated?
@ericasaw but also did you try to make callback() return empty string?
Can you tell me on which line does your code throws exception with JWT? Is it client = Client(auth)
or user_client = client.as_user(user)
?
It is only when I try to use the user_client that that specific error is thrown. If I just try to use the client I get a different error that says the ID (corresponding to the folder that holds all the data) doesn't exist. Haven't tried to make callback return an empty string yet.
Ok so I know why JWT didn't work: You must have as-user headers enabled: Go to Configuration of your app in Dev Console and then select checkbox Make API calls using as-user header
.
Then save changes and submit your app for reapproval. This should help ;)
Okay! App is resubmitted for approval, I'll update you when it's approved.
Hi Lukas! I had the app reauthorized (for JWT) last night. I downloaded the .json file again, but it doesn't include my public/private key. Do I need to generate a new one and have that .json file read in instead? I'm not sure if the app needs to be reauthorized each time I generate a key pair.
I tried copying the old key pair into the new .json file and I still get the same "Code: access_denied_insufficient_permissions" error from before even with the make API calls using the as-user header checked in the box developer app.
Hi, I checked and no reauthentication is needed when you generate new keypair. So I suggest you to:
Generate a Public/Private Keypair
Let me know if it worked. Best, @lukaszsocha2
Hi Lukas, Unfortunately even with a new key pair and app authorization I still get the "Code: access_denied_insufficient_permissions" error.
My CCG app was approved as well so I tried authenticating using the information from that app with:
auth = CCGAuth(
client_id="my_client_id",
client_secret="my_client_secret",
user="my_user")
client = Client(auth)
but I get the following error:
"GET https://api.box.com/2.0/folders/163358064246/items?offset=0" 500 182
{'Date': 'Fri, 08 Jul 2022 17:06:54 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'x-envoy-upstream-service-time': '359', 'box-request-id': '0a1505c8b99a802e28a0ec8ab3f44bdea', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000'}
{'code': '---rror',
'help_url': 'http://developers.box.com/docs/#errors',
'message': 'Internal Server Error',
'request_id': 'e4r1xah400ls9yqf',
'status': 500,
'type': 'error'}
"GET https://api.box.com/2.0/folders/163358064246/items?offset=0" 500 182
{'Date': 'Fri, 08 Jul 2022 17:06:56 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'x-envoy-upstream-service-time': '75', 'box-request-id': '1446244467da6adb295013dbf22e6ff7e', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000'}
{'code': '---rror',
'help_url': 'http://developers.box.com/docs/#errors',
'message': 'Internal Server Error',
'request_id': '1katv8h400lt772u',
'status': 500,
'type': 'error'}
"GET https://api.box.com/2.0/folders/163358064246/items?offset=0" 500 182
{'Date': 'Fri, 08 Jul 2022 17:06:58 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'x-envoy-upstream-service-time': '77', 'box-request-id': '020b0186fcda7cbc17fc6b3dbf2d442c4', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000'}
{'code': '---rror',
'help_url': 'http://developers.box.com/docs/#errors',
'message': 'Internal Server Error',
'request_id': 'jd6m1ih400luj7ow',
'status': 500,
'type': 'error'}
"GET https://api.box.com/2.0/folders/163358064246/items?offset=0" 500 182
{'Date': 'Fri, 08 Jul 2022 17:07:01 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'x-envoy-upstream-service-time': '87', 'box-request-id': '086f4acaca05b68b9eb16fa1d5d887418', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000'}
{'code': '---rror',
'help_url': 'http://developers.box.com/docs/#errors',
'message': 'Internal Server Error',
'request_id': 'gzwjw4h400lwp5mj',
'status': 500,
'type': 'error'}
"GET https://api.box.com/2.0/folders/163358064246/items?offset=0" 500 182
{'Date': 'Fri, 08 Jul 2022 17:07:09 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'x-envoy-upstream-service-time': '80', 'box-request-id': '06e68760d7f669ae481ee6c4c70b1e570', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000'}
{'code': '---rror',
'help_url': 'http://developers.box.com/docs/#errors',
'message': 'Internal Server Error',
'request_id': 'zdyuyuh400m18c3b',
'status': 500,
'type': 'error'}
"GET https://api.box.com/2.0/folders/163358064246/items?offset=0" 500 182
{'Date': 'Fri, 08 Jul 2022 17:07:27 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'x-envoy-upstream-service-time': '103', 'box-request-id': '0c1b83bedcdb410fc9b403e6ce2c121c8', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000'}
{'code': '---rror',
'help_url': 'http://developers.box.com/docs/#errors',
'message': 'Internal Server Error',
'request_id': '2ol1k6h400mcr40f',
'status': 500,
'type': 'error'}
Traceback (most recent call last):
File "Recipe_IDs.py", line 22, in <module>
for item in RRISA_items:
File "/Users/ericasaw/opt/miniconda3/envs/photometry/lib/python3.6/site-packages/boxsdk/pagination/box_object_collection.py", line 81, in next
return next(self._all_items)
File "/Users/ericasaw/opt/miniconda3/envs/photometry/lib/python3.6/site-packages/boxsdk/pagination/box_object_collection.py", line 87, in _items_generator
response_object = self._load_next_page()
File "/Users/ericasaw/opt/miniconda3/envs/photometry/lib/python3.6/site-packages/boxsdk/pagination/box_object_collection.py", line 124, in _load_next_page
box_response = self._session.get(self._url, params=params)
File "/Users/ericasaw/opt/miniconda3/envs/photometry/lib/python3.6/site-packages/boxsdk/session/session.py", line 90, in get
return self.request('GET', url, **kwargs)
File "/Users/ericasaw/opt/miniconda3/envs/photometry/lib/python3.6/site-packages/boxsdk/session/session.py", line 134, in request
response = self._prepare_and_send_request(method, url, **kwargs)
File "/Users/ericasaw/opt/miniconda3/envs/photometry/lib/python3.6/site-packages/boxsdk/session/session.py", line 337, in _prepare_and_send_request
self._raise_on_unsuccessful_request(network_response, request)
File "/Users/ericasaw/opt/miniconda3/envs/photometry/lib/python3.6/site-packages/boxsdk/session/session.py", line 273, in _raise_on_unsuccessful_request
network_response=network_response
boxsdk.exception.BoxAPIException: Message: Internal Server Error
Status: 500
Code: internal_server_error
Request ID: 2ol1k6h400mcr40f
Headers: {'Date': 'Fri, 08 Jul 2022 17:07:27 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'x-envoy-upstream-service-time': '103', 'box-request-id': '0c1b83bedcdb410fc9b403e6ce2c121c8', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000'}
URL: https://api.box.com/2.0/folders/163358064246/items
Method: GET
Context Info: None
I'm not sure what an internal service error indicates, do you have any ideas?
ericasaw, the "Internal Server Error" is a different issue than the auth issue in the issue description. However, I'd like to state that we are also receiving this error. There are some intermittent issues going on with the Box servers right now if I had to guess.
File "boxsdk/pagination/box_object_collection.py", line 81, in next
File "boxsdk/pagination/box_object_collection.py", line 87, in _items_generator
File "boxsdk/pagination/box_object_collection.py", line 124, in _load_next_page
File "boxsdk/session/session.py", line 90, in get
File "boxsdk/session/session.py", line 134, in request
File "boxsdk/session/session.py", line 337, in _prepare_and_send_request
File "boxsdk/session/session.py", line 264, in _raise_on_unsuccessful_request
boxsdk.exception.BoxAPIException: Message: Internal Server Error
Status: 500
Code: internal_server_error
Request ID: 3llc7h400r53ja0
Headers: {'Date': 'Fri, 08 Jul 2022 17:12:03 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'x-envoy-upstream-service-time': '78', 'box-request-id': '0de4280d7c30a4c605598d8e59a14cde7', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000'}
URL: https://api.box.com/2.0/search
Method: GET
Context Info: None
Okay good to know! I wasn't sure if it was related to me setting up my app wrong, I might just try to run the CCG Auth again tomorrow to see if things are fixed.
Okay the CCG Authentication method seems to work this morning! Thank you all so much for your help. I still cannot get the JWT Auth to work, maybe it is a university limitation? I am open to trouble shooting that further since it seems like the preferred authentication method.
Hi, @ericasaw @lukaszsocha2 I'm facing the same problem again and again. Can you help me with that? I used JWT but getting permission denied errors and with CCG I'm getting Grant credentials are invalid.
hi @kailashlimba1997 ,
To make JWT and CCG apps works, you need to authorize your app.
To check if you did it, please open the developer console, select your application, and then go to the Authorization tab.
Your app should have Authorization Status: Authorized
and Enabled Status: Enabled
.
If your app is not yet authorized, click Review and Submit to ask the Box Enterprise administrator for approval. Read this for more information: https://developer.box.com/guides/authentication/jwt/jwt-setup/#app-authorization.
Please let me know about the result @arjankowski
Hi, @arjankowski Thanks for replying. I've authorized the application and enable status is also enabled. Still, I'm facing this issue.
Hi @kailashlimba1997, I generated a new app in the box developer console specifically for the CCG method. Under the configuration tab, I selected the app + enterprise access option for the app access level. Under application scopes I checked the "write all files and folders stored in Box", "manage users", "manage groups", and "manage enterprise properties" boxes. I didn't check anything else. After doing all of that, I then clicked the review and submit button under the authorization tab. It's important to note that nothing will work until the app has been approved by whatever admin is in control of the organization's Box settings. After the app was approved I used the following lines in python to generate the client:
from boxsdk import Client, CCGAuth
auth = CCGAuth(
client_id="", #your client ID in the box developer app
client_secret="", #your client secret in the box developer app
user="" #your user ID in your box developer app
)
client = Client(auth)
I hope that works! I was never able to figure out the JWT Auth and the Box team has not been very responsive when I reached out through the support channels so I just gave up trying to use that method.
Hi @ericasaw @arjankowski After writing the below code
from boxsdk import Client, CCGAuth
auth = CCGAuth( client_id="", #your client ID in the box developer app client_secret="", #your client secret in the box developer app user="" #your user ID in your box developer app )
client = Client(auth)
events = client.events().generate_events_with_long_polling() print(events) for event in events: print(f'Got {event} event')
I'm getting this error, message Message: Grant credentials are invalid
HI @kailashlimba1997, Did you add your client ID, client secret, and user ID from your CCG Auth application (between the "" placeholders in the code I wrote above)?
Yes, I write in inverted commas. Can I have your contact and discuss this issue on zoom/meet?
@kailashlimba1997 since I am not a box developer I am not really comfortable meeting or spending a ton of time helping with resolving issues like these. Hopefully one of the developers in this thread can help!
Hi @antusus @mhagmajer @cristynkells @lukaszsocha2, can anyone help me with the above issue?
@kailashlimba1997 Did you manage to resolve this issue? If not please contact me on email so we may arrange some call.
No, the error is still not resolved. I've emailed you on ajankowski@box.com for a call.
If you haven't received the email, please ping me at kailash@nroadcorp.com whenever you get time.
Thanks, @arjankowski. The CCG credential (for the user) worked for me.
Description of the Issue
I've been having issues with Box authentication through Python since I started using it. I am trying to use the Box Python SDK to generate permanent download links for thousands of files. I have figured out how to generate all of the links, but unfortunately when I first generated them they were not permanent. I now need to go and update all of the links, but the first time I did this, due to all of my authentication issues, I put in a developer token each hour for many many hours (weeks of time). I don't want to have to do this ever again so I am hoping to solve the authentication issue.
I have tried all of the different authentication methods recommended in the documentation. However, the only method that is successful for me is using the developer token. Here are some of the problems I ran into using various authentication methods:
I’m sorry if this is generally straight forward for other developers to figure out, but I am just a grad student who isn’t really familiar with this type of developer programming and I find the API for all of the Box ecosystem pretty opaque.
I should also note that I have tried all of the above authentication methods with both the initial Box CLI app and another trial app that I generated which allows me to create the downloadable .json files with public/private key pairs.
Steps to Reproduce
All of the lines of code I tried for authorization I directly copied from the SDK auth wiki page and inserted my own user ID, .json file, etc., generated using the Box Developer. This leads me to believe that this might be an issue with setting up the Box Developer side of things--unless that code only works in very specific cases, but if so, then more detailed instructions should be added to the wiki for how to set that up properly so that the sample code will work.
Expected Behavior
Successful authentication that did not require a development token to be put in each hour.
Versions Used
Python SDK: 3.3.0 Python: 3.6.13