Skip to content

Commit fc6678a

Browse files
committed
make pkce multiplatform (fixes #252 and #253)
Signed-off-by: Adam Ratzman <[email protected]>
1 parent bb32849 commit fc6678a

File tree

13 files changed

+218
-53
lines changed

13 files changed

+218
-53
lines changed

build.gradle.kts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ plugins {
77
signing
88
id("io.codearte.nexus-staging") version "0.22.0"
99
id("com.android.library")
10-
kotlin("multiplatform") version "1.4.21"
11-
kotlin("plugin.serialization") version "1.4.20"
10+
kotlin("multiplatform") version "1.4.30"
11+
kotlin("plugin.serialization") version "1.4.30"
1212
id("com.diffplug.spotless") version "5.9.0"
1313
id("com.moowork.node") version "1.3.1"
1414
id("org.jetbrains.dokka") version "1.4.20"
@@ -27,7 +27,7 @@ buildscript {
2727
}
2828
dependencies {
2929
classpath("com.android.tools.build:gradle:3.5.4")
30-
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21")
30+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.30")
3131
}
3232
}
3333

@@ -132,6 +132,7 @@ kotlin {
132132
testTask {
133133
useKarma {
134134
useChromeHeadless()
135+
//useChrome()
135136
webpackConfig.cssSupport.enabled = true
136137
}
137138
}
@@ -183,6 +184,7 @@ kotlin {
183184
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
184185
implementation("io.ktor:ktor-client-core:$ktorVersion")
185186
implementation("com.soywiz.korlibs.klock:klock:$klockVersion")
187+
implementation("com.soywiz.korlibs.krypto:krypto:2.0.6")
186188
}
187189
}
188190

@@ -226,6 +228,10 @@ kotlin {
226228
val jsTest by getting {
227229
dependencies {
228230
implementation(kotlin("test-js"))
231+
232+
// implementation("io.kotest:kotest-assertions-core-js:4.3.2")
233+
// implementation("io.kotest:kotest-framework-api-js:4.3.2")
234+
// implementation("io.kotest:kotest-framework-engine-js:4.3.2")
229235
}
230236
}
231237

@@ -394,8 +400,10 @@ fun PublishingExtension.registerPublishing() {
394400
url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
395401

396402
credentials {
397-
val nexusUsername: String? = System.getenv("nexus.username") ?: if (project.extra.has("nexusUsername")) project.extra["nexusUsername"] as? String else null
398-
val nexusPassword: String? = System.getenv("nexus.password") ?: if (project.extra.has("nexusPassword")) project.extra["nexusPassword"] as? String else null
403+
val nexusUsername: String? = System.getenv("nexus.username")
404+
?: if (project.extra.has("nexusUsername")) project.extra["nexusUsername"] as? String else null
405+
val nexusPassword: String? = System.getenv("nexus.password")
406+
?: if (project.extra.has("nexusPassword")) project.extra["nexusPassword"] as? String else null
399407
username = nexusUsername
400408
password = nexusPassword
401409
}

src/androidMain/kotlin/com/adamratzman/spotify/Pkce.kt

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/commonMain/kotlin/com.adamratzman.spotify/Builder.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import com.adamratzman.spotify.http.HttpRequestMethod
77
import com.adamratzman.spotify.models.Token
88
import com.adamratzman.spotify.models.serialization.nonstrictJson
99
import com.adamratzman.spotify.models.serialization.toObject
10+
import com.soywiz.krypto.SHA256
1011
import io.ktor.client.features.ServerResponseException
12+
import io.ktor.utils.io.core.toByteArray
1113
import kotlinx.coroutines.CancellationException
1214
import kotlinx.serialization.json.Json
1315

@@ -76,7 +78,14 @@ public fun getPkceAuthorizationUrl(
7678
/**
7779
* A utility to get the pkce code challenge for a corresponding code verifier. Only available on JVM/Android
7880
*/
79-
public expect fun getSpotifyPkceCodeChallenge(codeVerifier: String): String
81+
public fun getSpotifyPkceCodeChallenge(codeVerifier: String): String {
82+
if (codeVerifier.length !in 43..128) throw IllegalArgumentException("Code verifier must be between 43 and 128 characters long")
83+
84+
var sha256 = SHA256.digest(codeVerifier.toByteArray()).base64
85+
while (sha256.endsWith("=")) sha256 = sha256.removeSuffix("=")
86+
87+
return sha256.replace("/", "_").replace("+", "-")
88+
}
8089

8190
// ==============================================
8291

src/commonMain/kotlin/com.adamratzman.spotify/endpoints/public/SearchApi.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public open class SearchApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) {
3737
*
3838
* @param id The internal id
3939
*/
40-
public enum class SearchType(internal val id: String) {
40+
public enum class SearchType(public val id: String) {
4141
ALBUM("album"),
4242
TRACK("track"),
4343
ARTIST("artist"),
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* Spotify Web API, Kotlin Wrapper; MIT License, 2017-2021; Original author: Adam Ratzman */
2+
package com.adamratzman.spotify
3+
4+
abstract class AbstractTest<T : GenericSpotifyApi> {
5+
lateinit var api: T
6+
7+
suspend fun build(): Boolean {
8+
return try {
9+
@Suppress("UNCHECKED_CAST")
10+
(buildSpotifyApi() as? T)?.let { api = it }
11+
println(api as? T)
12+
::api.isInitialized
13+
} catch (cce: ClassCastException) {
14+
false
15+
}
16+
}
17+
}
18+
19+
typealias GenericSpotifyApiTest = AbstractTest<GenericSpotifyApi>
20+
typealias SpotifyClientApiTest = AbstractTest<SpotifyClientApi>

src/commonTest/kotlin/com.adamratzman/spotify/utilities/UtilityTests.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.adamratzman.spotify.SpotifyUserAuthorization
88
import com.adamratzman.spotify.assertFailsWithSuspend
99
import com.adamratzman.spotify.buildSpotifyApi
1010
import com.adamratzman.spotify.getEnvironmentVariable
11+
import com.adamratzman.spotify.getSpotifyPkceCodeChallenge
1112
import com.adamratzman.spotify.runBlockingTest
1213
import com.adamratzman.spotify.spotifyAppApi
1314
import com.adamratzman.spotify.spotifyClientApi
@@ -26,6 +27,12 @@ class UtilityTests {
2627

2728
fun testPrereq() = ::api.isInitialized
2829

30+
@Test
31+
fun testGeneratePkceCodeChallenge() {
32+
assertEquals("c7jV_d4sQ658HgwINAR77Idumz1ik1lIb1JNlOva75E", getSpotifyPkceCodeChallenge("thisisaveryrandomalphanumericcodeverifierandisgreaterthan43characters"))
33+
assertEquals("9Y__uhKapn7GO_ElcaQpd8C3hdOyqTzAU4VXyR2iEV0", getSpotifyPkceCodeChallenge("12345678901234567890123456789012345678901234567890"))
34+
}
35+
2936
@Test
3037
fun testPagingObjectTakeItemsSize() {
3138
runBlockingTest {

src/desktopMain/kotlin/com/adamratzman/spotify/Pkce.kt

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* Spotify Web API, Kotlin Wrapper; MIT License, 2017-2021; Original author: Adam Ratzman */
2+
package co.scdn.sdk
3+
4+
import kotlinx.browser.window
5+
6+
public fun setOnSpotifyWebPlaybackSDKReady(callback: suspend () -> Unit) {
7+
val dynamicWindow: dynamic = window
8+
dynamicWindow["onSpotifyWebPlaybackSDKReady"] = callback
9+
}

src/jsMain/kotlin/com/adamratzman/spotify/Pkce.kt

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* Spotify Web API, Kotlin Wrapper; MIT License, 2017-2021; Original author: Adam Ratzman */
2+
package com.adamratzman.spotify.webplayer
3+
4+
typealias ErrorListener = (err: Error) -> Unit
5+
typealias PlaybackInstanceListener = (inst: WebPlaybackInstance) -> Unit
6+
typealias PlaybackStateListener = (s: PlaybackState) -> Unit

0 commit comments

Comments
 (0)