cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
Want to learn some quick and useful tips to make your day easier? Check out how Calvin uses Replay to get feedback from other teams at Dropbox here.

Dropbox API Support & Feedback

Find help with the Dropbox API from other developers.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

dropbox.exceptions.AuthError: AuthError('adf0b24714c641a5b3dfcd68573db5e4', AuthError('invalid_acces

dropbox.exceptions.AuthError: AuthError('adf0b24714c641a5b3dfcd68573db5e4', AuthError('invalid_acces

af11
Explorer | Level 4

I am working on a notification app linked to a business account via a webhook to get notified when any of the team members edit files in certain folders.  Attached below is the code, deployed on Heroku

 

 

import os
from dotenv import load_dotenv
from dropbox import Dropbox
from flask import Flask, render_template, session, Response, request, abort
import hmac
from hashlib import sha256
import json
import threading
import sendgrid
from sendgrid.helpers.mail import *
import redis
from dropbox.files import DeletedMetadata, FolderMetadata, WriteMode, FileMetadata
from dropbox.users import FullAccount

load_dotenv()

ACCESS_TOKEN = os.environ.get('ACCESS_TOKEN')
APP_KEY = os.environ.get('APP_KEY')
APP_SECRET = os.environ.get('APP_SECRET')
EMAIL_USERNAME = os.environ.get('EMAIL_USERNAME')
redis_url = os.environ.get('REDISTOGO_URL')
redis_client = redis.from_url(redis_url, decode_responses=True)
main_folder = 'Career Consulting Real'
subfolder_list = ['eng101', "mat101"]

app = Flask(__name__)
app.secret_key = os.environ.get('FLASK_SECRET_KEY')

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/login')
def login():
    return render_template('done.html')

@app.route('/webhook', methods=['GET'])
def challenge():
    resp = Response(request.args.get('challenge'))
    resp.headers['Content-Type'] = 'text/plain'
    resp.headers['X-Content-Type-Options'] = 'nosniff'
    print(resp)
    return resp

@app.route('/webhook', methods=['POST'])
def webhook():
    # '''Receive a list of changed user IDs from Dropbox and process each.'''

    #make sure this is a valid request from Dropbox
    signature = request.headers.get('X-Dropbox-Signature')
    key = bytes(APP_SECRET, encoding="ascii")
    if not hmac.compare_digest(signature, hmac.new(key, request.data, sha256).hexdigest()):
        abort(403)

    #print(json.loads(request.data))
    #print(json.loads(request.data)['delta']['teams']['dbtid:AAB_JmVTCr29MzCFLUPWLOP3ch-RdRv3Quo'])
    for account in json.loads(request.data)['delta']['teams']['dbtid:AAB_JmVTCr29MzCFLUPWLOP3ch-RdRv3Quo']:
        # We need to respond quickly to the webhook request, so we do the
        # actual work in a separate thread. For more robustness, it's a
        # good idea to add the work to a reliable queue and process the queue
        # in a worker process.
        threading.Thread(target=process_user, args=(account,)).start()

    return ''

def filter_notifications(entry):
    file_path_split = entry.path_display.replace(' ', '').lower().split('/')
    if file_path_split[1] == main_folder.replace(' ', '').lower():
        for subfolder in subfolder_list:
            if subfolder in file_path_split[2]:
                return True

def send_notification(message):

    send_grid_key = os.environ.get('SEND_GRID')
    sg = sendgrid.SendGridAPIClient(api_key=send_grid_key)
    from_email = Email(EMAIL_USERNAME)
    to_email = To("cdropboxchanges@gmail.com")
    subject = "A change has been made"
    content = Content("text/plain", message)
    mail = Mail(from_email, to_email, subject, content)
    response = sg.client.mail.send.post(request_body=mail.get())

def process_user(account):

    # cursor for the user (None the first time)
    cursor = redis_client.hget('cursors', account)

    dbx = Dropbox(ACCESS_TOKEN)

    has_more = True

    while has_more:
        if cursor is None:
            result = dbx.files_list_folder(path='', recursive=True, include_non_downloadable_files=True)
        else:
            result = dbx.files_list_folder_continue(cursor)

        for entry in result.entries:
            if filter_notifications(entry):
                if isinstance(entry, FileMetadata):
                    send_notification('File Metadat')
                elif isinstance(entry, DeletedMetadata):
                    send_notification('DeletedMetadata')
                elif isinstance(entry, FolderMetadata):
                    send_notification('Folder Metadata')
                else:
                    send_notification('Something happened, not sure what...')

        # Update cursor
        cursor = result.cursor
        redis_client.hset('cursors', account, cursor)

        # Repeat only if there's more to do
        has_more = result.has_more


if __name__ == '__main__':
    app.run(debug=True)

 

 

When I run the code, I get the following error: 

 dropbox.exceptions.AuthError: AuthError('adf0b24714c641a5b3dfcd68573db5e4', AuthError('invalid_access_token', None))

However, the access token I am passing in is straight from the app on Dropbox.

Can you please advise what could be the problem that is causing this error?

Thank you

1 Reply 1

Greg-DB
Dropbox Staff
By default, Dropbox API access tokens for your app(s) don't become invalid and yield 'invalid_access_token' by themselves, but there a number of different ways that a Dropbox API access token can become invalid, including:
 
Please review the above possibilities for information on why the access token may be invalid. If the Dropbox API isn't behaving as expected, feel free to contact support by opening an API ticket.
Need more support?
Who's talking

Top contributors to this post

  • User avatar
    Greg-DB Dropbox Staff
What do Dropbox user levels mean?