Skip to content

Commit

Permalink
Use URL encoding for authentication header values
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsvanvelzen committed Aug 14, 2022
1 parent 3a42563 commit 1b336e8
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package org.jellyfin.sdk.api.client.util

import io.ktor.http.encodeURLParameter

public object AuthorizationHeaderBuilder {
public const val AUTHORIZATION_SCHEME: String = "MediaBrowser"

public fun encodeParameterValue(raw: String): String = raw
// Trim whitespace
.trim()
// Remove characters not allowed in HTTP headers
.replace(Regex("""[^\x20-\x7e]"""), "?")
// Remove characters that might break serverside parsing
.replace(Regex("""[=,"]"""), "?")
public fun encodeParameterValue(raw: String): String = raw.encodeURLParameter(
spaceToPlus = true
)

public fun buildParameter(key: String, value: String): String {
// Check for bad strings to prevent endless hours debugging why the server throws http 500 errors
Expand All @@ -22,18 +20,9 @@ public object AuthorizationHeaderBuilder {
require(!key.startsWith('"') && !key.endsWith('"')) {
"Key $key can not start or end with the \" character in the authorization header"
}
require(!value.contains('=')) {
"Value $value (for key $key) can not contain the = character in the authorization header"
}
require(!value.contains(',')) {
"Value $value (for key $key) can not contain the , character in the authorization header"
}
require(!value.startsWith('"') && !value.endsWith('"')) {
"Value $value (for key $key) can not start or end with the \" character in the authorization header"
}

// key="value"
return """${key}="$value""""
return """${key}="${encodeParameterValue(value)}""""
}

public fun buildHeader(
Expand All @@ -47,9 +36,7 @@ public object AuthorizationHeaderBuilder {
"Client" to clientName,
"Version" to clientVersion,
"DeviceId" to deviceId,
// Only encode the device name as it is user input
// other fields should be validated manually by the client
"Device" to encodeParameterValue(deviceName),
"Device" to deviceName,
"Token" to accessToken
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package org.jellyfin.sdk.api.client.util

import io.kotest.core.spec.style.FunSpec
import io.kotest.data.forAll
import io.kotest.data.row
import io.kotest.matchers.shouldBe

class AuthorizationHeaderBuilderTests : FunSpec({
test("encodeParameter removes special characters") {
AuthorizationHeaderBuilder.encodeParameterValue("""test""") shouldBe "test"
AuthorizationHeaderBuilder.encodeParameterValue("""test+""") shouldBe "test+"
AuthorizationHeaderBuilder.encodeParameterValue("""'test'""") shouldBe "'test'"
AuthorizationHeaderBuilder.encodeParameterValue("""今日は""") shouldBe "???"
AuthorizationHeaderBuilder.encodeParameterValue("""水母""") shouldBe "??"
AuthorizationHeaderBuilder.encodeParameterValue("""ἈᾼᾺΆᾍᾋ""") shouldBe "??????"
forAll(
row("""test""", "test"),
row("""test+""", "test%2B"),
row("""'test'""", "%27test%27"),
row("""今日は""", "%E4%BB%8A%E6%97%A5%E3%81%AF"),
row("""水母""", "%E6%B0%B4%E6%AF%8D"),
row("""ἈᾼᾺΆᾍᾋ""", "%E1%BC%88%E1%BE%BC%E1%BE%BA%E1%BE%BB%E1%BE%8D%E1%BE%8B"),
) { a, b -> AuthorizationHeaderBuilder.encodeParameterValue(a) shouldBe b }
}

test("buildParameter creates a valid header with access token") {
Expand Down

0 comments on commit 1b336e8

Please sign in to comment.