Skip to content

Commit

Permalink
Add support for auth API v2 (#5305)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/1205648422731273/1208821656071388/f

### Description

This PR adds support for new version of the authentication API that uses
OAuth 2.0 with PKCE extension. Usage of the new API is controlled via a
feature flag which is currently disabled.

### Steps to test this PR

See task.

### No UI changes
  • Loading branch information
lmac012 authored Nov 27, 2024
1 parent 44bab05 commit dcebb5b
Show file tree
Hide file tree
Showing 32 changed files with 1,801 additions and 494 deletions.
3 changes: 0 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,6 @@ dependencies {

implementation project(':breakage-reporting-impl')

implementation project(":auth-jwt-api")
implementation project(":auth-jwt-impl")

// Deprecated. TODO: Stop using this artifact.
implementation "androidx.legacy:legacy-support-v4:_"
debugImplementation Square.leakCanary.android
Expand Down
Empty file removed auth-jwt/auth-jwt-api/.gitignore
Empty file.
67 changes: 0 additions & 67 deletions auth-jwt/auth-jwt-impl/build.gradle

This file was deleted.

9 changes: 0 additions & 9 deletions auth-jwt/readme.md

This file was deleted.

6 changes: 6 additions & 0 deletions subscriptions/subscriptions-impl/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ dependencies {
implementation Square.okHttp3.okHttp
implementation AndroidX.security.crypto

implementation "io.jsonwebtoken:jjwt-api:_"
runtimeOnly "io.jsonwebtoken:jjwt-impl:_"
runtimeOnly("io.jsonwebtoken:jjwt-orgjson:_") {
exclude(group: 'org.json', module: 'json') // provided by Android natively
}

// Testing dependencies
testImplementation project(':feature-toggles-test')
testImplementation project(path: ':common-test')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ interface PrivacyProFeature {

@Toggle.DefaultValue(false)
fun serpPromoCookie(): Toggle

@Toggle.DefaultValue(false)
fun authApiV2(): Toggle
}

@ContributesBinding(AppScope::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.work.Constraints
import androidx.work.CoroutineWorker
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequest
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.WorkerParameters
Expand All @@ -35,8 +36,8 @@ import com.duckduckgo.subscriptions.api.SubscriptionStatus.UNKNOWN
import com.duckduckgo.subscriptions.impl.RealSubscriptionsChecker.Companion.TAG_WORKER_SUBSCRIPTION_CHECK
import com.squareup.anvil.annotations.ContributesBinding
import com.squareup.anvil.annotations.ContributesMultibinding
import java.util.concurrent.TimeUnit.HOURS
import java.util.concurrent.TimeUnit.MINUTES
import java.time.Duration
import java.time.Instant
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -66,21 +67,13 @@ class RealSubscriptionsChecker @Inject constructor(
}

override suspend fun runChecker() {
if (subscriptionsManager.subscriptionStatus() != UNKNOWN) {
PeriodicWorkRequestBuilder<SubscriptionsCheckWorker>(1, HOURS)
.addTag(TAG_WORKER_SUBSCRIPTION_CHECK)
.setConstraints(
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build(),
)
.setBackoffCriteria(BackoffPolicy.LINEAR, 10, MINUTES)
.build().run {
workManager.enqueueUniquePeriodicWork(
TAG_WORKER_SUBSCRIPTION_CHECK,
ExistingPeriodicWorkPolicy.REPLACE,
this,
)
}
}
if (!subscriptionsManager.isSignedIn()) return

workManager.enqueueUniquePeriodicWork(
TAG_WORKER_SUBSCRIPTION_CHECK,
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
buildSubscriptionCheckPeriodicWorkRequest(),
)
}

companion object {
Expand All @@ -101,18 +94,48 @@ class SubscriptionsCheckWorker(

override suspend fun doWork(): Result {
return try {
if (subscriptionsManager.subscriptionStatus() != UNKNOWN) {
subscriptionsManager.fetchAndStoreAllData()
val subscription = subscriptionsManager.getSubscription()
if (subscription?.status == null || subscription.status == UNKNOWN) {
workManager.cancelAllWorkByTag(TAG_WORKER_SUBSCRIPTION_CHECK)
if (subscriptionsManager.isSignedIn()) {
if (subscriptionsManager.isSignedInV2()) {
subscriptionsManager.refreshSubscriptionData()
val subscription = subscriptionsManager.getSubscription()
if (subscription?.isActive() == true) {
// No need to refresh active subscription in the background. Delay next refresh to the expiry/renewal time.
// It will still get refreshed when the app goes to the foreground.
val expiresOrRenewsAt = Instant.ofEpochMilli(subscription.expiresOrRenewsAt)
if (expiresOrRenewsAt > Instant.now()) {
workManager.enqueueUniquePeriodicWork(
TAG_WORKER_SUBSCRIPTION_CHECK,
ExistingPeriodicWorkPolicy.UPDATE,
buildSubscriptionCheckPeriodicWorkRequest(nextScheduleTimeOverride = expiresOrRenewsAt),
)
}
}
} else {
subscriptionsManager.fetchAndStoreAllData()
val subscription = subscriptionsManager.getSubscription()
if (subscription?.status == null || subscription.status == UNKNOWN) {
workManager.cancelUniqueWork(TAG_WORKER_SUBSCRIPTION_CHECK)
}
}
} else {
workManager.cancelAllWorkByTag(TAG_WORKER_SUBSCRIPTION_CHECK)
workManager.cancelUniqueWork(TAG_WORKER_SUBSCRIPTION_CHECK)
}
Result.success()
} catch (e: Exception) {
Result.failure()
}
}
}

private fun buildSubscriptionCheckPeriodicWorkRequest(nextScheduleTimeOverride: Instant? = null): PeriodicWorkRequest =
PeriodicWorkRequestBuilder<SubscriptionsCheckWorker>(Duration.ofHours(1))
.setConstraints(
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build(),
)
.setBackoffCriteria(BackoffPolicy.LINEAR, Duration.ofMinutes(10))
.apply {
if (nextScheduleTimeOverride != null) {
setNextScheduleTimeOverride(nextScheduleTimeOverride.toEpochMilli())
}
}
.build()
Loading

0 comments on commit dcebb5b

Please sign in to comment.