Flask对接Discord OAuth2仅部分账号登录成功报401 Unauthorized错误
问题原因
- API地址使用HTTP协议而非HTTPS:你定义的
discord_api_url为http://discord.com/api,Discord API强制要求HTTPS访问,HTTP请求会触发301重定向到HTTPS地址。requests默认跟随重定向时,跨HTTP/HTTPS协议会自动清除Authorization请求头,导致携带的token丢失,返回401。少数账号可用是因为这些账号历史授权过应用,Discord侧存在临时授权缓存,刚好通过了重定向后的校验。 - GET请求携带多余请求体:
/users/@me为GET接口,不需要提交请求体,你代码中调用该接口时传入了data={"scope": Oauth.scope}参数,Discord会将携带多余请求体的GET请求判定为非法请求,直接返回401。 - 权限范围缺失:获取用户基础信息(用户名、ID等)必须申请
identify权限,你当前仅配置了email权限,没有identify权限的账号调用/users/@me接口本身就没有访问权限。少数可用账号是历史授权过带identify的权限,Discord保留了授权记录所以临时可用。
修复方案
修改oauth.py代码
- 将
discord_api_url修改为HTTPS地址 - 调整scope添加
identify权限 - 移除
get_user_json方法中多余的data参数
修改后的oauth.py参考代码:
import requests class Oauth(object): client_id = ... # 替换为你的client_id client_secret = ... # 替换为你的client_secret scope = "identify email" redirect_uri = "http://192.168.35.5:8080/login" discord_login_url = f"https://discord.com/api/oauth2/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code&scope={scope}" discord_token_url = "https://discord.com/api/oauth2/token" discord_api_url = "https://discord.com/api" @staticmethod def get_access_token(code): payload = { "client_id": Oauth.client_id, "client_secret": Oauth.client_secret, "grant_type": "authorization_code", "code": code, "redirect_uri": Oauth.redirect_uri, "scope": Oauth.scope, } headers = {"Content-Type": "application/x-www-form-urlencoded"} acces_token = requests.post( url=Oauth.discord_token_url, data=payload, headers=headers ) # 新增异常判断,避免token为空 if acces_token.status_code != 200: return None json = acces_token.json() return json.get("access_token") @staticmethod def get_user_json(access_token): if not access_token: return None url = Oauth.discord_api_url + "/users/@me" headers = {"Authorization": f"Bearer {access_token}"} # 移除多余的data参数 user_object = requests.get(url=url, headers=headers) if user_object.status_code != 200: return None user_json = user_object.json() return user_json
可选优化
Flask应用需要配置secret_key,后续如果要将用户信息存入session必须设置,在Flask初始化代码后添加:
app.secret_key = "替换为你的随机密钥字符串"
内容的提问来源于stack exchange,提问作者obtuse-triangle
相关产品推荐
相关产品推荐

