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

TouchID support (FREEBIE) #1606

Closed
wants to merge 1 commit into from
Closed

Conversation

noahemmet
Copy link

@noahemmet noahemmet commented Jan 17, 2017

First time contributor checklist

Contributor checklist

  • I'm following the code, UI and style conventions
  • My commits are rebased on the latest master branch
  • My commits are in nice logical chunks
  • My contribution is fully baked and is ready to be merged as is
  • I have tested my contribution on these devices:
  • iPhone SE, iOS 10.2.0 (sorry, this is the only device I have handy! It'd be nice to test it on an iOS 8 device, and a device without TouchID support.)
  • I have made the choice whether I want the BitHub reward or not by omitting or adding the word FREEBIE in my commit message

Description

This PR adds Touch ID support to the app. It builds off @fbartho's work from #663, with updated style conventions and rebased off master. Here's a video of it in action.

Summary:

  • Adds a TouchID security toggle to the Privacy settings (off by default).
  • Enabling it will require a TouchID authentication on first launch, and after 60 seconds in the background. (Note that there isn't UI informing the user of the 60 second cut-off; we may wish to add a label somewhere, or change the timeout to something shorter, like 1 second.)
  • Requires TouchID authentication when enabling/disabling the feature.
  • Enabling TouchID will automatically enable Screen Security.
  • Disables the TouchID switch if there is no hardware availability (untested).
  • Adds a setter and getter in PropertyListPreferences (I'm assuming this class is appropriately secure for this setting, as it's also responsible for the Screen Security feature, but if it's not, we'll want to use the keychain for storage).
  • Adds two localized strings (English only) for the prompt and the settings toggle.
  • Canceling TouchID will immediately re-present the prompt, as we don't currently have a password option to fallback on.

Tested:

  • User launches app for first time; is not prompted for TouchID.
  • User enables/disables TouchID in settings; is prompted for TouchID both times.
  • User cancels TouchID after enabling/disabling; TouchID setting is unchanged.
  • User launches app with TouchID enabled; is prompted for TouchID.
  • User authenticates with TouchID, backgrounds app, then foregrounds app within 60 seconds of backgrounding; is not prompted for TouchID.
  • User authenticates with TouchID, backgrounds app, then foregrounds app after 60 seconds of backgrounding; is prompted for TouchID.

@charlesmchen
Copy link
Contributor

Thank you @noahemmet - this PR looks promising. The team is occupied with a forthcoming release. We'll circle back to this PR when that work is complete.

CC @michaelkirk

Copy link
Contributor

@michaelkirk michaelkirk left a comment

Choose a reason for hiding this comment

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

Hey @noahemmet - thanks a lot for this well thought out PR.

I had some feedback, and unfortunately in the meanwhile we've made some conflicting changes - I think mostly in the PrivacySettingsTableViewController.m

If you're interested in getting this up to date, I'm interested in getting it merged =)


[self removeScreenProtection];
if (Environment.preferences.touchIDIsEnabled && !TouchIDManager.shared.isTouchIDUnlocked) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We intentionally don't access any storage synchronously from didLaunch / didBecomeActive methods. Reason being that a long running-migration could cause this call to block - hanging the UI. Hence the TSAccountManager runAsync machinery below.

Can you do something similar?

if (!TouchIDManager.shared.userDidCancel) {
[self presentTouchID];
} else {
[self protectScreen];
Copy link
Contributor

Choose a reason for hiding this comment

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

So the user would just see the signal logo on a blue screen and be unable to use the app here?

Based on your comment below...

// User canceled; we don't want to unlock the phone, but we want to avoid an endless cycle of 
// TouchID prompts, which hijacks the homebutton and prevents the user from switching apps,
// so just show the security screen until the user backgrounds and foregrounds the app.

...this limitation makes some sense, but expecting the user to figure out to relaunch the app seems a bit much.

Maybe tapping/swiping on the screen re-prompts? What do you think?

// Copyright (c) 2015 Open Whisper Systems. All rights reserved.
//

#import <Foundation/Foundation.h>
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add nullability annotations?

e.g. NS_ASSUME_NONNULL_BEGIN here and in your .m file?

completion(TouchIDAuthResultUnavailable);
} else {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:NSLocalizedString(@"TOUCHID_SECURITY_PROMPT",@"")
Copy link
Contributor

Choose a reason for hiding this comment

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

please add a useful comment on all localized strings for our translation team describing what this string is for.

- (BOOL)isTouchIDAvailable {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
return [myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError] && !authError;
Copy link
Contributor

Choose a reason for hiding this comment

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

please log any error


#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, TouchIDAuthResult) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason not to use the existing error codes? https://developer.apple.com/reference/localauthentication/laerror.code

dispatch_async(dispatch_get_main_queue(), ^{
if (error || !success){
DDLogError(@"Error Accessing TouchID: %@",error);
if (error.code == -2) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we compare to the constant rather than a magic number here?

https://developer.apple.com/reference/localauthentication/laerror.code

#import "TouchIDManager.h"

/// The number of seconds the app must be backgrounded before we lock the screen.
NSTimeInterval const TouchIDLockTimeoutDefault = 60;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: please prefix constants with their corresponding class name

e.g. TouchIDManagerLockTimeoutDefault

self.enableTouchIDSecuritySwitch.enabled = NO;
}

#if DEBUG
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd prefer not to - the more we diverge from RELEASE the more likely we are to break shit later and not notice =(

}

/// Ensures that security switches reflect the user's preferences.
- (void)validateSecuritySwitches
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see anything inherently wrong with this, but IMO it muddies the waters a bit about responsibilities.

Can you elaborate on why this method exists?

@hodgesmr
Copy link

hodgesmr commented Apr 3, 2017

I came across this issue while Googling for PIN functionality. According to the feedback in #738, it seems that locking the app from an unlocked iPhone is undesirable. If that has changed, would it make sense to have PINs and TouchID, not just the latter?

@sigenc sigenc mentioned this pull request May 8, 2017
@bvadnai
Copy link

bvadnai commented Nov 26, 2017

Please make this happen.

@philipcv
Copy link

I've been waiting for this for a long time.
Guys, please implement this as soon as possible.

@michaelkirk
Copy link
Contributor

Please do not bump issues or pull requests.

This has been sitting stagnant for a long time, so I'm closing it.

@signalapp signalapp locked and limited conversation to collaborators Nov 27, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants