Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: JWT id check #1487

Merged
merged 3 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ internal class VerifyClient(
}
}

override fun resolveV2(attestation: String, metadataUrl: String, onSuccess: (VerifyResult) -> Unit, onError: (Throwable) -> Unit) {
override fun resolveV2(attestationId: String, attestationJWT: String, metadataUrl: String, onSuccess: (VerifyResult) -> Unit, onError: (Throwable) -> Unit) {
try {
verifyRepository.resolveV2(attestation, metadataUrl, onSuccess, onError)
verifyRepository.resolveV2(attestationId, attestationJWT, metadataUrl, onSuccess, onError)
} catch (e: Exception) {
onError(e)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ interface VerifyInterface {
fun initialize()
fun register(attestationId: String, onSuccess: () -> Unit, onError: (Throwable) -> Unit)
fun resolve(attestationId: String, metadataUrl: String, onSuccess: (VerifyResult) -> Unit, onError: (Throwable) -> Unit)
fun resolveV2(attestation: String, metadataUrl: String, onSuccess: (VerifyResult) -> Unit, onError: (Throwable) -> Unit)
fun resolveV2(attestationId: String, attestationJWT: String, metadataUrl: String, onSuccess: (VerifyResult) -> Unit, onError: (Throwable) -> Unit)
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class ResolveAttestationIdUseCase(private val verifyInterface: VerifyInterface,
request: WCRequest,
onResolve: (VerifyContext) -> Unit
) {
verifyInterface.resolveV2(request.attestation!!, metadataUrl,
verifyInterface.resolveV2(sha256(request.encryptedMessage.toByteArray()), request.attestation!!, metadataUrl,
onSuccess = { result ->
insertContext(VerifyContext(request.id, result.origin, result.validation, verifyUrl, result.isScam)) { verifyContext -> onResolve(verifyContext) }
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal class VerifyRepository(
}
}

fun resolveV2(attestationJWT: String, metadataUrl: String, onSuccess: (VerifyResult) -> Unit, onError: (Throwable) -> Unit) {
fun resolveV2(attestationId: String, attestationJWT: String, metadataUrl: String, onSuccess: (VerifyResult) -> Unit, onError: (Throwable) -> Unit) {
scope.launch {
supervisorScope {
getVerifyPublicKey().fold(
Expand All @@ -47,7 +47,7 @@ internal class VerifyRepository(
return@supervisorScope
}

onSuccess(VerifyResult(getValidation(claims, metadataUrl), claims.isScam, claims.origin))
checkIds(attestationId, claims, metadataUrl, onSuccess, onError)
} catch (e: Exception) {
onError(e)
}
Expand Down Expand Up @@ -78,6 +78,20 @@ internal class VerifyRepository(
}
}

private fun checkIds(
attestationId: String,
claims: VerifyClaims,
metadataUrl: String,
onSuccess: (VerifyResult) -> Unit,
onError: (Throwable) -> Unit
) {
if (attestationId != claims.id) {
resolve(attestationId, metadataUrl, onSuccess, onError)
} else {
onSuccess(VerifyResult(getValidation(claims, metadataUrl), claims.isScam, claims.origin))
}
}

private fun getValidation(claims: VerifyClaims, metadataUrl: String): Validation =
when {
!claims.isVerified || currentTimeInSeconds >= claims.expiration -> Validation.UNKNOWN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.walletconnect.utils.Empty
import io.mockk.Runs
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.invoke
import io.mockk.just
import io.mockk.mockk
import io.mockk.verify
Expand Down Expand Up @@ -77,8 +78,8 @@ class ResolveAttestationUseCaseTest {
isScam = false
)

coEvery { verifyInterface.resolveV2(any(), any(), any(), any()) } answers {
thirdArg<(VerifyResult) -> Unit>().invoke(result)
coEvery { verifyInterface.resolveV2(any(), any(), any(), captureLambda(), any()) } answers {
lambda<(VerifyResult) -> Unit>().invoke(result)
}

coEvery { repository.insertOrAbort(any()) } just Runs
Expand All @@ -90,7 +91,7 @@ class ResolveAttestationUseCaseTest {
}

coVerify {
verifyInterface.resolveV2("jwt", metadataUrl, any(), any())
verifyInterface.resolveV2(any(), "jwt", metadataUrl, any(), any())
}
coVerify {
repository.insertOrAbort(withArg { context ->
Expand Down Expand Up @@ -121,8 +122,8 @@ class ResolveAttestationUseCaseTest {
)
val metadataUrl = "https://metadata.url"

coEvery { verifyInterface.resolveV2(any(), any(), any(), any()) } answers {
thirdArg<(VerifyResult) -> Unit>().invoke(result)
coEvery { verifyInterface.resolveV2(any(), any(), any(), captureLambda(), any()) } answers {
lambda<(VerifyResult) -> Unit>().invoke(result)
}

coEvery { repository.insertOrAbort(any()) } just Runs
Expand All @@ -134,7 +135,7 @@ class ResolveAttestationUseCaseTest {
}

coVerify {
verifyInterface.resolveV2("jwt", metadataUrl, any(), any())
verifyInterface.resolveV2(any(), "jwt", metadataUrl, any(), any())
}
coVerify {
repository.insertOrAbort(withArg { context ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class VerifyClientTest {
val onSuccess = mockk<(VerifyResult) -> Unit>(relaxed = true)
val onError = mockk<(Throwable) -> Unit>(relaxed = true)

verifyClient.resolveV2(attestation, metadataUrl, onSuccess, onError)
verifyClient.resolveV2("id", attestation, metadataUrl, onSuccess, onError)

coVerify { verifyRepository.resolveV2(attestation, metadataUrl, onSuccess, onError) }
coVerify { verifyRepository.resolveV2("id", attestation, metadataUrl, onSuccess, onError) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ class VerifyRepositoryTest {
coVerify { verifyPublicKeyStorageRepository.upsertPublicKey(newKey, any()) }
}


@Test
fun `resolveV2 calls onSuccess when JWT is valid`() = testScope.runTest {
fun `resolveV2 calls onSuccess when JWT is valid and ids match`() = testScope.runTest {
val attestationId = "5106a25552e89acfb5bed83ee21bf4e80dbcd51b0b203f6925a369aacb1c860b"
val attestationJWT = "attestationJWT"
val metadataUrl = "https://metadata.url"
val publicKey = "0409b2f80ce60e6f59ed77ef0e984c4efa84b40d608c0b4d039edaf2989a01f2d92931708c7b50c464c347dd55b0eca971d05fbdba3ab00323e69e166fef61440d"
Expand All @@ -93,7 +95,38 @@ class VerifyRepositoryTest {
val onSuccess = mockk<(VerifyResult) -> Unit>(relaxed = true)
val onError = mockk<(Throwable) -> Unit>(relaxed = true)

verifyRepository.resolveV2(attestationJWT, metadataUrl, onSuccess, onError)
verifyRepository.resolveV2(attestationId, attestationJWT, metadataUrl, onSuccess, onError)

advanceUntilIdle()

verify { onSuccess(verifyResult) }
}

@Test
fun `resolveV2 calls onSuccess when JWT is valid and ids do not match`() = testScope.runTest {
val attestationId = "test"
val attestationJWT = "attestationJWT"
val metadataUrl = "https://metadata.url"
val publicKey = "0409b2f80ce60e6f59ed77ef0e984c4efa84b40d608c0b4d039edaf2989a01f2d92931708c7b50c464c347dd55b0eca971d05fbdba3ab00323e69e166fef61440d"
val verifyResult = VerifyResult(Validation.INVALID, false, "https://react-dapp-v2-git-chore-verify-v2-samples-walletconnect1.vercel.app")
val claimsJson =
"""{"exp":1722579908,"id":"5106a25552e89acfb5bed83ee21bf4e80dbcd51b0b203f6925a369aacb1c860b","origin":"https://react-dapp-v2-git-chore-verify-v2-samples-walletconnect1.vercel.app","isScam":null,"isVerified":true}"""
jakubuid marked this conversation as resolved.
Show resolved Hide resolved

coEvery { verifyPublicKeyStorageRepository.getPublicKey() } returns Pair(publicKey, currentTimeInSeconds + 1000)
every { jwtRepository.verifyJWT(any(), any()) } returns true
every { jwtRepository.decodeClaimsJWT(any()) } returns claimsJson
coEvery { verifyService.resolveAttestation(attestationId) } returns Response.success(
Origin(
"attId",
origin = "https://react-dapp-v2-git-chore-verify-v2-samples-walletconnect1.vercel.app",
isScam = false
)
)

val onSuccess = mockk<(VerifyResult) -> Unit>(relaxed = true)
val onError = mockk<(Throwable) -> Unit>(relaxed = true)

verifyRepository.resolveV2(attestationId, attestationJWT, metadataUrl, onSuccess, onError)

advanceUntilIdle()

Expand Down
Loading