-
Notifications
You must be signed in to change notification settings - Fork 89
PM-11720 - TDE User Without MP Cannot Enable Autofill For Account #908
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
PM-11720 - TDE User Without MP Cannot Enable Autofill For Account #908
Conversation
…e showing the vault screen
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #908 +/- ##
==========================================
- Coverage 88.77% 88.77% -0.01%
==========================================
Files 617 617
Lines 30906 30905 -1
==========================================
- Hits 27438 27437 -1
Misses 3468 3468 ☔ View full report in Codecov by Sentry. |
|
No New Or Fixed Issues Found |
matt-livefront
left a comment
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.
These changes look good!
There may be one additional piece that we need though. After you use SSO to authenticate in the extension, if you open the extension again, I think we should prompt the user for Face ID at that point since they have authenticated and we could have saved the integrity state.
Here's where we set the integrity state if you unlock your vault with your MP:
ios/BitwardenShared/Core/Auth/Repositories/AuthRepository.swift
Lines 959 to 966 in c3f3a13
| // Re-enable biometrics, if required. | |
| let biometricUnlockStatus = try? await biometricsRepository.getBiometricUnlockStatus() | |
| switch biometricUnlockStatus { | |
| case .available(_, true, false): | |
| try await biometricsRepository.configureBiometricIntegrity() | |
| try await biometricsRepository.setBiometricUnlockKey( | |
| authKey: clientService.crypto().getUserEncryptionKey() | |
| ) |
I think we would want to do that if you use either a password, device key (TDE), or key connector in that method.
| if case let .available(_, enabled, validIntegrity) = biometricUnlockStatus, enabled, !validIntegrity { | ||
| return .enterpriseSingleSignOn(email: activeAccount.profile.email) |
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.
I think one other check we need to add here is to ensure the user doesn't have a master password, since otherwise they could use their MP to unlock the vault.
activeAccount.profile.userDecryptionOptions?.hasMasterPassword
… logic to save integrity state
| let biometricUnlockStatus = try await services.biometricsRepository.getBiometricUnlockStatus() | ||
| let hasMasterPassword = activeAccount.profile.userDecryptionOptions?.hasMasterPassword ?? false | ||
|
|
||
| if case .available(_, true, false) = biometricUnlockStatus, !hasMasterPassword { | ||
| return .enterpriseSingleSignOn(email: activeAccount.profile.email) | ||
| } else { | ||
| return .vaultUnlock( | ||
| activeAccount, | ||
| animated: animated, | ||
| attemptAutomaticBiometricUnlock: attemptAutomaticBiometricUnlock, | ||
| didSwitchAccountAutomatically: didSwitchAccountAutomatically | ||
| ) | ||
| } |
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.
🎨 A small improvement I'd add is that we don't need to check for biometric status if hasMasterPassword is true so I'd rewrite this as:
| let biometricUnlockStatus = try await services.biometricsRepository.getBiometricUnlockStatus() | |
| let hasMasterPassword = activeAccount.profile.userDecryptionOptions?.hasMasterPassword ?? false | |
| if case .available(_, true, false) = biometricUnlockStatus, !hasMasterPassword { | |
| return .enterpriseSingleSignOn(email: activeAccount.profile.email) | |
| } else { | |
| return .vaultUnlock( | |
| activeAccount, | |
| animated: animated, | |
| attemptAutomaticBiometricUnlock: attemptAutomaticBiometricUnlock, | |
| didSwitchAccountAutomatically: didSwitchAccountAutomatically | |
| ) | |
| } | |
| let hasMasterPassword = activeAccount.profile.userDecryptionOptions?.hasMasterPassword == true | |
| if !hasMasterPassword { | |
| let biometricUnlockStatus = try await services.biometricsRepository.getBiometricUnlockStatus() | |
| if case .available(_, true, false) = biometricUnlockStatus { | |
| return .enterpriseSingleSignOn(email: activeAccount.profile.email) | |
| } | |
| } | |
| return .vaultUnlock( | |
| activeAccount, | |
| animated: animated, | |
| attemptAutomaticBiometricUnlock: attemptAutomaticBiometricUnlock, | |
| didSwitchAccountAutomatically: didSwitchAccountAutomatically | |
| ) |
|
|
||
| private func configureBiometricUnlockIfRequired() async throws { | ||
| if case .available(_, true, false) = try? await biometricsRepository.getBiometricUnlockStatus() { | ||
| try await biometricsRepository.configureBiometricIntegrity() | ||
| try await biometricsRepository.setBiometricUnlockKey( | ||
| authKey: clientService.crypto().getUserEncryptionKey() | ||
| ) | ||
| } | ||
| } |
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.
⛏️ Add docs.
❓ Would it be ok the unlock flows affected by this break if this throws? I'd guess it's fine but checking just in case.
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.
yeah I was thinking that if this fails for some reason then the calls wouldn't be executed and the user would have to provide another form of auth. Instead of being given the optional to provide biometrics. Does that make sense?
matt-livefront
left a comment
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.
Looks good to me!
🎟️ Tracking
PM-11720
📔 Objective
⏰ Reminders before review
🦮 Reviewer guidelines
:+1:) or similar for great changes:memo:) or ℹ️ (:information_source:) for notes or general info:question:) for questions:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion:art:) for suggestions / improvements:x:) or:warning:) for more significant problems or concerns needing attention:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt:pick:) for minor or nitpick changes