mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-21 20:47:03 -05:00
feat: more optimization Hikka authorization
This commit is contained in:
parent
9eeed9f050
commit
f39e947ece
4 changed files with 25 additions and 64 deletions
|
@ -151,14 +151,6 @@ class Hikka(id: Long) : BaseTracker(id, "Hikka"), DeletableTracker {
|
||||||
interceptor.setAuth(null)
|
interceptor.setAuth(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getIfAuthExpired(): Boolean {
|
|
||||||
return trackPreferences.trackAuthExpired(this).get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setAuthExpired() {
|
|
||||||
trackPreferences.trackAuthExpired(this).set(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveOAuth(oAuth: HKOAuth?) {
|
fun saveOAuth(oAuth: HKOAuth?) {
|
||||||
trackPreferences.trackToken(this).set(json.encodeToString(oAuth))
|
trackPreferences.trackToken(this).set(json.encodeToString(oAuth))
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,12 +174,20 @@ class HikkaApi(
|
||||||
.appendQueryParameter("scope", SCOPE)
|
.appendQueryParameter("scope", SCOPE)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun refreshTokenRequest(hkOAuth: HKOAuth): Request {
|
fun refreshTokenRequest(accessToken: String): Request {
|
||||||
val headers = Headers.Builder()
|
val headers = Headers.Builder()
|
||||||
.add("auth", hkOAuth.accessToken)
|
.add("auth", accessToken)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return GET("$BASE_API_URL/user/me", headers = headers)
|
return GET("$BASE_API_URL/user/me", headers = headers) // Any request with auth
|
||||||
|
}
|
||||||
|
|
||||||
|
fun authTokenInfo(accessToken: String): Request {
|
||||||
|
val headers = Headers.Builder()
|
||||||
|
.add("auth", accessToken)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return GET("$BASE_API_URL/auth/token/info", headers = headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,33 @@
|
||||||
package eu.kanade.tachiyomi.data.track.hikka
|
package eu.kanade.tachiyomi.data.track.hikka
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.track.hikka.dto.HKAuthTokenInfo
|
||||||
import eu.kanade.tachiyomi.data.track.hikka.dto.HKOAuth
|
import eu.kanade.tachiyomi.data.track.hikka.dto.HKOAuth
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.json.JSONObject
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
class HikkaInterceptor(private val hikka: Hikka) : Interceptor {
|
class HikkaInterceptor(private val hikka: Hikka) : Interceptor {
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
private var oauth: HKOAuth? = hikka.loadOAuth()
|
private var oauth: HKOAuth? = hikka.loadOAuth()
|
||||||
private val tokenExpired get() = hikka.getIfAuthExpired()
|
|
||||||
|
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
if (tokenExpired) {
|
|
||||||
throw HKTokenExpired()
|
|
||||||
}
|
|
||||||
val originalRequest = chain.request()
|
val originalRequest = chain.request()
|
||||||
|
|
||||||
if (oauth?.isExpired() == true) {
|
val currAuth = oauth ?: throw Exception("Not authenticated with Hikka")
|
||||||
refreshToken(chain)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oauth == null) {
|
if (currAuth.isExpired()) {
|
||||||
throw IOException("User is not authenticated")
|
val refreshTokenResponse = chain.proceed(HikkaApi.refreshTokenRequest(currAuth.accessToken))
|
||||||
|
if (!refreshTokenResponse.isSuccessful)
|
||||||
|
refreshTokenResponse.close()
|
||||||
|
|
||||||
|
val authTokenInfoResponse = chain.proceed(HikkaApi.authTokenInfo(currAuth.accessToken))
|
||||||
|
if (!authTokenInfoResponse.isSuccessful)
|
||||||
|
authTokenInfoResponse.close()
|
||||||
|
|
||||||
|
val authTokenInfo = json.decodeFromString<HKAuthTokenInfo>(authTokenInfoResponse.body.string())
|
||||||
|
setAuth(HKOAuth(oauth!!.accessToken, authTokenInfo.expiration))
|
||||||
}
|
}
|
||||||
|
|
||||||
val authRequest = originalRequest.newBuilder()
|
val authRequest = originalRequest.newBuilder()
|
||||||
|
@ -40,41 +42,4 @@ class HikkaInterceptor(private val hikka: Hikka) : Interceptor {
|
||||||
this.oauth = oauth
|
this.oauth = oauth
|
||||||
hikka.saveOAuth(oauth)
|
hikka.saveOAuth(oauth)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshToken(chain: Interceptor.Chain): HKOAuth = synchronized(this) {
|
|
||||||
if (tokenExpired) throw HKTokenExpired()
|
|
||||||
oauth?.takeUnless { it.isExpired() }?.let { return@synchronized it }
|
|
||||||
|
|
||||||
val response = try {
|
|
||||||
chain.proceed(HikkaApi.refreshTokenRequest(oauth!!))
|
|
||||||
} catch (_: Throwable) {
|
|
||||||
throw HKTokenRefreshFailed()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.code != 200) {
|
|
||||||
hikka.setAuthExpired()
|
|
||||||
throw HKTokenExpired()
|
|
||||||
}
|
|
||||||
|
|
||||||
return runCatching {
|
|
||||||
if (response.isSuccessful && oauth != null) {
|
|
||||||
val responseBody = response.body?.string() ?: return@runCatching null
|
|
||||||
val jsonObject = JSONObject(responseBody)
|
|
||||||
|
|
||||||
val secret = oauth!!.accessToken
|
|
||||||
val expiration = jsonObject.getLong("expiration")
|
|
||||||
|
|
||||||
HKOAuth(secret, expiration)
|
|
||||||
} else {
|
|
||||||
response.close()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}.getOrNull()?.also {
|
|
||||||
this.oauth = it
|
|
||||||
hikka.saveOAuth(it)
|
|
||||||
} ?: throw HKTokenRefreshFailed()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HKTokenRefreshFailed : IOException("Hikka: Failed to refresh account token")
|
|
||||||
class HKTokenExpired : IOException("Hikka: Login has expired")
|
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
package eu.kanade.tachiyomi.data.track.hikka.dto
|
package eu.kanade.tachiyomi.data.track.hikka.dto
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class HKOAuth(
|
data class HKOAuth(
|
||||||
@SerialName("secret")
|
|
||||||
val accessToken: String,
|
val accessToken: String,
|
||||||
|
|
||||||
@SerialName("expiration")
|
|
||||||
val expiration: Long,
|
val expiration: Long,
|
||||||
) {
|
) {
|
||||||
fun isExpired(): Boolean {
|
fun isExpired(): Boolean {
|
||||||
return (expiration - 7200) < (System.currentTimeMillis() / 1000)
|
return (expiration - 43200) < (System.currentTimeMillis() / 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue