diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2a75d8..e3bb12a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@ccb4328a959376b642e027874838f60f8e596de3 - name: Setup Gradle - uses: gradle/gradle-build-action@v3.4.2 + uses: gradle/gradle-build-action@v3.5.0 - name: Check lint run: ./gradlew lintDebug --stacktrace - name: Build diff --git a/README.md b/README.md index cddeb0c..5738afd 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ written for Android. You can read more on the [Descope Website](https://descope. Add the following to your `build.gradle` dependencies: ```groovy -implementation 'com.descope:descope-kotlin:0.10.0' +implementation 'com.descope:descope-kotlin:0.11.1' ``` ## Quickstart @@ -303,6 +303,9 @@ Descope.sessionManager.session?.run { runner.flowAuthentication = DescopeFlow.Authentication("flow-id", refreshJwt) } +// Optionally, you can customize the flow's presentation if needed +runner.flowPresentation = myFlowPresentation + // Starting an authentication flow runner.start(this@MainActivity) ``` diff --git a/build.gradle b/build.gradle index 126a8ba..396a3b9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,8 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { id "io.github.gradle-nexus.publish-plugin" version "1.3.0" - id "com.android.library" version "8.5.0" apply false - id "org.jetbrains.kotlin.android" version "2.0.0" apply false + id "com.android.library" version "8.5.2" apply false + id "org.jetbrains.kotlin.android" version "1.9.25" apply false } nexusPublishing { diff --git a/descopesdk/build.gradle b/descopesdk/build.gradle index 2555741..3f401c5 100644 --- a/descopesdk/build.gradle +++ b/descopesdk/build.gradle @@ -41,8 +41,8 @@ android { dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1" - implementation "androidx.lifecycle:lifecycle-common:2.8.3" - implementation "androidx.lifecycle:lifecycle-process:2.8.3" + implementation "androidx.lifecycle:lifecycle-common:2.8.4" + implementation "androidx.lifecycle:lifecycle-process:2.8.4" implementation "androidx.browser:browser:1.8.0" implementation "androidx.security:security-crypto:1.0.0" implementation "androidx.credentials:credentials:1.2.2" diff --git a/descopesdk/src/main/java/com/descope/internal/routes/Flow.kt b/descopesdk/src/main/java/com/descope/internal/routes/Flow.kt index 29f556a..3d48657 100644 --- a/descopesdk/src/main/java/com/descope/internal/routes/Flow.kt +++ b/descopesdk/src/main/java/com/descope/internal/routes/Flow.kt @@ -35,8 +35,9 @@ internal class Flow( private lateinit var codeVerifier: String + override var flowPresentation: DescopeFlow.Presentation? = null override var flowAuthentication: DescopeFlow.Authentication? = null - + override suspend fun start(context: Context) { log(Info, "Starting flow", flowUrl) val codeChallenge = initVerifierAndChallenge() @@ -73,7 +74,7 @@ internal class Flow( override fun exchange(incomingUri: Uri, callback: (Result) -> Unit) = wrapCoroutine(callback) { exchange(incomingUri) } - + // Internal private fun initVerifierAndChallenge(): String { @@ -91,7 +92,7 @@ internal class Flow( // codeChallenge == base64(sha256(randomBytes)) return hashed.toBase64() } - + private fun startFlowViaBrowser(codeChallenge: String, context: Context) { val uriBuilder = Uri.parse(flowUrl).buildUpon() .appendQueryParameter("ra-callback", deepLinkUrl) @@ -106,15 +107,22 @@ internal class Flow( launchUri(context, uri) } + private fun launchUri(context: Context, uri: Uri) { + val customTabsIntent = flowPresentation?.createCustomTabsIntent(context) ?: defaultCustomTabIntent() + customTabsIntent.launchUrl(context, uri) + } + } } -private fun launchUri(context: Context, uri: Uri) { - val customTabsIntent = CustomTabsIntent.Builder() +private fun defaultCustomTabIntent(): CustomTabsIntent { + return CustomTabsIntent.Builder() .setUrlBarHidingEnabled(true) .setShowTitle(true) .setShareState(CustomTabsIntent.SHARE_STATE_OFF) + .setBookmarksButtonEnabled(false) + .setDownloadButtonEnabled(false) + .setInstantAppsEnabled(false) .build() - customTabsIntent.launchUrl(context, uri) } diff --git a/descopesdk/src/main/java/com/descope/sdk/Routes.kt b/descopesdk/src/main/java/com/descope/sdk/Routes.kt index 358a613..0060db7 100644 --- a/descopesdk/src/main/java/com/descope/sdk/Routes.kt +++ b/descopesdk/src/main/java/com/descope/sdk/Routes.kt @@ -4,6 +4,7 @@ import android.content.Context import android.net.Uri import android.os.Build import androidx.annotation.RequiresApi +import androidx.browser.customtabs.CustomTabsIntent import com.descope.session.DescopeSession import com.descope.types.AuthenticationResponse import com.descope.types.DeliveryMethod @@ -942,6 +943,9 @@ interface DescopeFlow { /** Optional authentication info to allow running flows for authenticated users */ var flowAuthentication: Authentication? + /** Optional overrides and customizations to the flow's presentation */ + var flowPresentation: Presentation? + /** * Start a user authentication flow from the current [context]. * @@ -989,6 +993,20 @@ interface DescopeFlow { fun exchange(incomingUri: Uri, callback: (Result) -> Unit) } + /** + * Customize the flow's presentation by implementing the [Presentation] interface. + */ + interface Presentation { + /** + * Provide your own [CustomTabsIntent] that will be used when [Runner.start] + * or [Runner.resume] are called. You can configure it to suit + * your application's presentation needs. + * @param context The context passed down to [Runner.start] or [Runner.resume] + * @return A [CustomTabsIntent]. Returning `null` will use the default custom tab intent. + */ + fun createCustomTabsIntent(context: Context): CustomTabsIntent? + } + /** * Provide authentication info if the flow is being run by an already * authenticated user. diff --git a/descopesdk/src/main/java/com/descope/sdk/Sdk.kt b/descopesdk/src/main/java/com/descope/sdk/Sdk.kt index 2c085ad..c4b2805 100644 --- a/descopesdk/src/main/java/com/descope/sdk/Sdk.kt +++ b/descopesdk/src/main/java/com/descope/sdk/Sdk.kt @@ -69,6 +69,6 @@ class DescopeSdk(context: Context, projectId: String, configure: DescopeConfig.( const val name = "DescopeAndroid" /** The Descope SDK version */ - const val version = "0.10.0" + const val version = "0.11.1" } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e644113..2c35211 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a441313..09523c0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index b740cf1..f5feea6 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 7101f8e..9b42019 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ##########################################################################