diff --git a/Classes/BITAuthenticator.h b/Classes/BITAuthenticator.h index 9c677f6378..0d0f7f0d39 100644 --- a/Classes/BITAuthenticator.h +++ b/Classes/BITAuthenticator.h @@ -111,6 +111,13 @@ typedef NS_ENUM(NSUInteger, BITAuthenticatorAppRestrictionEnforcementFrequency) * sure only users who are testers of your app are allowed to run it. * * This module automatically disables itself when running in an App Store build by default! + * + * @warning It is mandatory to call `authenticateInstallation` somewhen after calling + * `[[BITHockeyManager sharedHockeyManager] startManager]` or disable `automaticMode` + * and fully customize the identification and validation workflow yourself. + * If your app shows a modal view on startup, make sure to call `authenticateInstallation` + * either once your modal view is fully presented (e.g. its `viewDidLoad:` method is processed) + * or once your modal view is dismissed. */ @interface BITAuthenticator : BITHockeyBaseManager @@ -285,6 +292,27 @@ typedef NS_ENUM(NSUInteger, BITAuthenticatorAppRestrictionEnforcementFrequency) /// @name Authentication ///----------------------------------------------------------------------------- +/** + * Invoked automatic identification and validation + * + * If the `BITAuthenticator` is in automatic mode this will initiate identifying + * the current user according to the type specified in `identificationType` and + * validate if the identified user is allowed to run this application. + * + * If the user is not yet identified it will present a modal view asking the user to + * provide the required information. + * + * If your app provides it's own startup modal screen, e.g. a guide or a login, then + * you might either call this method once that UI is fully presented or once + * the user e.g. did actually login already. + * + * @warning You need to call this method in your code even if automatic mode is enabled! + * + * @see identificationType + * @see automaticMode + */ +- (void) authenticateInstallation; + /** * Identifies the user according to the type specified in `identificationType`. * diff --git a/Classes/BITAuthenticator.m b/Classes/BITAuthenticator.m index fffebf9eda..c1ce305da5 100644 --- a/Classes/BITAuthenticator.m +++ b/Classes/BITAuthenticator.m @@ -50,6 +50,8 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut id _appDidBecomeActiveObserver; id _appWillResignActiveObserver; UIViewController *_authenticationController; + + BOOL _isSetup; } - (void)dealloc { @@ -63,6 +65,7 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut _identificationType = BITAuthenticatorIdentificationTypeAnonymous; _automaticMode = YES; + _isSetup = NO; _restrictApplicationUsage = NO; _restrictionEnforcementFrequency = BITAuthenticatorAppRestrictionEnforcementOnFirstLaunch; } @@ -74,20 +77,36 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut //disabled in the appStore if([self isAppStoreEnvironment]) return; - switch ([[UIApplication sharedApplication] applicationState]) { - case UIApplicationStateActive: - [self authenticate]; - break; - case UIApplicationStateBackground: - case UIApplicationStateInactive: - // do nothing, wait for active state - break; - } - - [self registerObservers]; + _isSetup = YES; } #pragma mark - +- (void)authenticateInstallation { + //disabled in the appStore + if([self isAppStoreEnvironment]) return; + + // make sure this is called after startManager so all modules are fully setup + if (!_isSetup) { + [self performSelector:@selector(authenticateInstallation) withObject:nil afterDelay:0.1]; + } + + static dispatch_once_t authenticatePredicate; + dispatch_once(&authenticatePredicate, ^{ + + switch ([[UIApplication sharedApplication] applicationState]) { + case UIApplicationStateActive: + [self authenticate]; + break; + case UIApplicationStateBackground: + case UIApplicationStateInactive: + // do nothing, wait for active state + break; + } + + [self registerObservers]; + }); +} + - (void) authenticate { //when running in manual mode, we don't actually do anything ourselves if(!self.automaticMode) return; diff --git a/docs/HowTo-Authenticating-Users-on-iOS-template.md b/docs/HowTo-Authenticating-Users-on-iOS-template.md index 5dad53f08b..94d3117932 100644 --- a/docs/HowTo-Authenticating-Users-on-iOS-template.md +++ b/docs/HowTo-Authenticating-Users-on-iOS-template.md @@ -26,6 +26,22 @@ Previous versions of HockeySDK for iOS used the response of the method `UIDevice The user needs to enter the email address and password of his HockeyApp account. +The `BITAuthenticator` class doesn't do anything on its own. In addition to setting up the behavior, you also need to trigger the process yourself. + +If `automaticMode` is enabled (default), you simply need to place a call to `[[BITHockeyManager sharedHockeyManager] authenticateInstallation]` in your code. This will show a UI asking for identification details according to the chosen strategy. + +**IMPORTANT**: If your app shows a modal view on startup, make sure to call `authenticateInstallation` either once your modal view is fully presented (e.g. its `viewDidLoad:` method is processed) or once your modal view is dismissed. + +If `automaticMode` is disabled, you need to implement your own workflow by using + + - (void) identifyWithCompletion:(void(^)(BOOL identified, NSError *error)) completion; + +to identify the current user depending on your strategy and + + - (void) validateWithCompletion:(void(^)(BOOL validated, NSError *error)) completion; + +to validate the user may still use the app if required. + The following sections explain the different strategies and their advantages / disadvantages. @@ -35,6 +51,7 @@ Initialize HockeySDK with the following code: [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"<#APP_ID#>" delegate:self]; [[BITHockeyManager sharedHockeyManager] startManager]; + [[BITHockeyManager sharedHockeyManager] authenticateInstallation]; Replace APP_ID with the your App ID (can be found on the app page). @@ -57,6 +74,7 @@ Initialize HockeySDK with the following code: [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"<#APP_ID#>" delegate:self]; [[BITHockeyManager sharedHockeyManager].authenticator setIdentificationType:BITAuthenticatorIdentificationTypeDevice]; [[BITHockeyManager sharedHockeyManager] startManager]; + [[BITHockeyManager sharedHockeyManager] authenticateInstallation]; Replace APP_ID with the your App ID (can be found on the app page). @@ -104,6 +122,7 @@ Initialize HockeySDK with the following code: [[BITHockeyManager sharedHockeyManager].authenticator setAuthenticationSecret:@"<#SECRET#>"]; [[BITHockeyManager sharedHockeyManager].authenticator setIdentificationType:BITAuthenticatorIdentificationTypeHockeyAppEmail]; [[BITHockeyManager sharedHockeyManager] startManager]; + [[BITHockeyManager sharedHockeyManager] authenticateInstallation]; Replace APP_ID with the your App ID and SECRET with the Secret (both values can be found on the app page). @@ -127,6 +146,7 @@ Initialize HockeySDK with the following code: [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_ID" delegate:self]; [[BITHockeyManager sharedHockeyManager].authenticator setIdentificationType:BITAuthenticatorIdentificationTypeHockeyAppUser]; [[BITHockeyManager sharedHockeyManager] startManager]; + [[BITHockeyManager sharedHockeyManager] authenticateInstallation]; Replace APP_ID with the your App ID (can be found on the app page).