-
Notifications
You must be signed in to change notification settings - Fork 25
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-8352] Initial Fido2 User verification flow implementation #653
Conversation
Bitwarden code coverageTotal coverage:
|
File | Coverage |
---|---|
BitwardenShared/Core/Auth/Repositories/AuthRepository.swift | 97.19% |
BitwardenShared/Core/Auth/Services/LocalAuth/LocalAuthService.swift | 100.00% |
BitwardenShared/Core/Platform/Services/ServiceContainer.swift | 97.33% |
BitwardenShared/UI/Auth/Extensions/Alert+Auth.swift | 100.00% |
BitwardenShared/UI/Auth/Utilities/UserVerificationHelper.swift | 79.01% |
BitwardenShared/UI/Auth/Utilities/UserVerificationRunner.swift | 100.00% |
BitwardenShared/UI/Autofill/Utilities/Fido2UserVerificationMediator.swift | 83.56% |
BitwardenShared/UI/Platform/Application/Extensions/Alert+Extensions.swift | 92.31% |
BitwardenShared/UI/Platform/Settings/Extensions/Alert+Settings.swift | 100.00% |
BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityProcessor.swift | 98.71% |
Powered by Slather
Generated by 🚫 Danger
No New Or Fixed Issues Found |
/// Whether master password reprompt should be performed. | ||
/// | ||
/// - Parameter reprompt: Cipher reprompt type to check | ||
/// - Returns: `True` if master password reprompt should be performed, `False` otherwise. |
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.
⛏️ In general we don't capitalize true
and false
in doc comments
|
||
switch laError.code { | ||
case .userCancel: | ||
Logger.application.log("User cancel authentication") |
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 "User canceled authentication"?
func verifyPin() async throws -> UserVerificationResult | ||
} | ||
|
||
// MARK: DefaultUserVerificationHelper |
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.
⛏️ Usually our MARK
comments for different top-level options (classes, etc.) are MARK: -
to differentiate them from landmarks inside of a class.
/// | ||
protocol UserVerificationHelper { | ||
/// Performs OS local auth, e.g. biometrics or pin/pattern | ||
/// - Parameter because: The reason to be displayed to the user when evaluating the policy if needed |
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.
⛏️
/// - Parameter because: The reason to be displayed to the user when evaluating the policy if needed | |
/// - Parameter because: The reason to be displayed to the user when evaluating the policy if needed |
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 also kinda feel like this parameter would better be called reason
, to match what we call similar things elsewhere in the app
/// `verifyDeviceLocalAuth()` with device status not authorized. | ||
func test_verifyDeviceLocalAuth_cant_perform_when_not_authorized() async throws { |
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 feel like our usual pattern with tests is to make the test name somewhat more terse, generally of the test_function_condition
variety, with each unit camelcased—so test_verifyDeviceLocalAuth_notAuthorized
here—and to put the fuller explanation of the Given/When/Then in the comment, since that's easier to read.
func verifyWithAttempts( | ||
verifyFunction: () async throws -> UserVerificationResult | ||
) async throws -> UserVerificationResult { | ||
var attempts: Int8 = 0 |
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.
❓ Why Int8
instead of Int
for just counting? The Swift language guide indicates that we should always use Int
unless there's a good reason to do otherwise.
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 just thought that given it counts "attempts", one would never use hundreds or thousands of attempts so Int8 (maximum 127) made sense. Maybe I could even have used UInt8
to indicate that attempts shouldn't be negative. I can make it Int
if performance is better or something like that. IMO even though is negligible for performance I often try to use the necessary data type instead of the broader one.
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.
It's a good instinct, and one that I had coming from Objective-C, but Swift really pushes to use the base types (Int, Double, etc.) unless absolutely necessary. I assume there's some sort of compiler optimization that happens around those base types, and I've also occasionally run into issues doing math when I had competing types (though that was also a Very Long Time Ago so it might not be an issue now). It's relatively moot here, however.
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.
Given that in this case it's pretty much the same and the performance gain is negligible, I'll just change it to avoid confusions.
/// An enum with the possible results when verifying a user | ||
/// | ||
enum UserVerificationResult { | ||
case cantPerform |
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.
🎨 Using a contraction here feels weird to me. I think a more idiomatic way would be unableToPerform
BitwardenShared/UI/Autofill/Utilities/Fido2UserVerificationMediator.swift
Outdated
Show resolved
Hide resolved
BitwardenShared/UI/Autofill/Utilities/Fido2UserVerificationMediator.swift
Show resolved
Hide resolved
Co-authored-by: Katherine Bertelsen <[email protected]>
…iator.swift Co-authored-by: Katherine Bertelsen <[email protected]>
XCTAssertEqual(result, .passcodeNotSet) | ||
} | ||
|
||
/// `evaluateDeviceOwnerPolicy(suppliedContext:,deviceAuthStatus:,localizedReason:)` |
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.
⛏️ Generally when giving a Swift function that takes multiple parameters, just the colons are used: evaluateDeviceOwnerPolicy(suppliedContext:deviceAuthStatus:localizedReason:)
. It's a little weird, but it's a holdover from the Objective-C days (when there weren't commas between function arguments like that).
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.
BitwardenShared/UI/Platform/Application/Extensions/Alert+Extensions.swift
Outdated
Show resolved
Hide resolved
Co-authored-by: Matt Czech <[email protected]>
…g, updated tests symbol names
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!
…d logic for checking if can verify master password.
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.
👍
🎟️ Tracking
PM-8352
📔 Objective
Implement Fido2 User verification flow.
Note: This is an initial PR and the flow will be completed in subsequent PRs to ease
⏰ 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