Skip to content
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

Biometrics lock (Lock app with FaceID/TouchID/iOS Password) #2398

Closed
wants to merge 30 commits into from

Conversation

bgoncal
Copy link
Member

@bgoncal bgoncal commented Aug 17, 2023

Summary

Concept for locking the HA app using iOS biometrics. (FaceID wasn't working on my simulator, thats why the video shows password instead).

Pending:

  • Localised copy
  • Better error logging
  • Remove print statements

Screenshots

@codecov
Copy link

codecov bot commented Aug 20, 2023

Codecov Report

Attention: 474 lines in your changes are missing coverage. Please review.

Comparison is base (8f7f0ec) 28.37% compared to head (eec44b0) 28.16%.
Report is 3 commits behind head on master.

❗ Current head eec44b0 differs from pull request most recent head 5dbb72e. Consider uploading reports for the commit 5dbb72e to get more accurate results

Files Patch % Lines
...dentialsSharing/ThreadCredentialsSharingView.swift 0.00% 117 Missing ⚠️
Sources/App/WebView/WebViewController.swift 0.00% 85 Missing ⚠️
...thentication/BiometricsAuthenticationService.swift 0.00% 82 Missing ⚠️
...alsSharing/ThreadCredentialsSharingViewModel.swift 38.46% 24 Missing ⚠️
...ces/App/Settings/DebugSettingsViewController.swift 0.00% 21 Missing ⚠️
...rces/Shared/DesignSystem/Components/CardView.swift 0.00% 21 Missing ⚠️
...App/Settings/Security/SecurityViewController.swift 0.00% 18 Missing ⚠️
...rces/Shared/DesignSystem/Components/HAButton.swift 0.00% 14 Missing ⚠️
...es/Shared/LocalAuthentication/BiometricsView.swift 0.00% 14 Missing ⚠️
Sources/Shared/Environment/MatterWrapper.swift 0.00% 12 Missing ⚠️
... and 14 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2398      +/-   ##
==========================================
- Coverage   28.37%   28.16%   -0.21%     
==========================================
  Files         273      290      +17     
  Lines       30284    30834     +550     
==========================================
+ Hits         8593     8685      +92     
- Misses      21691    22149     +458     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

}

