@@ -32,6 +32,7 @@ import com.google.firebase.dataconnect.testutil.UnavailableDeferred
3232import com.google.firebase.dataconnect.testutil.newBackgroundScopeThatAdvancesLikeForeground
3333import com.google.firebase.dataconnect.testutil.newMockLogger
3434import com.google.firebase.dataconnect.testutil.property.arbitrary.dataConnect
35+ import com.google.firebase.dataconnect.testutil.property.arbitrary.distinctPair
3536import com.google.firebase.dataconnect.testutil.shouldContainWithNonAbuttingText
3637import com.google.firebase.dataconnect.testutil.shouldContainWithNonAbuttingTextIgnoringCase
3738import com.google.firebase.dataconnect.testutil.shouldHaveLoggedAtLeastOneMessageContaining
@@ -46,15 +47,19 @@ import io.kotest.assertions.nondeterministic.eventually
4647import io.kotest.assertions.nondeterministic.eventuallyConfig
4748import io.kotest.assertions.throwables.shouldThrow
4849import io.kotest.assertions.withClue
50+ import io.kotest.matchers.collections.shouldBeEmpty
4951import io.kotest.matchers.collections.shouldContain
5052import io.kotest.matchers.collections.shouldContainExactly
53+ import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
5154import io.kotest.matchers.nulls.shouldBeNull
5255import io.kotest.matchers.nulls.shouldNotBeNull
5356import io.kotest.matchers.shouldBe
5457import io.kotest.matchers.types.shouldBeSameInstanceAs
5558import io.kotest.property.Arb
5659import io.kotest.property.RandomSource
60+ import io.kotest.property.arbitrary.map
5761import io.kotest.property.arbitrary.next
62+ import io.kotest.property.arbs.products.brand
5863import io.mockk.coEvery
5964import io.mockk.confirmVerified
6065import io.mockk.every
@@ -311,6 +316,74 @@ class DataConnectAuthUnitTest {
311316 mockLogger.shouldNotHaveLoggedAnyMessagesContaining(accessToken)
312317 }
313318
319+ @Test
320+ fun `getToken() should populate authUids from user_id claim` () = runTest {
321+ val dataConnectAuth = newDataConnectAuth()
322+ dataConnectAuth.initialize()
323+ advanceUntilIdle()
324+ val uid = Arb .brand().map { it.value }.next(rs)
325+ coEvery { mockInternalAuthProvider.getAccessToken(any()) } returns
326+ taskForToken(accessToken, mapOf (" user_id" to uid))
327+
328+ val result = dataConnectAuth.getToken(requestId)
329+
330+ result.shouldNotBeNull().authUids.shouldContainExactly(uid)
331+ }
332+
333+ @Test
334+ fun `getToken() should populate authUids from sub claim` () = runTest {
335+ val dataConnectAuth = newDataConnectAuth()
336+ dataConnectAuth.initialize()
337+ advanceUntilIdle()
338+ val uid = Arb .brand().map { it.value }.next(rs)
339+ coEvery { mockInternalAuthProvider.getAccessToken(any()) } returns
340+ taskForToken(accessToken, mapOf (" sub" to uid))
341+
342+ val result = dataConnectAuth.getToken(requestId)
343+
344+ result.shouldNotBeNull().authUids.shouldContainExactly(uid)
345+ }
346+
347+ @Test
348+ fun `getToken() should populate authUids from user_id and sub claims` () = runTest {
349+ val dataConnectAuth = newDataConnectAuth()
350+ dataConnectAuth.initialize()
351+ advanceUntilIdle()
352+ val (uid1, uid2) = Arb .brand().map { it.value }.distinctPair().next(rs)
353+ coEvery { mockInternalAuthProvider.getAccessToken(any()) } returns
354+ taskForToken(accessToken, mapOf (" user_id" to uid1, " sub" to uid2))
355+
356+ val result = dataConnectAuth.getToken(requestId)
357+
358+ result.shouldNotBeNull().authUids.shouldContainExactlyInAnyOrder(uid1, uid2)
359+ }
360+
361+ @Test
362+ fun `getToken() should populate empty authUids if claims are missing` () = runTest {
363+ val dataConnectAuth = newDataConnectAuth()
364+ dataConnectAuth.initialize()
365+ advanceUntilIdle()
366+ coEvery { mockInternalAuthProvider.getAccessToken(any()) } returns
367+ taskForToken(accessToken, emptyMap())
368+
369+ val result = dataConnectAuth.getToken(requestId)
370+
371+ result.shouldNotBeNull().authUids.shouldBeEmpty()
372+ }
373+
374+ @Test
375+ fun `getToken() should ignore non-string uid claims` () = runTest {
376+ val dataConnectAuth = newDataConnectAuth()
377+ dataConnectAuth.initialize()
378+ advanceUntilIdle()
379+ coEvery { mockInternalAuthProvider.getAccessToken(any()) } returns
380+ taskForToken(accessToken, mapOf (" user_id" to 123 , " sub" to true ))
381+
382+ val result = dataConnectAuth.getToken(requestId)
383+
384+ result.shouldNotBeNull().authUids shouldBe emptySet()
385+ }
386+
314387 @Test
315388 fun `getToken() should return re-throw the exception from the task returned from FirebaseAuth` () =
316389 runTest {
@@ -613,7 +686,7 @@ class DataConnectAuthUnitTest {
613686 interval = 100 .milliseconds
614687 }
615688
616- fun taskForToken (token : String? ): Task <GetTokenResult > =
617- Tasks .forResult(mockk(relaxed = true ) { every { getToken() } returns token } )
689+ fun taskForToken (token : String? , claims : Map < String , Any > = emptyMap() ): Task <GetTokenResult > =
690+ Tasks .forResult(GetTokenResult ( token, claims) )
618691 }
619692}
0 commit comments