11package io .github .techstreet .dfscript .network ;
22
33import com .google .gson .JsonObject ;
4+ import com .mojang .authlib .exceptions .AuthenticationException ;
45import io .github .techstreet .dfscript .DFScript ;
56import io .github .techstreet .dfscript .loader .Loadable ;
7+ import io .github .techstreet .dfscript .network .request .ForbiddenException ;
68import io .github .techstreet .dfscript .network .request .ServerCodeResponse ;
9+ import net .minecraft .client .util .Session ;
710import org .apache .commons .codec .digest .DigestUtils ;
811
912import java .io .BufferedReader ;
@@ -21,7 +24,6 @@ public class AuthHandler implements Loadable {
2124
2225 @ Override
2326 public void load () {
24-
2527 try {
2628 regen ();
2729 }
@@ -40,19 +42,21 @@ public void regen() throws IOException {
4042 e .printStackTrace ();
4143 return ;
4244 }
45+ // STEP 2: Connect to the fake server, and get our code validated
4346 try {
4447 validateCode ();
4548 this .valid = true ;
46- } catch (Exception e ) {
47- DFScript .LOGGER .error (e );
48- e .printStackTrace ();
49+ } catch (AuthenticationException | ForbiddenException e ) {
4950 this .valid = false ;
51+ DFScript .LOGGER .error (e .getMessage ());
52+ e .printStackTrace ();
5053 }
5154 }
5255
5356 /**
5457 * Sends a code to the server, and generates a hash of this code and one returned by the server.
5558 * This code is to be used as the bearer token, it just has to be verified by connecting to the fake server.
59+ * This also sends our username, which is used later for verification.
5660 * @return The common code hash
5761 * @throws IOException Any error in the networking
5862 */
@@ -70,6 +74,7 @@ private String getCommonSecret() throws IOException {
7074
7175 JsonObject jsonObject = new JsonObject ();
7276 jsonObject .addProperty ("client" ,clientCode );
77+ jsonObject .addProperty ("name" ,DFScript .MC .getSession ().getUsername ());
7378
7479 try (OutputStream os = connection .getOutputStream ()) {
7580 byte [] input = jsonObject .toString ().getBytes (StandardCharsets .UTF_8 );
@@ -84,11 +89,38 @@ private String getCommonSecret() throws IOException {
8489 response .append (responseLine .trim ());
8590 }
8691 ServerCodeResponse servercodeResponse = DFScript .GSON .fromJson (response .toString (), ServerCodeResponse .class );
87- return DigestUtils .sha256Hex (servercodeResponse .getServerCode () + clientCode );
92+ return DigestUtils .sha256Hex (clientCode + servercodeResponse .getServerCode ());
8893 }
8994 }
9095
91- private void validateCode () {
92- // TODO: validate code.
96+ /**
97+ * Joins a fake minecraft server, and notifies the backend.
98+ * The server ID is the common hash, which is then verified as safe to use.
99+ * If this completes, the common hash should be used as an authentication token.
100+ * @throws AuthenticationException Likely logged out
101+ * @throws IOException DFOnline Backend error
102+ */
103+ private void validateCode () throws AuthenticationException , IOException , ForbiddenException {
104+
105+ Session session = DFScript .MC .getSession ();
106+ DFScript .MC .getSessionService ().joinServer (session .getProfile (), session .getAccessToken (), commonSecret .substring (0 ,30 ));
107+
108+ URL url = new URL (DFScript .BACKEND + "/user/verify/" + commonSecret );
109+ DFScript .LOGGER .info (url .toString ());
110+ HttpURLConnection connection = (HttpURLConnection ) url .openConnection ();
111+ connection .setRequestMethod ("GET" );
112+ connection .setRequestProperty ("Accept" , "application/json" );
113+ connection .setReadTimeout (500000000 );
114+ connection .setConnectTimeout (500000000 );
115+
116+ int status = connection .getResponseCode ();
117+
118+ if (status == 403 ) {
119+ throw new ForbiddenException ("Player is banned by the backend!" );
120+ }
121+ if (status != 204 ) {
122+ throw new IOException ("Unexpected response code from backend: " + status );
123+ }
124+ // It worked.
93125 }
94126}
0 commit comments