javaoauth-2.0discordoauth

Discord oAuth API - 400 error getting token from code


What I'm trying to do: setup oauth discord logins on my website, I've setup the first part, identify email scope for getting the initial code, now that I've got the code, I'm unable to use the /oauth/token endpoint without getting a consistent 400 error.

I've attempted 1 thing so far, changing my Auth from Basic to inside of my post params, still didn't work:

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();
}

My error stacktrace:

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)

Solution

  • Basic Authentication problem

    "Basic " + Base64.getEncoder().encodeToString((CLIENT_ID + ":" + CLIENT_SECRET).getBytes()));
    

    .getBytes() produces an array of byte. Appending an array to a String doesn't produce what you need, as it will print something related to the array's identity rather than its contents. But the solution here is simple : simply omit the .getBytes() call.

    To be entirely in line with the OAuth spec though, you have to URL encode both the client id and the client secret before encoding them with Base64. However that's likely not your problem.

    Form Post Authentication problem

    I asssume you were a bit too hasty when replacing the Basic authentication, and screwed up the '&' separator.

    "redirect_uri=https://website/api/discord&" +
    "&client_secret=" + CLIENT_SECRET
    

    has a double '&'

    "redirect_uri=https://website/api/discord&&client_secret=" + CLIENT_SECRET
    

    Here as well you should make sure to properly URL encode the code, the client id and the client secret.