Python boxsdk error: Message: b'{"error":"invalid_grant","error_description":"The authorization code
I have a flask web application (app.py) running on amazon ec2 server to which my users authenticate using their box login and password. The application also has a background cron process (cron.py) that needs to process the user's box files every few minutes.
The flask app is structured in such a way that as soon as the user authenticates and box.com redirects them back to the app home page, the access_token and refresh_token are stored in the database so that the cron can access it:
def store_the_tokens(access_token, refresh_token): print("store_the_tokens() called.") conn, cursor = db.opendb() cursor.execute("update box_tokens set auth_code=?, access_token=?, refresh_token=?", (session.get('auth_code'),access_token, refresh_token)) conn.commit() #session["message_info"] = "Authentication successful!" redirect(url_for("index")) oauth = OAuth2( client_id=config.client_id, client_secret=config.client_secret, store_tokens=store_the_tokens, )
Now, the trouble is that the cron is able to access the user files and folders, but only for one hour! After that, the following error message keeps coming:
Message: b'{"error":"invalid_grant","error_description":"The authorization code
Here is the cron.py code that tries to access the files through api. I also tried to handle the exception and get a new refresh_token by using the auth_code used during authentication, but in that case, I get the error: :"The authorization code has expired".
try: oauth = OAuth2( client_id=config.client_id, client_secret=config.client_secret, access_token = access_token, refresh_token = refresh_token, store_tokens = store_the_tokens, ) test_folder = client.folder(folder_id=0) except Exception as eouth: #print(str(eoauth)) #invalid grant, token expired log("Authentication error. Trying to refresh token.") access_token, refresh_token = oauth.authenticate(auth_code) oauth = OAuth2( client_id=config.client_id, client_secret=config.client_secret, access_token = access_token, store_tokens = store_the_tokens, )
What can I do so that the cron.py is able to function without the need for user re-authentication every hour?
-
Hi,
I have implemented similar process but i am storing tokens in file. You could implement something similar to read tokens from the DB as you are doing it to save it before.
May be the following code will help:
#ClientID and Client_Secret of the Box application obtained from Box dev console
CLIENT_ID = ''
CLIENT_SECRET = ''
#authentication function
def authenticateAdmin(oauth_class=OAuth2):
oauth = oauth_class(
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
store_tokens=save_tokens,
)#reading the tokens from the file
print("Reading tokens...")
os.system('cls')
at,rt = read_tokens_from_file()
oauth._access_token=at
oauth._refresh_token=rt
return oauth, at, rt#save token to a file
def save_tokens(access_token,refresh_token):
print("Refreshing tokens...")
target = open(Utility.get_path() +"\\config\\AdminToken.txt", 'w')
target.truncate()
tokens = access_token+'#'+refresh_token
target.write(tokens)
target.close()#reads tokens from a file
def read_tokens_from_file():
try:
with open(Utility.get_path() + "\\config\\AdminToken.txt", 'r') as f:
tokens=f.readline()
return tokens.split('#')
except:
print("Read token error:" + sys.exc_info())
return "null","null"as you can see there are function to save tokens (save_tokens()) and read tokens (read_tokens_from_file()). For instance i am saving it on config folder in AdminToken.txt in this instance. When saving tokens i am saving it separating tokens with # and returning the tuple (accesstoken,refreshtoken) .
You need similar process in your program that reads the tokens from the database and returns the at and rt. You don't need to worry about refreshing the tokens because once you instantiate the Client object after calling the authenticateAdmin function, it should refresh tokens automatically and save it to file.
when calling you just need to do:
oauth, _, _ = authenticateAdmin()
and instantiate with:
client = Client(oauth)
Let me know if this makes sense to you.
Thanks,
Bibek
-
Hi ,
Thanks for the script, but I am getting errors when I tried to execute the script. Let me tell you, I am MicroStrategy developer with very very limited knowledge of python. I want to get latest developer token every time script runs. Could you please help me with the corrected script so I don't need to access box.com to get latest version of the developer token.
I replaced CLIENT_ID and CLIENT_SECRET with the codes that I have received from box.com and when I tried to execute the script in paython (version: 2.7.13) I got an error at following code for indentation.
#reads tokens from a file
def read_tokens_from_file():
try:
with open(Utility.get_path() + "\\config\\AdminToken.txt", 'r') as f:
tokens=f.readline()
return tokens.split('#')
except:
print("Read token error:" + sys.exc_info())
return "null","null"I put a space in from of 'try' and 'except', but after that, I got an error and line 21 that the " 'return' outside function"
-
Hello,
Python is kind of sensitive with space and tab since there are no braces to enclose statements. Always use 4 spaces instead of tabs. that makes sure the code is properly formatted.Never mix tab and spaces. It's always a good practice to use spaces rather than tab.The code should look like this as shown here:#reads tokens from a file
def read_tokens_from_file():
try:
with open(Utility.get_path() + "\\config\\AdminToken.txt", 'r') as f:
tokens=f.readline()
return tokens.split('#')
except:
print("Read token error:" + sys.exc_info())
return "null","null"after the function definition 'def' there must be 4 spaces.and then try block. After try block another 4 spaces starting with 'with open' and ending with 'split'And then 'except' should be same level as 'try' and so on.if you follow these rules , the code should work just fine.thanks,Bibek -
Hi ,
Thanks for the reply. I am getting an error 'return' outside function at line number 28 of the code.
Could you please help me setup my app? I want to write a script to upload files from my local machine to BOX.com. I have created an account on box.com and followed instructions on the forum. My script to upload files is ready, and I will handover this code to project client and they will change client id, client secret and source path to upload files.
I have tried my best to implement a mechanism to refresh developer code, but nothing seems to work.
What exactly I need to do to automate this process? I have done following settings at box.com for the app.
1. Created a new app, name is "local_to_box"
2. from Authentication Method, I have selected "Standard OAuth 2.0 (User Authentication)"
3. from Developer Token, generated new token
4. from OAuth 2.0 Credentials, copied Client ID and Client Secret
5. Created OAuth 2.0 Redirect URI -----(This one is not used anywhere)
6. Application Scopes, everything is selected except, "Manage webhooks" and "Manage retention policies"
7. Wrote a script in python to upload files to box as below:
from boxsdk import Client
from boxsdk import OAuth2
oauth = OAuth2(
client_id='',
client_secret='',
access_token='',
)
client = Client(oauth)
root_folder = client.folder(folder_id='0')
shared_folder = client.folder(folder_id='')
uploaded_file = shared_folder.upload()
shared_link = shared_folder.get_shared_link()Now, I want to automate the process to getting a developer token every time the script runs. I am so confused and lost in all the tutorials present on the web, please help me implement this task.
Please sign in to leave a comment.
Comments
4 comments