Skip to content

Commit bdb36e9

Browse files
authored
Merge pull request #204 from adamint/dev
update docs, add state option to get auth url
2 parents c6b9838 + e4ef0c8 commit bdb36e9

File tree

3 files changed

+56
-19
lines changed

3 files changed

+56
-19
lines changed

build.gradle.kts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ plugins {
1515
}
1616

1717
group = "com.adamratzman"
18-
version = "3.1.0"
18+
version = "3.1.01"
1919

2020
java {
2121
withSourcesJar()
@@ -63,10 +63,11 @@ kotlin {
6363

6464
val commonMain by getting {
6565
dependencies {
66-
implementation(kotlin("stdlib-common"))
6766
api("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutineVersion")
68-
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serializationVersion")
67+
api("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serializationVersion")
6968
api("io.ktor:ktor-client-core:$ktorVersion")
69+
70+
implementation(kotlin("stdlib-common"))
7071
}
7172
}
7273
val commonTest by getting {
@@ -85,9 +86,9 @@ kotlin {
8586

8687
dependencies {
8788
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion")
88-
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion")
89+
api("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion")
8990
api("io.ktor:ktor-client-okhttp:$ktorVersion")
90-
implementation("commons-codec:commons-codec:1.14")
91+
api("commons-codec:commons-codec:1.14")
9192
implementation(kotlin("stdlib-jdk8"))
9293
}
9394
}
@@ -105,12 +106,12 @@ kotlin {
105106

106107
val jsMain by getting {
107108
dependencies {
108-
implementation(npm("text-encoding", "0.7.0"))
109+
api(npm("text-encoding", "0.7.0"))
109110
api("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutineVersion")
110-
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serializationVersion")
111+
api("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serializationVersion")
111112
api("io.ktor:ktor-client-js:$ktorVersion")
112-
implementation(npm("abort-controller", "3.0.0"))
113-
implementation(npm("node-fetch", "2.6.0"))
113+
api(npm("abort-controller", "3.0.0"))
114+
api(npm("node-fetch", "2.6.0"))
114115

115116
compileOnly(kotlin("stdlib-js"))
116117
}

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

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,24 @@ import kotlinx.serialization.json.Json
2828
* @param redirectUri Spotify [redirect uri](https://developer.spotify.com/documentation/general/guides/app-settings/)
2929
* @param isImplicitGrantFlow Whether the authorization url should be for the Implicit Grant flow, otherwise for Authorization Code flo
3030
* @param shouldShowDialog If [isImplicitGrantFlow] is true, whether or not to force the user to approve the app again if they’ve already done so.
31+
* @param state This provides protection against attacks such as cross-site request forgery.
3132
*/
32-
fun getSpotifyAuthorizationUrl(vararg scopes: SpotifyScope, clientId: String, redirectUri: String, isImplicitGrantFlow: Boolean = false, shouldShowDialog: Boolean = false): String {
33-
return SpotifyApi.getAuthUrlFull(*scopes, clientId = clientId, redirectUri = redirectUri, isImplicitGrantFlow = isImplicitGrantFlow, shouldShowDialog = shouldShowDialog)
33+
fun getSpotifyAuthorizationUrl(
34+
vararg scopes: SpotifyScope,
35+
clientId: String,
36+
redirectUri: String,
37+
isImplicitGrantFlow: Boolean = false,
38+
shouldShowDialog: Boolean = false,
39+
state: String? = null
40+
): String {
41+
return SpotifyApi.getAuthUrlFull(
42+
*scopes,
43+
clientId = clientId,
44+
redirectUri = redirectUri,
45+
isImplicitGrantFlow = isImplicitGrantFlow,
46+
shouldShowDialog = shouldShowDialog,
47+
state = state
48+
)
3449
}
3550

3651
// ==============================================
@@ -536,9 +551,10 @@ interface ISpotifyClientApiBuilder : ISpotifyApiBuilder<SpotifyClientApi, Spotif
536551
* Create a Spotify authorization URL from which API access can be obtained
537552
*
538553
* @param scopes The scopes that the application should have access to
554+
* @param state This provides protection against attacks such as cross-site request forgery.
539555
* @return Authorization URL that can be used in a browser
540556
*/
541-
fun getAuthorizationUrl(vararg scopes: SpotifyScope): String
557+
fun getAuthorizationUrl(vararg scopes: SpotifyScope, state: String? = null): String
542558
}
543559

544560
/**
@@ -549,9 +565,14 @@ class SpotifyClientApiBuilder(
549565
override var authorization: SpotifyUserAuthorization = SpotifyUserAuthorizationBuilder().build(),
550566
override var options: SpotifyApiOptions = SpotifyApiOptionsBuilder().build()
551567
) : ISpotifyClientApiBuilder {
552-
override fun getAuthorizationUrl(vararg scopes: SpotifyScope): String {
568+
override fun getAuthorizationUrl(vararg scopes: SpotifyScope, state: String?): String {
553569
require(credentials.redirectUri != null && credentials.clientId != null) { "You didn't specify a redirect uri or client id in the credentials block!" }
554-
return SpotifyApi.getAuthUrlFull(*scopes, clientId = credentials.clientId!!, redirectUri = credentials.redirectUri!!)
570+
return SpotifyApi.getAuthUrlFull(
571+
*scopes,
572+
clientId = credentials.clientId!!,
573+
redirectUri = credentials.redirectUri!!,
574+
state = state
575+
)
555576
}
556577

557578
override suspend fun suspendBuild(): SpotifyClientApi {

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,18 @@ sealed class SpotifyApi<T : SpotifyApi<T, B>, B : ISpotifyApiBuilder<T, B>>(
187187
* @param scopes The scopes that the application should have access to
188188
* @param redirectUri The redirect uri specified on the Spotify developer dashboard; where to
189189
* redirect the browser after authentication
190+
* @param state This provides protection against attacks such as cross-site request forgery.
190191
*
191192
* @return Authorization URL that can be used in a browser
192193
*/
193-
fun getAuthorizationUrl(vararg scopes: SpotifyScope, redirectUri: String): String {
194+
fun getAuthorizationUrl(vararg scopes: SpotifyScope, redirectUri: String, state: String? = null): String {
194195
require(clientId != null)
195-
return getAuthUrlFull(*scopes, clientId = clientId, redirectUri = redirectUri)
196+
return getAuthUrlFull(
197+
*scopes,
198+
clientId = clientId,
199+
redirectUri = redirectUri,
200+
state = state
201+
)
196202
}
197203

198204
/**
@@ -248,11 +254,20 @@ sealed class SpotifyApi<T : SpotifyApi<T, B>, B : ISpotifyApiBuilder<T, B>>(
248254
* @param scopes Spotify scopes the api instance should be able to access for the user
249255
* @param clientId Spotify [client id](https://developer.spotify.com/documentation/general/guides/app-settings/)
250256
* @param redirectUri Spotify [redirect uri](https://developer.spotify.com/documentation/general/guides/app-settings/)
257+
* @param state This provides protection against attacks such as cross-site request forgery.
251258
*/
252-
fun getAuthUrlFull(vararg scopes: SpotifyScope, clientId: String, redirectUri: String, isImplicitGrantFlow: Boolean = false, shouldShowDialog: Boolean = false): String {
259+
fun getAuthUrlFull(
260+
vararg scopes: SpotifyScope,
261+
clientId: String,
262+
redirectUri: String,
263+
isImplicitGrantFlow: Boolean = false,
264+
shouldShowDialog: Boolean = false,
265+
state: String? = null
266+
): String {
253267
return "https://accounts.spotify.com/authorize/?client_id=$clientId" +
254268
"&response_type=${if (isImplicitGrantFlow) "token" else "code"}" +
255269
"&redirect_uri=$redirectUri" +
270+
(state?.let { "&state=$it" } ?: "") +
256271
if (scopes.isEmpty()) "" else "&scope=${scopes.joinToString("%20") { it.uri }}" +
257272
if (shouldShowDialog) "&show_dialog=$shouldShowDialog" else ""
258273
}
@@ -589,9 +604,9 @@ open class SpotifyClientApi internal constructor(
589604
*
590605
* @return Authorization URL that can be used in a browser
591606
*/
592-
fun getAuthorizationUrl(vararg scopes: SpotifyScope): String {
607+
fun getAuthorizationUrl(vararg scopes: SpotifyScope, state: String? = null): String {
593608
require(clientId != null && clientSecret != null) { "Either the client id or the client secret is not set" }
594-
return redirectUri?.let { getAuthUrlFull(*scopes, clientId = clientId, redirectUri = it) }
609+
return redirectUri?.let { getAuthUrlFull(*scopes, clientId = clientId, redirectUri = it, state = state) }
595610
?: throw IllegalArgumentException("The redirect uri must be set")
596611
}
597612

0 commit comments

Comments
 (0)