private func authenticate(policy: LAPolicy) {
context.evaluatePolicy(policy, localizedReason: "Authentication required") { approved, error in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the hard part here is also blocking the ui while this should be happening, and e.g. in the app switcher. how would you imagine this to be implemented?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually most apps blur the UI using and overlay UIView, what do you think? I'd go for that, although at least in the simulator I wasn't able to dismiss iOS biometric/password screen (which is visible in the video), so maybe it is already doing that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like this, I just added to the PR, but Im not 100% sure the App Switcher will show this overlay if the user has already authenticated.
Simulator Screenshot - iPhone SE (3rd generation) - 2023-08-21 at 22 44 06

Sources/App/WebView/WebViewController.swift Outdated Show resolved Hide resolved
Sources/App/Settings/SettingsRootDataSource.swift Outdated Show resolved Hide resolved
@home-assistant
Copy link

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

@home-assistant home-assistant bot marked this pull request as draft August 20, 2023 22:19
@bgoncal bgoncal marked this pull request as ready for review August 21, 2023 20:51
@home-assistant home-assistant bot requested a review from zacwest August 21, 2023 20:51
@bgoncal bgoncal force-pushed the Biometric-lock-concept branch 2 times, most recently from cf3a0d3 to e300ba5 Compare November 7, 2023 13:18
@@ -410,6 +410,9 @@ Home Assistant is free and open source home automation software with a focus on
"settings_details.general.visibility.options.dock_and_menu_bar" = "Dock and Menu Bar";
"settings_details.general.visibility.options.menu_bar" = "Menu Bar";
"settings_details.general.visibility.title" = "Show App In…";
"settings_details.general.security.title" = "Security";
"settings_details.general.security.action" = "Enable biometric lock";
"settings_details.general.security.footer" = "You will be required to authenticate with biometrics everytime you open the app.";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

every time

Sources/App/WebView/WebViewController.swift Outdated Show resolved Hide resolved
Sources/App/WebView/WebViewController.swift Outdated Show resolved Hide resolved
Comment on lines 27 to 32
Current.Log
.error(
[
"Failed to authenticate with biometrics": "User context can't evaluate policy for device ownership",
]
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what should we tell the user if they fail to do this? should we have on-screen ui that says an error?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user can't authenticate neither with biometrics or password then the user is locked out, I would say this is very edge case since it's credentials are the same as the iOS/macOS device. Any suggestion?

@home-assistant home-assistant bot marked this pull request as draft November 16, 2023 04:02
@@ -95,6 +97,16 @@ enum SettingsRootDataSource {
}
}

private static func security() -> SettingsButtonRow {
SettingsButtonRow {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does this work on catalyst? should we hide it or make it available -- if the latter, how do we deal with e.g. the settings scene?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In catalyst it was a bit trickier, because of the "enter background/foreground" thats happens all the time even with the touchID dialog, I treated it with an extra logic to only reauthenticate when the user has reply enter background.

When the user open settings scene, the main web view scene locks again until the user unlocks it.

Screen.Recording.2023-11-16.at.16.33.08.mov
RPReplay_Final1700149090.MP4

@bgoncal bgoncal marked this pull request as ready for review November 16, 2023 15:47
@bgoncal bgoncal changed the title Biometrics lock concept (Lock app with FaceID/TouchID/iOS Password) Biometrics lock (Lock app with FaceID/TouchID/iOS Password) Nov 16, 2023
// MARK: - Biometrics lock

extension WebViewWindowController {
private func listenForBiometricsLockRelatedEvents() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if the user gets signed out (e.g. remotely, due to token) while this is happening?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can I easily reproduce that? I think the overlay will stay there, but it's nice to verify

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go into your user profile & delete the token for your device in your profile. you can do it from the same machine or other.

if the overlay stays, it may be worth killing it off since there's nothing it's protecting (if it's the last account) and may block signing into something new. there's no way to get to settings during onboarding.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested. Indeed the "lock screen" was still being shown even with no servers. So I updated it in a way that the user needs to authenticate one last time after the token expires, and then the biometric lock will be disabled and only reenabled if the user sets up a new server and manually enables the toggle.

@home-assistant home-assistant bot marked this pull request as draft November 16, 2023 17:46
@bgoncal bgoncal force-pushed the Biometric-lock-concept branch 2 times, most recently from b1b369b to 8c656d3 Compare December 5, 2023 01:42
# Conflicts:
#	Sources/App/Resources/Assets.xcassets/Logo.imageset/Contents.json
#	Sources/WatchApp/Assets.xcassets/WatchIcon.appiconset/Contents.json
#	Sources/WatchApp/Assets.xcassets/WatchIcon.beta.appiconset/Contents.json
#	Sources/WatchApp/Assets.xcassets/WatchIcon.dev.appiconset/Contents.json
@bgoncal bgoncal marked this pull request as ready for review December 5, 2023 13:20
@home-assistant home-assistant bot requested a review from zacwest December 5, 2023 13:20
@bgoncal bgoncal self-assigned this Dec 5, 2023
Sources/App/Settings/SettingsViewController.swift Outdated Show resolved Hide resolved
// MARK: - Biometrics lock

extension WebViewWindowController {
private func listenForBiometricsLockRelatedEvents() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go into your user profile & delete the token for your device in your profile. you can do it from the same machine or other.

if the overlay stays, it may be worth killing it off since there's nothing it's protecting (if it's the last account) and may block signing into something new. there's no way to get to settings during onboarding.

Sources/Shared/DesignSystem/Constants/HASpacing.swift Outdated Show resolved Hide resolved
HomeAssistant.xcodeproj/project.pbxproj Outdated Show resolved Hide resolved
HomeAssistant.xcodeproj/project.pbxproj Show resolved Hide resolved
Sources/App/Resources/Info.plist Outdated Show resolved Hide resolved
@home-assistant home-assistant bot marked this pull request as draft December 6, 2023 04:18
@bgoncal bgoncal marked this pull request as ready for review December 6, 2023 13:45
@home-assistant home-assistant bot requested a review from zacwest December 6, 2023 13:45
Copy link
Member

@zacwest zacwest left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think things seem good, but i am a little worried about the 'protect' part and how it works with multiple windows happening

Comment on lines +778 to +782
"thread.credentials.network_name_title" = "Network Name";
"thread.credentials.network_key_title" = "Network Key";
"thread.credentials.border_agent_id_title" = "Border Agent ID";
"thread.credentials.share_credentials_button_title" = "Share credential with Home Assistant";
"thread.credentials.screen_title" = "Thread Credentials";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad merge?

guard let window = controller.view.window,
previousRootViewController == nil else { return }

self.window = window
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if there are multiple windows open? e.g. multi-scene support on iPad.

i think you probably want to either collate all the windows during the lock phase, or make this chain off the WebViewWindowController itself, but synchronize the unlock status

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I will start over with this implementation, I liked your idea of sync status. Another question... should we allow shortcut actions if the app is locked?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it becomes really hard to do locking if we disallow extensions to do work. Most of them do not support being able to prompt the user for permission.

We could either:

  • tell the user it won't lock extensions
  • disallow extensions entirely if lock is enabled (where we cannot prompt)
  • allow the user to choose which extensions should be allowed

Maybe we could add more control in app but I think the first one sounds easiest for now.

@home-assistant home-assistant bot marked this pull request as draft December 7, 2023 05:02
@bgoncal
Copy link
Member Author

bgoncal commented Jan 5, 2024

Closing PR, I will start over with a better foundation for locking the app

@bgoncal bgoncal closed this Jan 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants