Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Oct 16 07:06
    scala-steward opened #324
  • Oct 15 15:17
    cdelmas opened #323
  • Oct 15 13:29
    cdelmas opened #322
  • Oct 09 15:35
    PipocaQuemada commented #321
  • Oct 09 14:48
    PipocaQuemada opened #321
  • Oct 01 03:55
    he9lin starred jmcardon/tsec
  • Sep 14 09:26
    ahjohannessen commented #319
  • Sep 14 09:25
    ahjohannessen synchronize #320
  • Sep 14 09:15
    ahjohannessen synchronize #319
  • Sep 10 09:39
    ahjohannessen commented #319
  • Sep 10 09:38
    ahjohannessen opened #320
  • Sep 10 09:29
    ahjohannessen commented #319
  • Sep 10 09:29
    ahjohannessen opened #319
  • Sep 01 14:51
    scala-steward opened #318
  • Aug 31 02:32
    scala-steward opened #317
  • Aug 28 07:55
    OliverHS starred jmcardon/tsec
  • Aug 26 07:42
    andyvl starred jmcardon/tsec
  • Aug 22 14:39
    scala-steward opened #316
  • Aug 22 04:39
    ahmed1hsn starred jmcardon/tsec
  • Aug 20 13:50
    Stefanqn starred jmcardon/tsec
Ivano Pagano
@ivanopagano
thank you @ChristopherDavenport I hoped so
James Cosford
@jamescosford

Excerpt from tsec.passwordhashers.PasswordHashAPI.scala

 /** Hash a password in a char array
  * then clear the data in the password original
  * array, as well as the byte encoding change,
  * but in a pure fashion because
  * side effects suck butt.
  *
  */
  def hashpw[F[_]](p: Array[Char])(implicit P: PasswordHasher[F, A]): F[PasswordHash[A]] = P.hashpw(p)

lost a couple of hours figuring out why my test was failing... The irony of having this code clearing the password data during my registration step so that the login step failed was too delicious to ignore. Side effects do suck butt.

Ryan Zeigler
@rzeigler
Does tsec support jdk8? I am seeing java.lang.UnsupportedClassVersionError: tsec/internal/CirceShim ... (class file version 55.0),...
But, this is only during tests, other bits appear to work fine
Jimin Hsieh
@jiminhsieh
@rzeigler I met the same situation before. You can checkout the meesage I left. I don’t know does it fix or not.
https://gitter.im/tsecc/Lobby?at=5dd24c7a50010612b2dc108b
Ender Tunc
@endertunc_gitlab
@rzeigler I remember I also had the same issue. I just updated to JDK11.
Ryan Zeigler
@rzeigler
ah
Christopher Davenport
@ChristopherDavenport
Hmm, I think it released on jdk11 so used whatever the new approach was which is very rarely incompatible.
I can see if we can instead release on jdk8 instead.
Ryan Zeigler
@rzeigler
that would be appreciated
Jacob Shao
@realradical
does anyone know what is partially stateless jwt auth?
sken
@sken77
hi guys
why is windows not supported?
or to be more precise. what parts of windows do not work
i just need bc wrappers. would that be fine?
Otto Chrons
@ochrons
secure random generation doesn't work on Windows
sken
@sken77
does BC uses that?
Zak Patterson
@zakpatterson
@ChristopherDavenport let me know if i can help out with jdk8 stuff - I pushed #299, which would require a little travis configuring. Also I put some similar work into cats-scalacheck yesterday.
sken
@sken77
is ecdsa signing on bouncy castle constant time?
i.e not vulnerable to side channel attacks
Loránd Szakács
@lorandszakacs

folks, correct me if I'm wrong, but does tsec 0.2.0 run only on Java 11?

Because I get this runtime error:

java.lang.UnsupportedClassVersionError: tsec/passwordhashers/jca/internal/JBCrypt has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0

And if so, is it intentional or an oversight? I'm using the scala 2.13 artifact

a, just noticed that @zakpatterson talked about the same thing :sweat_smile:
Christopher Davenport
@ChristopherDavenport
Yeah. I'm sorry.
I've been completely underwater.
Zak Patterson
@zakpatterson
@lorandszakacs you're welcome to try my fork released on jdk 8 for the time being
James Cosford
@jamescosford
Using tsec with http4s, how could I get tsec to accept a bearer token from a query parameter, rather than a header? For most routes it works perfect as-is, but for a websocket request I can't use the authorization header.
Alternatively I'm tinkering with requiring the client to pass the bearer token through the socket, but then there is no clear and simple way to verify it against the stored jwts, as far as I can see.
James Cosford
@jamescosford
In the end I didn't secure the websocket endpoint, but made a secure endpoint which returned a single use key to an authenticated client. The client then has to pass the key up through the websocket to unblock it.
If anyone know that to be an anti-pattern for some reason I haven't thought of, please educate me :)
Christopher Davenport
@ChristopherDavenport
0.2.1 released off java 8
Christopher Davenport
@ChristopherDavenport
Getting prepped to move this into my org for easier maintenance and management. I've been the only active maintainer for quite a while, and so getting it integrated with the rest of my toolchain will make for smoother and easier rollouts across the board as well as being centralized in my responses. Happy to discuss.
Also was considering calling it turtle as turtle is a secure animal that is still cute.
Rixamos
@Rixamos
Hello all, I am quite new in scala and tsec, I don't know even if this is the correct channel to ask my question, so sorry in advance.
I am trying to cipher (with AES256GMC) a string into a string and then decipher it back (simply cause the string will be stored somewhere) I used the cipherText.toConcatenated.toB64String to get a string, and then I am trying to get this String and convert it to a cipherText to give it to the decrypt every time I try some way I am getting "javax.crypto.AEADBadTagException: Tag mismatch!" so I suppose I converted wrongly the cipherText to String or the string back to cipherText.
If this is not the channel where to find this reply may someone suggest me where to look?
Thank you very much
Jonas Adler
@jadlr

@Rixamos it should look something like this:

import cats.effect.{ ExitCode, IO, IOApp }
import tsec.cipher.symmetric.{ AAD, AADEncryptor, IvGen }
import tsec.cipher.symmetric.jca.{ AES256GCM, SecretKey }
import tsec.common._
import tsec.cipher.symmetric._

object CrytoApp extends IOApp {

  private val aad: AAD = AAD("KnQCxy4rW4KuxMRcvkVvAs9KufF7XR4b".utf8Bytes)

  private implicit val ctrStrategy: IvGen[IO, AES256GCM]                      = AES256GCM.defaultIvStrategy[IO]
  private implicit val cachedInstance: AADEncryptor[IO, AES256GCM, SecretKey] = AES256GCM.genEncryptor[IO]

  override def run(args: List[String]): IO[ExitCode] =
    for {
      secretKey  <- AES256GCM.generateKey[IO]
      encrypted  <- AES256GCM.encryptWithAAD[IO](PlainText("I'm a secret".utf8Bytes), secretKey, aad)
      cipherText <- IO.fromEither(AES256GCM.ciphertextFromConcat(encrypted.toConcatenated))
      decrypted  <- AES256GCM.decryptWithAAD(cipherText, secretKey, aad)
      _          <- IO.delay(println(decrypted.toUtf8String))
    } yield ExitCode.Success
}

This program would print I'm a secret

Rixamos
@Rixamos
Hello @jadlr , thank you very very much
Jonas Adler
@jadlr
You're welcome
@Rixamos here's that same program also doing the base64 enc/dec you mentioned
import cats.effect.{ ExitCode, IO, IOApp }
import tsec.cipher.symmetric.{ AAD, AADEncryptor, IvGen }
import tsec.cipher.symmetric.jca.{ AES256GCM, SecretKey }
import tsec.common._
import tsec.cipher.symmetric._

object CrytoApp extends IOApp {

  private val aad: AAD = AAD("KnQCxy4rW4KuxMRcvkVvAs9KufF7XR4b".utf8Bytes)

  private implicit val ctrStrategy: IvGen[IO, AES256GCM]                      = AES256GCM.defaultIvStrategy[IO]
  private implicit val cachedInstance: AADEncryptor[IO, AES256GCM, SecretKey] = AES256GCM.genEncryptor[IO]

