polyvariant / sttp-oauth2

OAuth2 client library implemented in Scala using sttp
https://sttp-oauth2.polyvariant.org
Apache License 2.0
73 stars 22 forks source link

Optional scope not working as expected #486

Closed stefanosbou closed 3 months ago

stefanosbou commented 4 months ago

Hi there!

I'm reaching out because I've been experimenting with the sttp-oauth2 library for the Client Credentials flow, and initially, it seemed like the perfect fit for my project. However, I've encountered a small hiccup that I could really use your help with.

It appears that when attempting to authenticate against my OAuth provider, which doesn't require a specific scope, I'm running into an error. Despite following the documentation and passing val scope: Option[Scope] = Option.empty, I'm consistently met with the following error message: Predicate failed: "" matches ValidScope.

I'm curious if there might be a bug lurking or if there's something crucial I'm overlooking in my implementation. As a temporary workaround to get things moving, I took the liberty of modifying the scopeRegex to private val scopeRegex = """^((\x21|[\x23-\x5b]|[\x5d-\x7e])+(\s(\x21|[\x23-\x5b]|[\x5d-\x7e])+)*$)?""".

Any guidance or suggestions you could offer would be immensely appreciated! 🙏

majk-p commented 3 months ago

Thanks for reporting @stefanosbou! I just had a quick look at it and I have a guess what might be the reason for the error.

Current definition for scope looks like this:

object ValidScope {
  private val scopeRegex = """^(\x21|[\x23-\x5b]|[\x5d-\x7e])+(\s(\x21|[\x23-\x5b]|[\x5d-\x7e])+)*$"""

  implicit def scopeValidate: Validate.Plain[String, ValidScope] =
    Validate.fromPredicate(_.matches(scopeRegex), scope => s""""$scope" matches ValidScope""", ValidScope())

}

type Scope = String Refined ValidScope

We use that to derive circe Decoder for types like AccessTokenResponse. The decoder derivation takes the validation logic and lifts it to option. This means we'll roughly do something like this:

That fails in case we have "" which apparently some oauth providers do. What I think we should be doing in the lib instead, is introduce a fallback decoder that will accept empty string and turn it into Option[Scope].empty.

majk-p commented 3 months ago

Fix released in https://github.com/polyvariant/sttp-oauth2/releases/tag/v0.19.1