使用Flutter Web Auth_2获取Discord Bearer Token时重定向URI格式错误求助
解决Flutter Web Auth_2获取Discord Bearer Token时的"discord not valid formated well redirect uri"错误
核心问题定位
这个错误的根源是Redirect URI格式不符合Discord OAuth2的要求,同时你的代码和配置里还有几处逻辑错误,逐一拆解如下:
1. Callback URL Scheme格式错误
你当前把callbackUrlScheme设为http://com.example.sabadospotify,但Android自定义URL Scheme不能带http://前缀,必须是纯协议名(比如com.example.sabadospotify),而且Discord后台配置的Redirect URI必须和代码里的完全匹配。
2. AndroidManifest的Scheme配置错误
<data android:scheme="http://com.example.sabadospotify" /> 同样不能带http://,要改成纯协议名。
3. 代码里的其他逻辑问题
getGoogleAuthCode函数重复调用FlutterWebAuth2.authenticate,还存在无效的重复return语句- 全局变量
casteo错误地把Future<String>强制转成String,会直接触发运行时错误 print(result1)语法写错了,而且异步逻辑完全没处理对- 按钮点击事件没串联授权和Token交换的流程,也没传递授权码
- Discord授权请求里不该传
client_secret——这个参数只在后端交换Token时用,前端授权步骤暴露它会有安全风险
修正后的配置和代码
1. 修正AndroidManifest.xml
<activity android:name="com.linusu.flutter_web_auth_2.CallbackActivity" android:exported="true"> <intent-filter android:label="flutter_web_auth_2"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <!-- 去掉http://,只保留纯scheme --> <data android:scheme="com.example.sabadospotify" /> </intent-filter> </activity>
2. 修正Dart代码
import 'package:flutter/material.dart'; import 'package:flutter_web_auth_2/flutter_web_auth_2.dart'; import 'dart:convert' show jsonDecode; import 'package:http/http.dart' as http; // App配置变量 final discordClientId = '你的Discord Client ID'; final discordClientSecret = '你的Discord Client Secret'; // 修正为纯scheme,不带http:// final callbackUrlScheme = 'com.example.sabadospotify'; // 对应的Redirect URI,必须和Discord后台配置完全一致 final redirectUri = '$callbackUrlScheme:/'; // 构建Discord授权URL final authUrl = Uri.https('discord.com', '/oauth2/authorize', { 'response_type': 'code', 'client_id': discordClientId, // 授权步骤不需要传client_secret,避免泄露 'redirect_uri': redirectUri, 'scope': 'email', // 可按需添加其他权限,比如identify }); // 获取授权码 Future<String> getDiscordAuthCode() async { final resultUrl = await FlutterWebAuth2.authenticate( url: authUrl.toString(), callbackUrlScheme: callbackUrlScheme, ); // 从回调URL里提取授权码 final code = Uri.parse(resultUrl).queryParameters['code']; if (code == null) throw Exception('未获取到授权码'); return code; } // 用授权码交换Bearer Token Future<String> exchangeCodeForToken(String code) async { final response = await http.post( Uri.parse('https://discord.com/api/oauth2/token'), headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: { 'code': code, 'client_id': discordClientId, 'client_secret': discordClientSecret, 'redirect_uri': redirectUri, 'grant_type': 'authorization_code', }, ); if (response.statusCode != 200) { throw Exception('Token交换失败: ${response.body}'); } final body = jsonDecode(response.body); final accessToken = body['access_token'] as String; return accessToken; } void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('Discord 登录')), body: Center( child: ElevatedButton( child: const Text('Sign in with Discord'), onPressed: () async { try { // 先获取授权码 final code = await getDiscordAuthCode(); // 再交换Token final token = await exchangeCodeForToken(code); print('获取到Bearer Token: $token'); // 这里可以加后续逻辑,比如保存Token、跳转页面等 } catch (e) { print('登录失败: $e'); // 处理错误,比如提示用户 } }, ), ), ), ); } }
最后必做的配置
- 登录Discord开发者后台,找到你的应用
- 进入OAuth2 -> General页面
- 在Redirects列表里添加
com.example.sabadospotify:/(和代码里的redirectUri完全一致) - 保存配置
内容的提问来源于stack exchange,提问作者oshju
相关产品推荐
相关产品推荐

