You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

免费版X开发者账号OAuth2.0删除推文报401未授权

问题:X Flask客户端删除推文时出现401未授权错误

背景信息

  • 使用免费版X(原Twitter)开发者账号。
  • 对OAuth相关内容感到困惑,.env文件中有以下键值对(已移除具体值),不清楚哪些是必需的:
API_KEY=
API_SECRET=
ACCESS_TOKEN=
ACCESS_TOKEN_SECRET=
CLIENT_ID=
CLIENT_SECRET=
BEARER_TOKEN=

问题描述

我写了一个极简的X Flask客户端示例,用Tweepy和OAuth2.0完成授权流程,能正常获取授权用户信息和最近10条推文,但点击"Delete"按钮删除推文时,会收到401未授权错误。该如何修改才能正常删除推文?

示例代码

from flask import Flask, jsonify, redirect, request, session, render_template_string
import tweepy
import os
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)
app.secret_key = os.getenv("FLASK_SECRET_KEY", "supersecretkey")

CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
CALLBACK_URL = "http://127.0.0.1:5000/callback"

oauth2_handler = tweepy.OAuth2UserHandler(
    client_id=CLIENT_ID,
    client_secret=CLIENT_SECRET,
    redirect_uri=CALLBACK_URL,
    scope=["tweet.read", "tweet.write", "users.read", "offline.access"],
)


@app.route("/", methods=["GET"])
def auth_redirect():
    try:
        auth_url = oauth2_handler.get_authorization_url()
        return redirect(auth_url)
    except Exception as e:
        return jsonify({"error": str(e)}), 500


@app.route("/callback", methods=["GET"])
def callback():
    try:
        code = request.args.get("code")
        if not code:
            return jsonify({"error": "Missing authorization code"}), 400

        access_token = oauth2_handler.fetch_token(request.url)
        session["access_token"] = access_token
        client = tweepy.Client(access_token["access_token"], wait_on_rate_limit=True)
        user = client.get_me(user_auth=False)
        tweets = client.get_users_tweets(id=user.data.id, max_results=10)
        tweet_list = (
            "".join(
                [
                    f"""
                <li>{tweet.text}
                    <form action="/delete_tweet/{tweet.id}" method="POST">
                        <button type="submit">Delete</button>
                    </form>
                </li>
                """
                    for tweet in (tweets.data or [])
                ]
            )
            or "<p>No tweets found.</p>"
        )

        return render_template_string(
            f"""
            <h1>Authorization Successful</h1>
            <h2>User Information</h2>
            <ul>
                <li><strong>ID:</strong> {user.data.id}</li>
                <li><strong>Username:</strong> {user.data.username}</li>
                <li><strong>Name:</strong> {user.data.name}</li>
            </ul>
            <h2>Last 10 Tweets</h2>
            <ul>{tweet_list}</ul>
            """
        )
    except Exception as e:
        return jsonify({"error": str(e)}), 500


@app.route("/delete_tweet/<string:tweet_id>", methods=["POST"])
def delete_tweet(tweet_id):
    try:
        access_token = session.get("access_token")
        if not access_token:
            return jsonify({"error": "Access token not found"}), 400

        client = tweepy.Client(
            consumer_key=CLIENT_ID,
            consumer_secret=CLIENT_SECRET,
            access_token=access_token["access_token"],
            wait_on_rate_limit=True,
        )
        response = client.delete_tweet(tweet_id)
        if response.data:
            return jsonify({"message": f"Tweet {tweet_id} deleted successfully"})
        return jsonify({"error": "Failed to delete tweet"}), 500
    except Exception as e:
        return jsonify({"error": str(e)}), 500


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

解决方案

1. 修正Tweepy Client初始化方式

在delete_tweet函数中,你错误混用了OAuth1和OAuth2的参数。对于OAuth2用户上下文授权,只需要传入access_token即可,不需要consumer_key和consumer_secret。修改后的客户端初始化代码:

client = tweepy.Client(
    access_token=access_token["access_token"],
    wait_on_rate_limit=True,
)

2. 确认权限范围有效性

虽然你已经添加了tweet.write权限,但要确保用户授权时确实同意了该权限。可以检查授权URL的scope参数是否正确传递,或者在开发者后台确认应用的权限设置。

3. .env文件必需参数说明

针对当前的OAuth2用户授权流程,你只需要以下参数:

  • CLIENT_ID:OAuth2客户端ID
  • CLIENT_SECRET:OAuth2客户端密钥
  • FLASK_SECRET_KEY:Flask会话加密密钥(可选,但建议设置)

其他参数(API_KEY、API_SECRET、ACCESS_TOKEN、ACCESS_TOKEN_SECRET、BEARER_TOKEN)用于OAuth1或应用上下文授权,当前流程不需要。

修改后的完整delete_tweet函数

@app.route("/delete_tweet/<string:tweet_id>", methods=["POST"])
def delete_tweet(tweet_id):
    try:
        access_token = session.get("access_token")
        if not access_token:
            return jsonify({"error": "Access token not found"}), 400

        client = tweepy.Client(
            access_token=access_token["access_token"],
            wait_on_rate_limit=True,
        )
        response = client.delete_tweet(tweet_id)
        if response.data:
            return jsonify({"message": f"Tweet {tweet_id} deleted successfully"})
        return jsonify({"error": "Failed to delete tweet"}), 500
    except Exception as e:
        return jsonify({"error": str(e)}), 500

内容的提问来源于stack exchange,提问作者geofflittle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:00:59