diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/OAuthServer.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/OAuthServer.java index 726494e38f..daa1fc90fc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/OAuthServer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/OAuthServer.java @@ -163,6 +163,13 @@ public Response serve(IHTTPSession session) { return newFixedLengthResponse(Response.Status.OK, "text/html; charset=UTF-8", html); } + @Override + public void close() { + if (!future.isDone()) + future.completeExceptionally(new AuthenticationException("OAuth server is closing")); + stop(); + } + public static class Factory implements OAuth.Callback { public final EventManager onGrantDeviceCode = new EventManager<>(); public final EventManager onOpenBrowserAuthorizationCode = new EventManager<>(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/OAuth.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/OAuth.java index 51eec94366..d47860d617 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/OAuth.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/OAuth.java @@ -80,37 +80,37 @@ public Result authenticate(GrantFlow grantFlow, Options options) throws Authenti } private Result authenticateAuthorizationCode(Options options) throws IOException, InterruptedException, JsonParseException, ExecutionException, AuthenticationException { - Session session = options.callback.startServer(); - - String codeVerifier = session.getCodeVerifier(); - String state = session.getState(); - String codeChallenge = generateCodeChallenge(codeVerifier); - - options.callback.openBrowser(GrantFlow.AUTHORIZATION_CODE, NetworkUtils.withQuery(authorizationURL, - mapOf(pair("client_id", options.callback.getClientId()), - pair("response_type", "code"), - pair("redirect_uri", session.getRedirectURI()), - pair("scope", options.scope), - pair("prompt", "select_account"), - pair("code_challenge", codeChallenge), - pair("state", state), - pair("code_challenge_method", "S256") - ))); - String code = session.waitFor(); - - // Authorization Code -> Token - AuthorizationResponse response = HttpRequest.POST(accessTokenURL) - .form(pair("client_id", options.callback.getClientId()), - pair("code", code), - pair("grant_type", "authorization_code"), - pair("code_verifier", codeVerifier), - pair("redirect_uri", session.getRedirectURI()), - pair("scope", options.scope)) - .ignoreHttpCode() - .retry(5) - .getJson(AuthorizationResponse.class); - handleErrorResponse(response); - return new Result(response.accessToken, response.refreshToken); + try (Session session = options.callback.startServer()) { + String codeVerifier = session.getCodeVerifier(); + String state = session.getState(); + String codeChallenge = generateCodeChallenge(codeVerifier); + + options.callback.openBrowser(GrantFlow.AUTHORIZATION_CODE, NetworkUtils.withQuery(authorizationURL, + mapOf(pair("client_id", options.callback.getClientId()), + pair("response_type", "code"), + pair("redirect_uri", session.getRedirectURI()), + pair("scope", options.scope), + pair("prompt", "select_account"), + pair("code_challenge", codeChallenge), + pair("state", state), + pair("code_challenge_method", "S256") + ))); + String code = session.waitFor(); + + // Authorization Code -> Token + AuthorizationResponse response = HttpRequest.POST(accessTokenURL) + .form(pair("client_id", options.callback.getClientId()), + pair("code", code), + pair("grant_type", "authorization_code"), + pair("code_verifier", codeVerifier), + pair("redirect_uri", session.getRedirectURI()), + pair("scope", options.scope)) + .ignoreHttpCode() + .retry(5) + .getJson(AuthorizationResponse.class); + handleErrorResponse(response); + return new Result(response.accessToken, response.refreshToken); + } } private Result authenticateDevice(Options options) throws IOException, InterruptedException, JsonParseException, AuthenticationException { @@ -234,7 +234,7 @@ public Options setUserAgent(String userAgent) { } } - public interface Session { + public interface Session extends AutoCloseable { String getState(); String getCodeVerifier(); @@ -253,6 +253,9 @@ public interface Session { default String getIdToken() { return null; } + + @Override + void close(); } public interface Callback {