Skip to content
Open
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 @@ -117,6 +117,7 @@ class AuthProvider(
private fun getQueryParams(parResponse: PARResponse) = buildMap {
parResponse.requestUri.takeIf { it.isNotEmpty() }?.let { put(REQUEST_URI, it) }
authContext.prompt?.let { put(UriConfig.PROMPT_PARAM, it.value) }
authContext.nonce?.let { put(UriConfig.NONCE_PARAM, it) }
if (authContext.authType is AuthType.PKCE) {
val codeChallenge = codeVerifierGenerator.generateCodeChallenge(verifier)
put(CODE_CHALLENGE_PARAM, codeChallenge)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ import kotlinx.parcelize.Parcelize
* @param environment The [UriConfig.UberEnvironment] to target for OAuth flows. Defaults to
* [UriConfig.UberEnvironment.PRODUCTION]. Use [UriConfig.UberEnvironment.SANDBOX] to target
* Uber's sandbox environment for development and testing.
* @param nonce An optional, opaque, single-use string sent on the `/authorize` request. Required by
* the server when `openid` is one of the requested scopes; the same value is returned as the
* `nonce` claim of the issued ID token and must be validated by the caller's backend to mitigate
* token replay. The SDK does not generate, store, or validate the value — it only forwards it.
*/
@Parcelize
data class AuthContext
Expand All @@ -45,4 +49,5 @@ constructor(
val prefillInfo: PrefillInfo? = null,
val prompt: Prompt? = null,
val environment: UriConfig.UberEnvironment = UriConfig.UberEnvironment.PRODUCTION,
val nonce: String? = null,
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,40 @@ class AuthProviderTest : RobolectricTestBase() {
assert((result as AuthResult.Success).uberToken.authCode == "authCode")
}

@Test
fun `test authenticate when nonce is present should forward it as query param`() = runTest {
whenever(ssoLink.execute(any())).thenReturn("authCode")
whenever(authService.loginParRequest(any(), any(), any(), any()))
.thenReturn(Response.success(PARResponse("requestUri", "codeVerifier")))
val authContext =
AuthContext(
AuthDestination.CrossAppSso(listOf(CrossApp.Rider)),
AuthType.AuthCode,
null,
nonce = "n-0S6_WzA2Mj",
)
val authProvider = AuthProvider(activity, authContext, authService, codeVerifierGenerator)
val argumentCaptor = argumentCaptor<Map<String, String>>()
val result = authProvider.authenticate()
verify(ssoLink).execute(argumentCaptor.capture())
assert(argumentCaptor.lastValue[UriConfig.NONCE_PARAM] == "n-0S6_WzA2Mj")
assert(result is AuthResult.Success)
}

@Test
fun `test authenticate when nonce is absent should not include nonce query param`() = runTest {
whenever(ssoLink.execute(any())).thenReturn("authCode")
whenever(authService.loginParRequest(any(), any(), any(), any()))
.thenReturn(Response.success(PARResponse("requestUri", "codeVerifier")))
val authContext =
AuthContext(AuthDestination.CrossAppSso(listOf(CrossApp.Rider)), AuthType.AuthCode, null)
val authProvider = AuthProvider(activity, authContext, authService, codeVerifierGenerator)
val argumentCaptor = argumentCaptor<Map<String, String>>()
authProvider.authenticate()
verify(ssoLink).execute(argumentCaptor.capture())
assert(argumentCaptor.lastValue.containsKey(UriConfig.NONCE_PARAM).not())
}

@Test
fun `test authenticate when PAR request fails should continue without metadata`() = runTest {
whenever(ssoLink.execute(any())).thenReturn("authCode")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,5 @@ object UriConfig {
const val CODE_CHALLENGE_METHOD = "code_challenge_method"
const val CODE_CHALLENGE_METHOD_VAL = "S256"
const val PROMPT_PARAM = "prompt"
const val NONCE_PARAM = "nonce"
}
Loading