All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.toolsplus.atlassian.jwt.JwtParser.scala Maven / Gradle / Ivy

The newest version!
package io.toolsplus.atlassian.jwt

import cats.syntax.either._
import com.nimbusds.jose.JWSObject
import com.nimbusds.jwt._
import net.minidev.json.JSONObject

import scala.util.{Failure, Success, Try}

object JwtParser {

  final def parse(input: String): Either[ParsingFailure, Jwt] =
    for {
      jwsObject <- parseJWSObject(input)
      claims <- parseJWTClaimsSet(jwsObject.getPayload.toJSONObject)
    } yield Jwt(jwsObject, claims)

  final def parseJWSObject(input: String): Either[ParsingFailure, JWSObject] = {
    Try(JWSObject.parse(input)) match {
      case Success(jwsObject) => Right(jwsObject)
      case Failure(exception) =>
        val message = Option(exception.getMessage).getOrElse("Parsing JWS object failed")
        Left(ParsingFailure(message, exception))
    }
  }

  final def parseJWTClaimsSet(
      json: JSONObject): Either[ParsingFailure, JWTClaimsSet] = {
    Try(JWTClaimsSet.parse(json)) match {
      case Success(claims) => Right(claims)
      case Failure(exception) =>
        Left(ParsingFailure(claimParsingFailureDetails(exception), exception))
    }
  }

  final def claimParsingFailureDetails(exception: Throwable): String = {
    def toClaimName(message: String): String = message
      .replace(JwtParser.UnexpectedTypeMessagePrefix, "")
      .replaceAll("\"", "")

    def failureDetails(claimName: String): String = {
      if (JwtParser.NumericClaimNames.contains(claimName))
        s"Expecting claim '$claimName' to be numeric but it is a string"
      else
        s"Perhaps a claim is of the wrong type (e.g. expecting integer but found string): ${exception.getMessage}"
    }

    Option(exception.getMessage)
      .filter(_.startsWith(JwtParser.UnexpectedTypeMessagePrefix))
      .map(message => failureDetails(toClaimName(message)))
      .getOrElse("Parsing claims failed")
  }

  private val UnexpectedTypeMessagePrefix: String =
    "Unexpected type of JSON object member with key "

  private val NumericClaimNames: Set[String] = Set("exp", "iat", "nbf")

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy