-
Notifications
You must be signed in to change notification settings - Fork 429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Subscription oauth v2 #3480
base: main
Are you sure you want to change the base?
Subscription oauth v2 #3480
Conversation
# Conflicts: # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
# Conflicts: # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved # DuckDuckGo/AppDependencyProvider.swift # DuckDuckGo/NetworkProtectionRootView.swift # DuckDuckGo/NetworkProtectionTunnelController.swift # DuckDuckGo/Subscription/DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift # DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift # DuckDuckGo/Subscription/ViewModel/SubscriptionSettingsViewModel.swift # DuckDuckGo/Subscription/Views/SubscriptionContainerViewFactory.swift # PacketTunnelProvider/NetworkProtection/NetworkProtectionPacketTunnelProvider.swift
# Conflicts: # DuckDuckGo.xcodeproj/project.pbxproj # DuckDuckGo/AppDependencyProvider.swift
# Conflicts: # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
# Conflicts: # DuckDuckGo.xcodeproj/project.pbxproj # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved # DuckDuckGo/Feedback/VPNMetadataCollector.swift
# Conflicts: # DuckDuckGo.xcodeproj/project.pbxproj # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
…li/subscription_oauth_api_v2 # Conflicts: # DuckDuckGo.xcodeproj/project.pbxproj # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
This PR has been inactive for more than 7 days and will be automatically closed 7 days from now. |
This PR has been inactive for more than 7 days and will be automatically closed 7 days from now. |
# Conflicts: # DuckDuckGo.xcodeproj/project.pbxproj # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved # DuckDuckGo/AppDelegate.swift # DuckDuckGo/SettingsViewModel.swift # DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift
# Conflicts: # DuckDuckGo.xcodeproj/project.pbxproj # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved # DuckDuckGo/AppDependencyProvider.swift # DuckDuckGo/SettingsState.swift # DuckDuckGo/SettingsSubscriptionView.swift # DuckDuckGoTests/Subscription/SubscriptionPagesUseSubscriptionFeatureTests.swift
Note: I've edited the description to add links to the related PRs for easy of navigation. |
@diegoreymendez same issue than macOS, fixing now |
PixelParameters.source: "browser" | ||
] | ||
|
||
DailyPixel.fireDailyAndCount(pixel: .privacyProKeychainAccessError, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as for macOS, in new code we retained the 'privacyProKeychainAccessError' pixel but there are no places where it is fired. Additionally we lack feedback from v2 keychain store regarding access errors.
@@ -283,7 +283,7 @@ struct NetworkProtectionStatusView: View { | |||
|
|||
@ViewBuilder | |||
private func about() -> some View { | |||
let viewModel = UnifiedFeedbackFormViewModel(subscriptionManager: statusModel.subscriptionManager, | |||
let viewModel = UnifiedFeedbackFormViewModel(subscriptionManager: AppDependencyProvider.shared.subscriptionManager, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is wrongly resolved merge conflict, we can obtain the subsc. manager from the model. Left line seems to be correct.
guard case .success(false) = await accountManager.hasEntitlement(forProductName: .networkProtection) else { return } | ||
let subscriptionManager = AppDependencyProvider.shared.subscriptionManager | ||
|
||
guard let tokenContainer = try? await subscriptionManager.getTokenContainer(policy: .local), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should't we use 'guard !subscriptionManager.isFeatureActive(.networkProtection)' here?
private let settings: VPNSettings | ||
private let defaults: UserDefaults | ||
|
||
init(statusObserver: ConnectionStatusObserver, | ||
serverInfoObserver: ConnectionServerInfoObserver, | ||
accountManager: AccountManager = AppDependencyProvider.shared.subscriptionManager.accountManager, | ||
serverInfoObserver: ConnectionServerInfoObserver,// ConnectionServerInfoObserverThroughSession(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover?
|
||
struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { | ||
private let userDefaults: UserDefaults | ||
private let accountManager: AccountManager | ||
private let oAuthClient: any OAuthClient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we use 'any SubscriptionManager' here?
do { | ||
try await self.subscriptionManager.getTokenContainer(policy: .localForceRefresh) | ||
Logger.subscription.log("Token background refresh task completed successfully in \(Date().timeIntervalSince(refreshStartDate)) seconds") | ||
task.setTaskCompleted(success: true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we schedule another task after completing one?
Logger.networkProtection.log("Subscription Entitlements check...") | ||
let isNetworkProtectionEnabled = await subscriptionManager.isFeatureActive(.networkProtection) | ||
Logger.networkProtection.log("NetworkProtectionEnabled if: \( isNetworkProtectionEnabled ? "Enabled" : "Disabled", privacy: .public)") | ||
return .success(isNetworkProtectionEnabled) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if valid, but earlier the closure returned .failure
when fetching entitlement failed. Is this not possible for the new implementation of entitlements?
let purchaseTransactionJWS: String | ||
|
||
switch await appStorePurchaseFlow.purchaseSubscription(with: subscriptionSelection.id, | ||
emailAccessToken: emailAccessToken) { | ||
switch await appStorePurchaseFlow.purchaseSubscription(with: subscriptionSelection.id) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will look closer at it in BSK but I see you dropped the emailAccessToken: emailAccessToken)
param from the purchase call.
This was the access token from Email Protection feature. When we were creating a new account during the purchase and we passed this token as param the user account on BE was linked with user's Duck address from Email Protection. Not sure if this is still supported in v2.
_ = try await subscriptionManager.exchange(tokenV1: authToken) | ||
Logger.subscription.log("v1 token exchanged for v2") | ||
|
||
onSetSubscription?() | ||
|
||
} else { | ||
Logger.subscription.error("Failed to obtain subscription options") | ||
} catch { | ||
Logger.subscription.error("Failed to exchange v1 token for v2") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe worthy adding a pixel for (also on macOS)?
// guard let accessToken = accountManager.accessToken else { | ||
// Logger.subscription.error("Missing access token") | ||
// return nil | ||
// } | ||
// | ||
// switch await accountManager.fetchAccountDetails(with: accessToken) { | ||
// case .success(let accountDetails): | ||
// switch await subscriptionManager.subscriptionEndpointService.getSubscription(accessToken: accessToken) { | ||
// case .success: | ||
// accountManager.storeAccount(token: accessToken, | ||
// email: accountDetails.email, | ||
// externalID: accountDetails.externalID) | ||
// onBackToSettings?() | ||
// case .failure(let error): | ||
// Logger.subscription.error("Error retrieving subscription details: \(error.localizedDescription)") | ||
// } | ||
// case .failure(let error): | ||
// Logger.subscription.error("Could not get account Details: \(error.localizedDescription)") | ||
// setTransactionError(.generalError) | ||
// } | ||
// return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Probably commented out code can be removed.
- What about handling the error scenarios like in original code e.g. L:373?
# Conflicts: # DuckDuckGo.xcodeproj/project.pbxproj # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved # DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift
# Conflicts: # DuckDuckGo.xcodeproj/project.pbxproj # DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved # DuckDuckGo/AppLifecycle/AppStates/Inactive.swift # DuckDuckGo/OldAppDelegate.swift
# Conflicts: # DuckDuckGo/DuckPlayer/DuckPlayer.swift
Task/Issue URL: https://app.asana.com/0/1205842942115003/1207991044706235/f
CC: @miasma13
macOS PR: duckduckgo/macos-browser#3580
BSK PR: duckduckgo/BrowserServicesKit#1033
Description:
This PR introduces the use of OAuth V2 authentication in Privacy Pro Subscription.
The code changes are comprehensive due to the paradigm changes between the old access token lifecycle and the new JWT lifecycle.
The Subscription UI and UX should be unchanged.
Steps to test this PR:
Test all Privacy Pro Subscription features and UX, more details here
Internal references:
Software Engineering Expectations
Technical Design Template