From 63fac072a9726dd6208cc7d21419e7030df4bca8 Mon Sep 17 00:00:00 2001 From: lalwani Date: Wed, 3 Jul 2024 13:23:40 -0700 Subject: [PATCH] added prompt for sso authorization --- .../uber/sdk2/auth/internal/AuthProvider.kt | 16 ++++------ .../com/uber/sdk2/auth/request/AuthContext.kt | 5 ++-- .../com/uber/sdk2/auth/request/Prompt.kt | 29 +++++++++++++++++++ .../sdk2/auth/internal/AuthProviderTest.kt | 25 ++++++++++++++++ .../com/uber/sdk2/core/config/UriConfig.kt | 1 + 5 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 authentication/src/main/kotlin/com/uber/sdk2/auth/request/Prompt.kt diff --git a/authentication/src/main/kotlin/com/uber/sdk2/auth/internal/AuthProvider.kt b/authentication/src/main/kotlin/com/uber/sdk2/auth/internal/AuthProvider.kt index fa75099..5d2e4be 100644 --- a/authentication/src/main/kotlin/com/uber/sdk2/auth/internal/AuthProvider.kt +++ b/authentication/src/main/kotlin/com/uber/sdk2/auth/internal/AuthProvider.kt @@ -99,16 +99,12 @@ class AuthProvider( } ?: PARResponse("", "") private fun getQueryParams(parResponse: PARResponse) = buildMap { - when (authContext.authType) { - AuthType.AuthCode -> { - parResponse.requestUri.takeIf { it.isNotEmpty() }?.let { put(REQUEST_URI, it) } - } - is AuthType.PKCE -> { - val codeChallenge = codeVerifierGenerator.generateCodeChallenge(verifier) - parResponse.requestUri.takeIf { it.isNotEmpty() }?.let { put(REQUEST_URI, it) } - put(CODE_CHALLENGE_PARAM, codeChallenge) - put(UriConfig.CODE_CHALLENGE_METHOD, UriConfig.CODE_CHALLENGE_METHOD_VAL) - } + parResponse.requestUri.takeIf { it.isNotEmpty() }?.let { put(REQUEST_URI, it) } + authContext.prompt?.let { put(UriConfig.PROMPT_PARAM, it.value) } + if (authContext.authType is AuthType.PKCE) { + val codeChallenge = codeVerifierGenerator.generateCodeChallenge(verifier) + put(CODE_CHALLENGE_PARAM, codeChallenge) + put(UriConfig.CODE_CHALLENGE_METHOD, UriConfig.CODE_CHALLENGE_METHOD_VAL) } } diff --git a/authentication/src/main/kotlin/com/uber/sdk2/auth/request/AuthContext.kt b/authentication/src/main/kotlin/com/uber/sdk2/auth/request/AuthContext.kt index 4f81bfb..0d3e9f7 100644 --- a/authentication/src/main/kotlin/com/uber/sdk2/auth/request/AuthContext.kt +++ b/authentication/src/main/kotlin/com/uber/sdk2/auth/request/AuthContext.kt @@ -23,8 +23,8 @@ import kotlinx.parcelize.Parcelize * * @param authDestination The destination app to authenticate the user. * @param authType The type of authentication to perform. - * @param prefillInfo The prefill information to be used for the authentication. - * @param scopes The scopes to request for the authentication. + * @param prefillInfo The prefill information to be used for the authentication. This is optional. + * @param prompt The [Prompt] to be used for the authentication. This is optional. */ @Parcelize data class AuthContext @@ -33,4 +33,5 @@ constructor( val authDestination: AuthDestination = AuthDestination.CrossAppSso(), val authType: AuthType = AuthType.PKCE(), val prefillInfo: PrefillInfo? = null, + val prompt: Prompt? = null, ) : Parcelable diff --git a/authentication/src/main/kotlin/com/uber/sdk2/auth/request/Prompt.kt b/authentication/src/main/kotlin/com/uber/sdk2/auth/request/Prompt.kt new file mode 100644 index 0000000..16aa41c --- /dev/null +++ b/authentication/src/main/kotlin/com/uber/sdk2/auth/request/Prompt.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.uber.sdk2.auth.request + +/** + * Represents the prompt parameter for the OAuth 2.0 authorization request. + * https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest:~:text=select_account-,The,-Authorization%20Server%20SHOULD + */ +enum class Prompt(val value: String) { + + /** The user will be prompted to login and authorize the app. */ + LOGIN("login"), + + /** The user will be prompted to authorize the app. */ + CONSENT("consent") +} diff --git a/authentication/src/test/kotlin/com/uber/sdk2/auth/internal/AuthProviderTest.kt b/authentication/src/test/kotlin/com/uber/sdk2/auth/internal/AuthProviderTest.kt index fffb384..c28ce6c 100644 --- a/authentication/src/test/kotlin/com/uber/sdk2/auth/internal/AuthProviderTest.kt +++ b/authentication/src/test/kotlin/com/uber/sdk2/auth/internal/AuthProviderTest.kt @@ -29,10 +29,12 @@ import com.uber.sdk2.auth.request.AuthDestination import com.uber.sdk2.auth.request.AuthType import com.uber.sdk2.auth.request.CrossApp import com.uber.sdk2.auth.request.PrefillInfo +import com.uber.sdk2.auth.request.Prompt import com.uber.sdk2.auth.response.AuthResult import com.uber.sdk2.auth.response.PARResponse import com.uber.sdk2.auth.response.UberToken import com.uber.sdk2.auth.sso.SsoLink +import com.uber.sdk2.core.config.UriConfig import com.uber.sdk2.core.config.UriConfig.CODE_CHALLENGE_METHOD import com.uber.sdk2.core.config.UriConfig.CODE_CHALLENGE_METHOD_VAL import com.uber.sdk2.core.config.UriConfig.CODE_CHALLENGE_PARAM @@ -113,6 +115,7 @@ class AuthProviderTest : RobolectricTestBase() { assert(argumentCaptor.firstValue[REQUEST_URI] == "requestUri") assert(argumentCaptor.firstValue[CODE_CHALLENGE_PARAM] == "challenge") assert(argumentCaptor.firstValue[CODE_CHALLENGE_METHOD] == CODE_CHALLENGE_METHOD_VAL) + assert(argumentCaptor.firstValue.containsValue(UriConfig.PROMPT_PARAM).not()) assert(argumentCaptor.firstValue.size == 3) assert(result is AuthResult.Success) assert((result as AuthResult.Success).uberToken.accessToken == "accessToken") @@ -169,4 +172,26 @@ class AuthProviderTest : RobolectricTestBase() { verify(ssoLink).execute(any()) assert(result is AuthResult.Error && result.authException.message == "error") } + + @Test + fun `test authenticate when prompt param is present should add to 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, + prompt = Prompt.LOGIN, + ) + val authProvider = AuthProvider(activity, authContext, authService, codeVerifierGenerator) + val argumentCaptor = argumentCaptor>() + val result = authProvider.authenticate() + verify(authService, never()).token(any(), any(), any(), any(), any()) + verify(ssoLink).execute(argumentCaptor.capture()) + assert(argumentCaptor.lastValue[UriConfig.PROMPT_PARAM] == Prompt.LOGIN.value) + assert(result is AuthResult.Success) + assert((result as AuthResult.Success).uberToken.authCode == "authCode") + } } diff --git a/core/src/main/kotlin/com/uber/sdk2/core/config/UriConfig.kt b/core/src/main/kotlin/com/uber/sdk2/core/config/UriConfig.kt index 3a397eb..fd76c47 100644 --- a/core/src/main/kotlin/com/uber/sdk2/core/config/UriConfig.kt +++ b/core/src/main/kotlin/com/uber/sdk2/core/config/UriConfig.kt @@ -86,4 +86,5 @@ object UriConfig { const val REQUEST_URI = "request_uri" const val CODE_CHALLENGE_METHOD = "code_challenge_method" const val CODE_CHALLENGE_METHOD_VAL = "S256" + const val PROMPT_PARAM = "prompt" }