From 432fd287c96273bb64200bf518efd61dde5e49ea Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sat, 19 Aug 2017 23:44:12 +0800 Subject: [PATCH] Fix yggdrasil login. --- .../org/jackhuang/hmcl/setting/Settings.kt | 9 ++++- .../org/jackhuang/hmcl/ui/AccountsPage.kt | 6 ++++ .../org/jackhuang/hmcl/ui/DialogController.kt | 5 +-- .../hmcl/auth/yggdrasil/RefreshRequest.kt | 2 +- .../hmcl/auth/yggdrasil/ValidateRequest.kt | 5 ++- .../hmcl/auth/yggdrasil/YggdrasilAccount.kt | 34 +++++++++++-------- 6 files changed, 37 insertions(+), 24 deletions(-) diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/Settings.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/Settings.kt index 4736de5f6..fcf98b73d 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/Settings.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/Settings.kt @@ -66,7 +66,14 @@ object Settings { continue@loop } - val account = factory.fromStorage(settings) + val account: Account + try { + account = factory.fromStorage(settings) + } catch (e: Exception) { + SETTINGS.accounts.remove(name) + // storage is malformed, delete. + continue@loop + } if (account.username != name) { SETTINGS.accounts.remove(name) diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/AccountsPage.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/AccountsPage.kt index 8273e86ec..59729710d 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/AccountsPage.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/AccountsPage.kt @@ -30,6 +30,7 @@ import javafx.scene.control.Label import javafx.scene.control.ToggleGroup import org.jackhuang.hmcl.auth.Account import org.jackhuang.hmcl.auth.OfflineAccount +import org.jackhuang.hmcl.auth.yggdrasil.InvalidCredentialsException import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount import org.jackhuang.hmcl.i18n import org.jackhuang.hmcl.setting.Settings @@ -80,6 +81,9 @@ class AccountsPage() : StackPane(), DecoratorPage { } cboType.selectionModel.select(0) + txtPassword.setOnAction { onCreationAccept() } + txtUsername.setOnAction { onCreationAccept() } + Settings.selectedAccountProperty.addListener(listener) loadAccounts() @@ -150,6 +154,8 @@ class AccountsPage() : StackPane(), DecoratorPage { Settings.addAccount(account) dialog.close() loadAccounts() + } else if (account is InvalidCredentialsException) { + lblCreationWarning.text = i18n("login.wrong_password") } else if (account is Exception) { lblCreationWarning.text = account.localizedMessage } diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/DialogController.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/DialogController.kt index 21a157f08..1a0ae392b 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/DialogController.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/DialogController.kt @@ -42,10 +42,7 @@ object DialogController { pane.dialog = Controllers.dialog(pane) } latch.await() - if (res.get() == null) - throw SilentException() - else - return res.get() + return res.get() ?: throw SilentException() } return null } diff --git a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/RefreshRequest.kt b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/RefreshRequest.kt index a8a749a6c..0c6e3b452 100644 --- a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/RefreshRequest.kt +++ b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/RefreshRequest.kt @@ -20,6 +20,6 @@ package org.jackhuang.hmcl.auth.yggdrasil data class RefreshRequest( val clientToken: String, val accessToken: String, - val selectedProfile: GameProfile?, + val selectedProfile: GameProfile? = null, val requestUser: Boolean = true ) \ No newline at end of file diff --git a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/ValidateRequest.kt b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/ValidateRequest.kt index ae04fe801..32cba9bf5 100644 --- a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/ValidateRequest.kt +++ b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/ValidateRequest.kt @@ -17,8 +17,7 @@ */ package org.jackhuang.hmcl.auth.yggdrasil -data class ValidateRequest ( +data class ValidateRequest @JvmOverloads constructor( val clientToken: String = "", val accessToken: String = "" -) { -} \ No newline at end of file +) \ No newline at end of file diff --git a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.kt b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.kt index 39958b377..f1ff3890d 100644 --- a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.kt +++ b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.kt @@ -33,7 +33,7 @@ class YggdrasilAccount private constructor(override val username: String): Accou private var password: String? = null private var userId: String? = null private var accessToken: String? = null - private var clientToken: String = UUID.randomUUID().toString() + private var clientToken: String = randomToken() private var isOnline: Boolean = false private var userProperties = PropertyMap() var selectedProfile: GameProfile? = null @@ -96,7 +96,7 @@ class YggdrasilAccount private constructor(override val username: String): Accou isOnline = true return } - logIn1(ROUTE_REFRESH, RefreshRequest(accessToken!!, clientToken, selectedProfile), proxy) + logIn1(ROUTE_REFRESH, RefreshRequest(clientToken = clientToken, accessToken = accessToken!!, selectedProfile = selectedProfile), proxy) } else if (isNotBlank(password)) { logIn1(ROUTE_AUTHENTICATE, AuthenticationRequest(username, password!!, clientToken), proxy) } else @@ -122,7 +122,7 @@ class YggdrasilAccount private constructor(override val username: String): Accou userProperties.clear() accessToken = response.accessToken - if (user != null && user.properties != null) + if (user?.properties != null) userProperties.putAll(user.properties) } @@ -140,18 +140,19 @@ class YggdrasilAccount private constructor(override val username: String): Accou val result = HashMap() result[STORAGE_KEY_USER_NAME] = username + result[STORAGE_KEY_CLIENT_TOKEN] = clientToken if (userId != null) result[STORAGE_KEY_USER_ID] = userId!! if (!userProperties.isEmpty()) result[STORAGE_KEY_USER_PROPERTIES] = userProperties.toList() val profile = selectedProfile - if (profile != null && profile.name != null && profile.id != null) { + if (profile?.name != null && profile.id != null) { result[STORAGE_KEY_PROFILE_NAME] = profile.name - result[STORAGE_KEY_PROFILE_ID] = profile.id + result[STORAGE_KEY_PROFILE_ID] = UUIDTypeAdapter.fromUUID(profile.id) if (!profile.properties.isEmpty()) result[STORAGE_KEY_PROFILE_PROPERTIES] = profile.properties.toList() } - if (accessToken?.isNotBlank() ?: false) + if (accessToken != null && accessToken!!.isNotBlank()) result[STORAGE_KEY_ACCESS_TOKEN] = accessToken!! return result @@ -167,11 +168,12 @@ class YggdrasilAccount private constructor(override val username: String): Accou if (response.error?.isNotBlank() ?: false) { LOG.severe("Failed to log in, the auth server returned an error: " + response.error + ", message: " + response.errorMessage + ", cause: " + response.cause) - throw when (response.errorMessage) { - "Invalid token." -> InvalidTokenException(this) - "Invalid credentials. Invalid username or password." -> InvalidCredentialsException(this) - else -> AuthenticationException("Request error: ${response.errorMessage}") - } + if (response.errorMessage != null) + if (response.errorMessage.contains("Invalid credentials")) + throw InvalidCredentialsException(this) + else if (response.errorMessage.contains("Invalid token")) + throw InvalidTokenException(this) + throw AuthenticationException("Request error: ${response.errorMessage}") } return response @@ -183,10 +185,8 @@ class YggdrasilAccount private constructor(override val username: String): Accou } private fun checkTokenValidity(proxy: Proxy): Boolean { - val access = accessToken + val access = accessToken ?: return false try { - if (access == null) - return false makeRequest(ROUTE_VALIDATE, ValidateRequest(clientToken, access), proxy) return true } catch (e: AuthenticationException) { @@ -215,6 +215,9 @@ class YggdrasilAccount private constructor(override val username: String): Accou private val STORAGE_KEY_USER_NAME = "username" private val STORAGE_KEY_USER_ID = "userid" private val STORAGE_KEY_USER_PROPERTIES = "userProperties" + private val STORAGE_KEY_CLIENT_TOKEN = "clientToken" + + fun randomToken() = UUIDTypeAdapter.fromUUID(UUID.randomUUID()) override fun fromUsername(username: String, password: String): YggdrasilAccount { val account = YggdrasilAccount(username) @@ -223,10 +226,11 @@ class YggdrasilAccount private constructor(override val username: String): Accou } override fun fromStorage(storage: Map): YggdrasilAccount { - val username = storage[STORAGE_KEY_USER_NAME] as? String ?: throw IllegalArgumentException("storage does not have key $STORAGE_KEY_USER_NAME") + val username = storage[STORAGE_KEY_USER_NAME] as? String? ?: throw IllegalArgumentException("storage does not have key $STORAGE_KEY_USER_NAME") val account = YggdrasilAccount(username) account.userId = storage[STORAGE_KEY_USER_ID] as? String ?: username account.accessToken = storage[STORAGE_KEY_ACCESS_TOKEN] as? String + account.clientToken = storage[STORAGE_KEY_CLIENT_TOKEN] as? String? ?: throw IllegalArgumentException("storage does not have key $STORAGE_KEY_CLIENT_TOKEN") val userProperties = storage[STORAGE_KEY_USER_PROPERTIES] as? List<*> if (userProperties != null) account.userProperties.fromList(userProperties)