xyz.cssxsh.pixiv.auth.OauthApi.kt Maven / Gradle / Ivy
package xyz.cssxsh.pixiv.auth
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.forms.*
import io.ktor.http.*
import io.ktor.util.*
import xyz.cssxsh.pixiv.*
import java.security.*
import java.time.*
import kotlin.random.Random
public const val OAUTH_TOKEN_URL: String = "https://oauth.secure.pixiv.net/auth/token"
public const val OAUTH_AUTHORIZE_URL: String = "https://oauth.secure.pixiv.net/auth/authorize"
public const val REDIRECT_LOGIN_URL: String = "https://app-api.pixiv.net/web/v1/login"
public const val START_URL: String = "https://app-api.pixiv.net/web/v1/users/auth/pixiv/start"
public const val REDIRECT_URL: String = "https://app-api.pixiv.net/web/v1/users/auth/pixiv/callback"
public const val ORIGIN_URL: String = "https://accounts.pixiv.net"
public const val LOGIN_URL: String = "https://accounts.pixiv.net/login"
public const val LOGIN_API_URL: String = "https://accounts.pixiv.net/api/login"
public const val POST_SELECTED_URL: String = "https://accounts.pixiv.net/account-selected"
public const val POST_REDIRECT_URL: String = "https://accounts.pixiv.net/post-redirect"
public const val GIGYA_AUTH_URL: String = "https://accounts.pixiv.net/gigya-auth"
public const val SOCIALIZE_LOGIN_URL: String = "https://socialize.gigya.com/socialize.login"
private fun String.sha256(): ByteArray {
return MessageDigest.getInstance("SHA-256")
.digest(toByteArray(Charsets.US_ASCII))
}
private const val VERIFIER_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
private const val VERIFIER_LENGTH = 128
internal fun verifier(time: OffsetDateTime): Pair {
val random = Random(time.toEpochSecond())
val origin = buildString(VERIFIER_LENGTH) {
repeat(VERIFIER_LENGTH) {
append(VERIFIER_CHARS[random.nextInt(VERIFIER_CHARS.length)])
}
}
val challenge = origin
.sha256()
.encodeBase64()
.replace("=", "")
val parameters = ParametersBuilder().apply {
append("code_challenge", challenge)
append("code_challenge_method", "S256")
append("client", "pixiv-android")
}.build()
return origin to parameters
}
internal suspend fun HttpClient.authorize(code: String, verifier: String): AuthResult {
return submitForm(url = OAUTH_TOKEN_URL, formParameters = Parameters.build {
append("client_id", ANDROID_CLIENT_ID)
append("client_secret", ANDROID_CLIENT_SECRET)
append("grant_type", "authorization_code")
append("include_policy", "true")
append("code", code)
append("code_verifier", verifier)
append("redirect_uri", REDIRECT_URL)
}).body()
}
internal suspend fun HttpClient.refresh(token: String): AuthResult {
return submitForm(url = OAUTH_TOKEN_URL, formParameters = Parameters.build {
append("client_id", ANDROID_CLIENT_ID)
append("client_secret", ANDROID_CLIENT_SECRET)
append("grant_type", "refresh_token")
append("include_policy", "true")
append("refresh_token", token)
}).body()
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy