Skip to content

Commit

Permalink
fix: parse passwords with arbitrary number of colons
Browse files Browse the repository at this point in the history
  • Loading branch information
mobley-trent committed Nov 9, 2024
1 parent dc1f3f4 commit ee80e5c
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package zio.http.headers

import java.net.URI
import java.util.Base64

import zio.Scope
import zio.test._
Expand All @@ -26,6 +27,8 @@ import zio.http.Header.Authorization.Digest
import zio.http.ZIOHttpSpec

object AuthorizationSpec extends ZIOHttpSpec {
private def encodeCredentials(username: String, password: String): String =
Base64.getEncoder.encodeToString(s"$username:$password".getBytes)

override def spec: Spec[TestEnvironment with Scope, Any] =
suite("Authorization header suite")(
Expand Down Expand Up @@ -104,5 +107,15 @@ object AuthorizationSpec extends ZIOHttpSpec {
val auth = Authorization.parse("Basic not-base64")
assertTrue(auth.isLeft)
},
test("should parse valid Basic Authorization header") {
val encodedHeader = encodeCredentials("user", "pass")
val result = Authorization.parse(s"Basic $encodedHeader")
assert(result)(isRight(equalTo(Basic("user", Secret("pass")))))
},
test("should parse header with multiple colons in password") {
val encodedHeader = encodeCredentials("user", "pass:with:colon")
val result = Authorization.parse(s"Basic $encodedHeader")
assert(result)(isRight(equalTo(Basic("user", Secret("pass:with:colon")))))
},
)
}
11 changes: 8 additions & 3 deletions zio-http/shared/src/main/scala/zio/http/Header.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1088,9 +1088,14 @@ object Header {

private def parseBasic(value: String): Either[String, Authorization] = {
try {
val partsOfBasic = new String(Base64.getDecoder.decode(value)).split(":")
if (partsOfBasic.length == 2) {
Right(Basic(partsOfBasic(0), Secret(partsOfBasic(1))))
val decoded = new String(Base64.getDecoder.decode(value))
val indexOfColon = decoded.indexOf(":")

if (indexOfColon > 0) {
// Extract username as everything before the first ":", and password as everything after
val username = decoded.substring(0, indexOfColon)
val password = decoded.substring(indexOfColon + 1)
Right(Basic(username, Secret(password)))
} else {
Left("Basic Authorization header value is not in the format username:password")
}
Expand Down

0 comments on commit ee80e5c

Please sign in to comment.