biscuit-auth / biscuit-java

Java implementation of the Biscuit authentication and authorization token
https://biscuitsec.org/
Apache License 2.0
28 stars 13 forks source link

Querying Facts returns types that are missing public accessors #69

Open time4tea opened 11 months ago

time4tea commented 11 months ago

Thanks for a nice library.

When querying facts on an authorizer, the returned types are com.clevercloud.biscuit.token.builder.Term - this class hierarchy does not have public accessors, so it is difficult to get the data out. (Except for Term.Str, which does have a getValue() )

e.g. https://github.com/biscuit-auth/biscuit-java/blame/master/src/main/java/com/clevercloud/biscuit/token/builder/Term.java#L84

minor: The toStrings look a little bit odd too, e.g. ""+value rather than String.valueOf(x)

sorry my test case is kotlin.

import com.clevercloud.biscuit.crypto.KeyPair
import com.clevercloud.biscuit.token.Biscuit
import com.clevercloud.biscuit.token.builder.Term
import org.junit.jupiter.api.Test
import strikt.api.expectThat
import strikt.assertions.isEqualTo

class BiscuitTest {

    val keypair = KeyPair()

    @Test
    fun `can put a fact in a biscuit and get it back out again`() {

        val token = Biscuit.builder(keypair)
            .add_authority_fact("""email("bob@example.com")""")
            .add_authority_fact("""id(123)""")
            .build()

        val tokenString = token.serialize_b64url().replace("=", "")

        val authorizer = Biscuit.from_b64url(tokenString, keypair.public_key())
            .verify(keypair.public_key())
            .authorizer()

        val email = authorizer.query("emailfact(\$name) <- email(\$name)")
            .first { it.name() == "emailfact" }
            .terms()
            .first()
            .stringValue()

        expectThat(email).isEqualTo("bob@example.com")

        val id = authorizer.query("idfact(\$name) <- id(\$name)")
            .first { it.name() == "idfact" }
            .terms()
            .first()
            .intValue()

        expectThat(id).isEqualTo(123)  // might not work is a Term.Integer an int or a long?
    }
}

fun Term.stringValue(): String {
    return when (this) {
        is Term.Str -> this.value
        else -> throw IllegalArgumentException("Can only call on Term.Str")
    }
}

fun Term.intValue(): Int {
    return when (this) {
        is Term.Integer -> this.value  // does not compile:- package-private, also, is a long?
        else -> throw IllegalArgumentException("Can only call on Term.Integer")
    }
}