I'm trying to add a JWT authentication to my Akka HTTP Scala application API.
I'm using the maven dependency modules jwt-circe
and jwt-core
from the maven repository.
However the current code is giving me the Type errors
:
case Some(jwtToken) if Jwt.isValid(jwtToken, secretKey, Seq(JwtAlgorithm.HS256))
Type Error: None of the overloaded alternatives of method isValid in trait JwtCore with types
.
onComplete(Jwt.decode(jwtToken, secretKey, Seq(JwtAlgorithm.HS256)))
Type Error: None of the overloaded alternatives of method decode in trait JwtCore with types
.
Again, I installed both the dependency modules jwt-circe
and jwt-core
(check the sbt
code).
Could you please help me identify the issue?
Thanks in advance!
My current code looks like below:
case classes:
final case class Account(name: String, age: Int, country: String, roles: List[String])
object JsonFormats {
import DefaultJsonProtocol._
implicit val accountFormat: RootJsonFormat[Account] = jsonFormat4(Account.apply)
The JWT Code:
import pdi.jwt.{ Jwt, JwtAlgorithm, JwtClaim, JwtCirce }
private val expiresIn = 1 * 24 * 60 * 60
implicit val clock: Clock = Clock.systemUTC
private val secretKey = "vp-akka-http-jwt"
def authenticated: Directive1[Account] =
optionalHeaderValueByName("Authorization").flatMap {
case Some(jwtToken) if Jwt.isValid(jwtToken, secretKey, Seq(JwtAlgorithm.HS256)) =>
getClaims(jwtToken) match {
case Some(account) => provide(account)
case None => reject(AuthorizationFailedRejection).toDirective[Tuple1[Account]]
}
case t => println(t.get)
complete(StatusCodes.Unauthorized)
}
private def getClaims(jwtToken: String): Option[Account] = {
onComplete(Jwt.decode(jwtToken, secretKey, Seq(JwtAlgorithm.HS256))){
case Success(value) =>
Some(value.content.parseJson.convertTo[Account])
case Failure(ex) => None
}
}
The SBT config:
lazy val akkaHttpVersion = "10.6.3"
lazy val akkaVersion = "2.9.4"
resolvers += "Akka library repository".at("https://repo.akka.io/maven")
fork := true
lazy val root = (project in file(".")).
settings(
inThisBuild(List(
organization := "com.example",
scalaVersion := "3.3.3"
)),
name := "eskimi-bidding-agent",
libraryDependencies ++= Seq(
// ....
("com.github.jwt-scala" %% "jwt-circe" % "10.0.1")
.exclude("io.circe", "circe-parser_3")
.exclude("io.circe", "circe-core_3")
.exclude("org.typelevel", "cats-kernel_3")
.exclude("org.typelevel", "cats-core_3")
.exclude("io.circe", "circe-numbers_3")
.exclude("org.typelevel", "jawn-parser_3")
.exclude("io.circe", "circe-jawn_3"),
"com.github.jwt-scala" %% "jwt-core" % "10.0.1",
// ....
)
)
The full code error:
This is the Jwt.isValid
error. It is very similar to the Jwt.decode
error.
Type Error:
case Some(jwtToken) if Jwt.isValid(jwtToken, secretKey, Seq(JwtAlgorithm.HS256))
None of the overloaded alternatives of method isValid in trait JwtCore with types
(token: String, key: java.security.PublicKey): Boolean
(token: String, key: java.security.PublicKey, options: pdi.jwt.JwtOptions): Boolean
(token: String, key: java.security.PublicKey, algorithms: Seq[pdi.jwt.algorithms.JwtAsymmetricAlgorithm]): Boolean
(token: String, key: java.security.PublicKey, algorithms: Seq[pdi.jwt.algorithms.JwtAsymmetricAlgorithm], options: pdi.jwt.JwtOptions): Boolean
(token: String, key: javax.crypto.SecretKey): Boolean
(token: String, key: javax.crypto.SecretKey, options: pdi.jwt.JwtOptions): Boolean
(token: String, key: javax.crypto.SecretKey, algorithms: Seq[pdi.jwt.algorithms.JwtHmacAlgorithm]): Boolean
(token: String, key: javax.crypto.SecretKey, algorithms: Seq[pdi.jwt.algorithms.JwtHmacAlgorithm], options: pdi.jwt.JwtOptions): Boolean
(token: String, key: String, algorithms: => Seq[pdi.jwt.algorithms.JwtAsymmetricAlgorithm]): Boolean
(token: String, key: String, algorithms: => Seq[pdi.jwt.algorithms.JwtAsymmetricAlgorithm], options: pdi.jwt.JwtOptions): Boolean
(token: String, key: String, algorithms: Seq[pdi.jwt.algorithms.JwtHmacAlgorithm]): Boolean
(token: String, key: String, algorithms: Seq[pdi.jwt.algorithms.JwtHmacAlgorithm], options: pdi.jwt.JwtOptions): Boolean
(token: String): Boolean
(token: String, options: pdi.jwt.JwtOptions): Boolean
match arguments ((jwtToken : String), (com.example.WebServer.secretKey : String), scala.collection.Seq[pdi.jwt.JwtAlgorithm.HS256.type])
It sounds like the library is expecting scala.collection.immutable.Seq
and you're providing scala.collection.Seq
. Or maybe the library accepts scala.collection.Seq
but you're having Seq
as an alias of a totally different type?
You can use scala.collection.immutable.Seq
explicitly and/or check your import
s statements.
You can read more about the 3 different scala.collection
packages (root, immutable
, mutable
) at https://docs.scala-lang.org/overviews/collections-2.13/overview.html.
:
A collection in package
scala.collection.immutable
is guaranteed to be immutable for everyone. (...)A collection in package
scala.collection.mutable
is known to have some operations that change the collection in place. (...)A collection in package
scala.collection
can be either mutable or immutable. (...) Generally, the root collections in packagescala.collection
support transformation operations affecting the whole collection, the immutable collections in packagescala.collection.immutable
typically add operations for adding or removing single values, and the mutable collections in packagescala.collection.mutable
typically add some side-effecting modification operations to the root interface.Another difference between root collections and immutable collections is that clients of an immutable collection have a guarantee that nobody can mutate the collection, whereas clients of a root collection only promise not to change the collection themselves. Even though the static type of such a collection provides no operations for modifying the collection, it might still be possible that the run-time type is a mutable collection which can be changed by other clients.
By default, Scala always picks immutable collections.