Discord OAuth API问题:通过Code获取Token时持续返回400错误
我在给网站搭建Discord OAuth登录功能,已经通过identify email scope拿到了授权code,但调用/oauth2/token接口换取Token时持续返回400错误。试过将认证方式从Basic Auth改为在POST参数中传递凭据,问题仍未解决。以下是我的Java代码及错误栈:
final HttpURLConnection connection = (HttpURLConnection) new URL("https://discord.com/api/v10/oauth2/token").openConnection(); try(AutoCloseable autoCloseable = () -> connection.disconnect()){ connection.setRequestMethod("POST"); connection.addRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //connection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString((CLIENT_ID + ":" + CLIENT_SECRET).getBytes())); connection.setDoOutput(true); try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream())); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) writer.write("grant_type=authorization_code&" + "code="+code+"&" + "redirect_uri=https://website/api/discord&" + "&client_secret=" + CLIENT_SECRET + "&client_id=" + CLIENT_ID); writer.flush(); String s; while((s = reader.readLine()) != null){ resp.getWriter().println(s); } resp.getWriter().flush(); } }catch (Exception e){ e.printStackTrace(); }
错误栈:
java.io.IOException: Server returned HTTP response code: 400 for URL: https://discord.com/api/v10/oauth2/token at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1998) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1599) at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:223)
问题修复方案
修正POST参数格式错误
你拼接的POST参数里,redirect_uri=https://website/api/discord&后面多了一个多余的&,导致client_secret参数变成&client_secret,这会导致Discord接口无法正确解析参数,直接返回400。把这个多余的&删掉即可,正确的参数拼接代码:writer.write("grant_type=authorization_code&" + "code="+code+"&" + "redirect_uri=https://website/api/discord&" + "client_secret=" + CLIENT_SECRET + "&client_id=" + CLIENT_ID);优化错误处理逻辑
当前代码在发送请求前直接调用getInputStream(),如果接口返回400这类错误状态码,HttpURLConnection会直接抛出IOException,导致你无法看到Discord返回的具体错误信息。建议先检查响应状态码,再选择读取输入流或错误流:// 先发送请求 writer.flush(); // 检查响应码 int responseCode = connection.getResponseCode(); BufferedReader reader; if (responseCode == 200) { reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); } else { reader = new BufferedReader(new InputStreamReader(connection.getErrorStream())); } // 后续读取逻辑不变这样再出现400错误时,你能直接看到Discord返回的错误详情(比如code无效、参数缺失等),更快定位问题。
认证方式的补充说明
Discord OAuth2接口支持两种认证方式:Basic Auth或POST参数传递client_id和client_secret。如果使用Basic Auth,要确保Base64编码的是CLIENT_ID:CLIENT_SECRET的UTF-8字节,避免编码问题:connection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString((CLIENT_ID + ":" + CLIENT_SECRET).getBytes(StandardCharsets.UTF_8)));
内容的提问来源于stack exchange,提问作者Aaron Akhtar

