Ignore Unknown Claim
I've encounter a issue today with the library and unknown claim that is a bit related to #2 and #4. The new Draft of JWT(https://tools.ietf.org/html/draft-ietf-oauth-amr-values-03) that came out last week add a new claim that have already been implemented by major vendor, namely auth0.
Suddenly all my api were rejecting a valid JWT token, which is not something that I would expect.
According to the specification unknown claim should be ignored (https://tools.ietf.org/html/rfc7519) :
The set of claims that a JWT must contain to be considered valid is context dependent and is outside the scope of this specification. Specific applications of JWTs will require implementations to understand and process some claims in particular ways. However, in the absence of such requirements, all claims that are not understood by implementations MUST be ignored.
Is It something that you were aware?
Seconding this. I think that a desirable behavior would be something like: Unregistered, and unrequired claims are ignored. Registered, unrequired, and unignored claims are checked if present. Required and ignored claims behave obviously. I'd even take it a step further to modify the validation API to look something like
validateEncodedJwt(
jwt: String,
key: String,
requiredAlg: Algorithm,
requiredHeaders: Set[HeaderField],
requiredClaims: Set[ClaimValidation],
ignoredHeaders: Set[String] = Set(),
ignoredClaims: Set[String] = Set(),
charset: String = "UTF-8"
)
case class Iss(value: String) extends ClaimValue with ClaimValidation {
override val field: ClaimField = Iss
override val jsValue: JsValue = JsString(value)
override def validate(otherValue: Any) = value.equals(otherValue)
}
case object Exp extends ClaimField with ClaimValidation{
override def attemptApply(value: JsValue): Option[ClaimValue] =
value.asOpt[Long].map(apply)
override val name = "exp"
override def validate(value: Any) = value match {
case time: Long if System.currentTimeMillis / 1000 < time => true
case _ => false
}
}
which could be used like this
DecodedJwt.validateEncodedJwt(
jwt,
"secret",
Algorithm.HS256,
Set(Typ),
Set((Iss("readme"), Exp)
)
this also opens up more flexibility for custom validation like
class ExpValidatorWithClock(clock: Clock) extends ClaimValidation {
val name = "exp"
def validate(value: Any) = value match {
case time: Long if Instant.now(clock).getEpochSecond < time => true
case _ => false
}
}
I'd be open to making a PR for this change if you're interested.