  override def run(args: List[String]): IO[ExitCode] =
    for {
      secretKey <- AES256GCM.generateKey[IO]
      encrypted <- AES256GCM.encryptWithAAD[IO](PlainText("I'm a secret".utf8Bytes), secretKey, aad)
      base64 = encrypted.toConcatenated.toB64String
      //you can store `base64` somewhere
      bytes      <- IO.fromOption(base64.b64Bytes)(new Exception("Could not decode base64"))
      cipherText <- IO.fromEither(AES256GCM.ciphertextFromConcat(bytes))
      decrypted  <- AES256GCM.decryptWithAAD(cipherText, secretKey, aad)
      _          <- IO.delay(println(decrypted.toUtf8String))
    } yield ExitCode.Success
}
Pere Villega
@pvillega
I'm having an odd problem: we have a service deployed in K8s, and log-in stops working after around 24h (either that or after midnight). We use Cookies with backend storage, to restrict sessions. When we try to log in a new cookie is generated (we can see it in the database) but it is rejected during authentication, when calling a secured endpoint (we get 401). Has anybody hit this issue before? It also happens in our UAT environment with a single node running, so it doesn't seem related to different nodes sharing the same GCM key
Jose C
@jmcardon
@pvillega is it timeout-related?
Pere Villega
@pvillega
sorry I completely missed the answer. It was a very stupid issue, but unrelated to Tsec. Auth0 (the login provider) made recently a policy change by which machine to machine tokens expire after 24 hours (before they lived 'forever' until next request) and as we cached that token to avoid calling the token endpoint over and over, we hit that issue
for the record, not Tsec related. Tsec is as awesome as usual. As expected it was a user problem :D
James Cosford
@jamescosford
I need to share my HMACSHA256 JWT signing key between multiple app instances, and since we are using AWS my intent was to put it in AWS Secrets Manager and have it available at runtime as an environment var. Since I'm using TSec, I was hoping to generate one with TSec which I can then use, but I can't get TSec to print the key... Is there any way to do it?
James Cosford
@jamescosford
Or should it just be a random string?
James Cosford
@jamescosford
After some experimentation, I found it can just be a random string.
Lance Walton
@lancewalton
Hi. Can I suggest adding something to https://jmcardon.github.io/tsec/docs/http4s-auth.html to indicate that when combining authed routes with <+>, we need to combine them as TSecAuthServices and then convert the resulting TSecAuthService to an HttpRoutes using SecurityHandler.liftService, rather than using SecurityHandler.liftService on each TSecAuthService and then combining the resulting HttpRoutes with <+>. If you do it the second way, you get 401s/404s for every authed route after the first one and it's not obvious what's happening.
Kai(luo) Wang
@kailuowang

@lancewalton I am tackling the same issue. I suspect that the root cause is here
https://github.com/jmcardon/tsec/blob/master/tsec-http4s/src/main/scala/tsec/authentication/package.scala#L128-L130

 def withAuthorizationFHandler[I, A, F[_]](auth: F[TAuth[F, I, A]])(
        pf: PartialFunction[SecuredRequest[F, I, A], F[Response[F]]],
        onNotAuthorized: SecuredRequest[F, I, A] => OptionT[F, Response[F]]
    )(implicit F: Monad[F]): TSecAuthService[I, A, F] =
      Kleisli { req: SecuredRequest[F, I, A] =>
        OptionT.liftF(auth).flatMap { auth =>
          auth
            .isAuthorized(req)
            .flatMap(_ => pf.andThen(OptionT.liftF(_)).applyOrElse(req, Function.const(OptionT.none[F, Response[F]])))
            .orElse(onNotAuthorized(req))
        }
      }

If I read it correctly, if the pf misses a path, instead of the path being picked up by some other routes after this route (or 404), it will simply go to onNotAuthorized handler, which by default returns a 401.

This is the behavior I am seeing.
ping @ChristopherDavenport , did I read the code wrong?
Kai(luo) Wang
@kailuowang
@lancewalton actually I realized that we are seeing different issues. Yours is about routes with authentication
you can find the doc here it actually described the behavior you are seeing.
My issue is about endpoints with authorization. And it basically means you can only have one type of Authorization if you use withAuthorizationFHandler
Kai(luo) Wang
@kailuowang
to follow up , I tweeked the withAuthorizationHandler to something like
def withAuthorizationHandler[I, A, F[_]](
      auth: tsec.authorization.Authorization[F, I, A]
    )(pf: PartialFunction[SecuredRequest[F, I, A], F[Response[F]]],
      onNotAuthorized: SecuredRequest[F, I, A] => OptionT[F, Response[F]]
    )(implicit F: cats.Monad[F]
    ): TSecAuthService[I, A, F] =
    Kleisli { req: SecuredRequest[F, I, A] =>
      if (pf.isDefinedAt(req))
        OptionT(
          auth
            .isAuthorized(req)
            .fold(onNotAuthorized(req))(pf.andThen(OptionT.liftF(_)))
            .flatMap(_.value)
        )
      else OptionT.none[F, Response[F]]
    }
Christopher Davenport
@ChristopherDavenport
This code never got an upgrade when httpApp was created.