<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic dropbox.exceptions.AuthError: AuthError('adf0b24714c641a5b3dfcd68573db5e4', AuthError('invalid_acces in Dropbox API Support &amp; Feedback</title>
    <link>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/dropbox-exceptions-AuthError-AuthError/m-p/576929#M26908</link>
    <description>&lt;P&gt;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.&amp;nbsp; Attached below is the code, deployed on Heroku&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;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)
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When I run the code, I get the following error:&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt; dropbox.exceptions.AuthError: AuthError('adf0b24714c641a5b3dfcd68573db5e4', AuthError('invalid_access_token', None))&lt;/PRE&gt;
&lt;P&gt;However, the access token I am passing in is straight from the app on Dropbox.&lt;/P&gt;
&lt;P&gt;Can you please advise what could be the problem that is causing this error?&lt;/P&gt;
&lt;P&gt;Thank you&lt;/P&gt;</description>
    <pubDate>Wed, 27 Apr 2022 12:52:59 GMT</pubDate>
    <dc:creator>af11</dc:creator>
    <dc:date>2022-04-27T12:52:59Z</dc:date>
    <item>
      <title>dropbox.exceptions.AuthError: AuthError('adf0b24714c641a5b3dfcd68573db5e4', AuthError('invalid_acces</title>
      <link>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/dropbox-exceptions-AuthError-AuthError/m-p/576929#M26908</link>
      <description>&lt;P&gt;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.&amp;nbsp; Attached below is the code, deployed on Heroku&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;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)
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When I run the code, I get the following error:&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt; dropbox.exceptions.AuthError: AuthError('adf0b24714c641a5b3dfcd68573db5e4', AuthError('invalid_access_token', None))&lt;/PRE&gt;
&lt;P&gt;However, the access token I am passing in is straight from the app on Dropbox.&lt;/P&gt;
&lt;P&gt;Can you please advise what could be the problem that is causing this error?&lt;/P&gt;
&lt;P&gt;Thank you&lt;/P&gt;</description>
      <pubDate>Wed, 27 Apr 2022 12:52:59 GMT</pubDate>
      <guid>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/dropbox-exceptions-AuthError-AuthError/m-p/576929#M26908</guid>
      <dc:creator>af11</dc:creator>
      <dc:date>2022-04-27T12:52:59Z</dc:date>
    </item>
    <item>
      <title>Re: dropbox.exceptions.AuthError: AuthError('adf0b24714c641a5b3dfcd68573db5e4', AuthError('invalid_a</title>
      <link>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/dropbox-exceptions-AuthError-AuthError/m-p/576996#M26915</link>
      <description>&lt;DIV&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;By default, Dropbox API access tokens for your app(s) don't become invalid and yield&lt;/SPAN&gt; &lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e h-apos"&gt;'invalid_access_token'&lt;/SPAN&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt; by themselves, but there a number of different ways that a Dropbox API access token can become invalid, including:&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;UL class="listtype-bullet listindent1 list-bullet1"&gt;
&lt;LI&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;the user or team admin can revoke all access tokens for an app by unlinking it on any of the following Dropbox web pages:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;UL class="listtype-bullet listindent2 list-bullet2"&gt;
&lt;LI&gt;&lt;SPAN class="attrlink url author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;&lt;A class="attrlink" href="https://www.dropbox.com/account/connected_apps" target="_blank" rel="noreferrer nofollow noopener" data-target-href="https://www.dropbox.com/account/connected_apps"&gt;the Connected apps page&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN class="attrlink url author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;&lt;A class="attrlink" href="https://www.dropbox.com/security_checkup" target="_blank" rel="noreferrer nofollow noopener" data-target-href="https://www.dropbox.com/security_checkup"&gt;the Security checkup page&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN class="attrlink url author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;&lt;A class="attrlink" href="https://www.dropbox.com/team/admin/settings/team_apps" target="_blank" rel="noreferrer nofollow noopener" data-target-href="https://www.dropbox.com/team/admin/settings/team_apps"&gt;the Team apps page&lt;/A&gt;&lt;/SPAN&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt; on &lt;/SPAN&gt;&lt;SPAN class="attrlink url author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;&lt;A class="attrlink" href="https://www.dropbox.com/team/admin/settings?role=work" target="_blank" rel="noreferrer nofollow noopener" data-target-href="https://www.dropbox.com/team/admin/settings?role=work"&gt;the Settings section of Business Admin console&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;the team member’s page on &lt;/SPAN&gt;&lt;SPAN class="attrlink url author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;&lt;A class="attrlink" href="https://www.dropbox.com/team/admin/members?role=work" target="_blank" rel="noreferrer nofollow noopener" data-target-href="https://www.dropbox.com/team/admin/members?role=work"&gt;the Members section of the Business Admin console&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;any client with the access token can revoke the access token by calling &lt;/SPAN&gt;&lt;SPAN class="attrlink url author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;&lt;A class="attrlink" href="https://www.dropbox.com/developers/documentation/http/documentation#auth-token-revoke" target="_blank" rel="noreferrer nofollow noopener" data-target-href="https://www.dropbox.com/developers/documentation/http/documentation#auth-token-revoke"&gt;/2/auth/token/revoke&lt;/A&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN class="attrlink url author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;&lt;A class="attrlink" href="https://help.github.com/en/github/administering-a-repository/about-token-scanning" target="_blank" rel="noreferrer nofollow noopener" data-target-href="https://help.github.com/en/github/administering-a-repository/about-token-scanning"&gt;the GitHub-Dropbox token scanning partnership&lt;/A&gt;&lt;/SPAN&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt; can revoke access tokens found publicly posted on GitHub&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;if the app uses the&lt;/SPAN&gt; &lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e h-quot"&gt;"app&lt;/SPAN&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt; folder" access type, the access token can effectively be disabled by deleting the app folder itself in the Dropbox account, via &lt;/SPAN&gt;&lt;SPAN class="attrlink url author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;&lt;A class="attrlink" href="https://www.dropbox.com/home" target="_blank" rel="noreferrer nofollow noopener" data-target-href="https://www.dropbox.com/home"&gt;the Dropbox website&lt;/A&gt;&lt;/SPAN&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt; or any client&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;the app can be disabled&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;the account that owns the app can be disabled&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;the connected account/team can be disabled&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;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 &lt;/SPAN&gt;&lt;SPAN class="attrlink url author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;&lt;A class="attrlink" href="https://www.dropbox.com/developers/contact" target="_blank" rel="noreferrer nofollow noopener" data-target-href="https://www.dropbox.com/developers/contact"&gt;opening an API ticket&lt;/A&gt;&lt;/SPAN&gt;&lt;SPAN class=" author-d-42z69zz85zx9z84zz79zvz66zz71z4yz65zz67znhz79zc7fz89zz67z5z82zikmz70zz75ztz72zz83zuyz68zz122zz69z9z122zz122zv35e"&gt;.&lt;/SPAN&gt;&lt;/DIV&gt;</description>
      <pubDate>Thu, 10 Feb 2022 16:22:02 GMT</pubDate>
      <guid>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/dropbox-exceptions-AuthError-AuthError/m-p/576996#M26915</guid>
      <dc:creator>Greg-DB</dc:creator>
      <dc:date>2022-02-10T16:22:02Z</dc:date>
    </item>
  </channel>
</rss>

