add udid auth via safari roundtrip

This commit is contained in:
Stephan Diederich 2013-09-07 17:27:10 +02:00
parent 41b1d72f83
commit 41d7a0da6a
4 changed files with 168 additions and 12 deletions

View File

@ -15,6 +15,15 @@
- (instancetype) initWithDelegate:(id<BITAuthenticationViewControllerDelegate>) delegate;
/**
* can be set to YES to show an additional button + description text
* and allowing to login via external website/UDID.
* if this is set to yes, no further email/password options are shown
*
* defaults to NO
*/
@property (nonatomic, assign) BOOL showsLoginViaWebButton;
/**
* can be set to YES to also require the users password
*
@ -41,6 +50,8 @@
*/
- (void) authenticationViewControllerDidCancel:(UIViewController*) viewController;
- (void) authenticationViewControllerDidTapWebButton:(UIViewController*) viewController;
/**
* called when the user wants to login
*

View File

@ -33,10 +33,14 @@
return self;
}
#pragma mark - view lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView setScrollEnabled:NO];
[self updateWebLoginButton];
}
- (void)viewWillAppear:(BOOL)animated {
@ -60,6 +64,7 @@
[[UIApplication sharedApplication] setStatusBarStyle:_statusBarStyle];
}
#pragma mark - Property overrides
- (void)setShowsCancelButton:(BOOL)showsCancelButton {
if(_showsCancelButton != showsCancelButton) {
_showsCancelButton = showsCancelButton;
@ -77,6 +82,44 @@
}
}
- (void)setShowsLoginViaWebButton:(BOOL)showsLoginViaWebButton {
if(_showsLoginViaWebButton != showsLoginViaWebButton) {
_showsLoginViaWebButton = showsLoginViaWebButton;
if(self.isViewLoaded) {
[self.tableView reloadData];
[self updateWebLoginButton];
}
}
}
- (void) updateWebLoginButton {
if(self.showsLoginViaWebButton) {
static const CGFloat kFooterHeight = 60.f;
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,
CGRectGetWidth(self.tableView.bounds),
kFooterHeight)];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:BITHockeyLocalizedString(@"Show login page") forState:UIControlStateNormal];
CGSize buttonSize = [button sizeThatFits:CGSizeMake(CGRectGetWidth(self.tableView.bounds),
kFooterHeight)];
button.frame = CGRectMake(floorf((CGRectGetWidth(containerView.bounds) - buttonSize.width) / 2.f),
floorf((kFooterHeight - buttonSize.height) / 2.f),
buttonSize.width,
buttonSize.height);
button.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[containerView addSubview:button];
[button addTarget:self
action:@selector(handleWebLoginButton:)
forControlEvents:UIControlEventTouchUpInside];
self.tableView.tableFooterView = containerView;
} else {
self.tableView.tableFooterView = nil;
}
}
- (IBAction) handleWebLoginButton:(id)sender {
[self.delegate authenticationViewControllerDidTapWebButton:self];
}
#pragma mark - UIViewController Rotation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
@ -101,16 +144,24 @@
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger rows = 1;
if ([self requirePassword]) rows ++;
return rows;
if(self.showsLoginViaWebButton) {
return 0;
} else {
NSInteger rows = 1;
if ([self requirePassword]) rows ++;
return rows;
}
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
if (section == 0) {
return BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerDataDescription");
if(self.showsLoginViaWebButton) {
return BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerWebLoginDescription");
} else {
return BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerDataDescription");
}
}
return nil;

View File

@ -13,6 +13,7 @@
typedef NS_ENUM(NSUInteger, BITAuthenticatorAuthType) {
BITAuthenticatorAuthTypeEmail,
BITAuthenticatorAuthTypeEmailAndPassword,
BITAuthenticatorAuthTypeWebbased,
//TODO: add Facebook?
};
@ -87,6 +88,35 @@ typedef void(^tValidationCompletion)(BOOL validated, NSError *error);
*/
@property (nonatomic, readonly) NSString *installationIdentification;
#pragma mark - HandleURL Helper
/**
* should be used by the app-delegate to forward handle application:openURL:sourceApplication:annotation calls
*
* @param url URL that was passed to the app
* @param sourceApplication sourceApplication that was passed to the app
* @param annotation annotation that was passed to the app
*
* @return YES if the URL request was handled, NO if the URL could not be handled/identified
*
* Sample usage (in AppDelegate)
* - (BOOL)application:(UIApplication *)application
* openURL:(NSURL *)url
* sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
* if ([[BITHockeyManager sharedHockeyManager].authenticator handleOpenURL:url
* sourceApplication:sourceApplication
* annotation:annotation]) {
* return YES;
* } else {
* //do your own URL handling, return appropriate valu
* }
* return NO;
}
*/
- (BOOL) handleOpenURL:(NSURL *) url
sourceApplication:(NSString *) sourceApplication
annotation:(id) annotation;
@end
@protocol BITAuthenticatorDelegate <NSObject>

View File

@ -135,6 +135,9 @@ static NSString* const kBITAuthenticatorLastAuthenticatedVersionKey = @"BITAuthe
case BITAuthenticatorAuthTypeEmailAndPassword:
params = @{@"auid" : self.authenticationToken};
break;
case BITAuthenticatorAuthTypeWebbased:
params = @{@"udid" : self.authenticationToken};
break;
}
return params;
}
@ -197,19 +200,21 @@ static NSString* const kBITAuthenticatorLastAuthenticatedVersionKey = @"BITAuthe
BITHockeyLog(@"Already authenticating. Ignoring request");
return;
}
BOOL requiresPassword;
BITAuthenticationViewController *viewController = [[BITAuthenticationViewController alloc] initWithDelegate:self];
switch (self.authenticationType) {
case BITAuthenticatorAuthTypeEmailAndPassword:
requiresPassword = YES;
viewController.requirePassword = YES;
break;
case BITAuthenticatorAuthTypeEmail:
requiresPassword = NO;
viewController.requirePassword = NO;
break;
case BITAuthenticatorAuthTypeWebbased:
viewController.requirePassword = NO;
viewController.showsLoginViaWebButton = YES;
break;
}
BITAuthenticationViewController *viewController = [[BITAuthenticationViewController alloc] initWithDelegate:self];
viewController.requirePassword = requiresPassword;
switch (self.validationType) {
case BITAuthenticatorValidationTypeNever:
case BITAuthenticatorValidationTypeOptional:
@ -375,6 +380,65 @@ static NSString* const kBITAuthenticatorLastAuthenticatedVersionKey = @"BITAuthe
}
}
- (void)authenticationViewControllerDidTapWebButton:(UIViewController *)viewController {
NSURL *hockeyWebbasedLoginURL = [self.hockeyAppClient.baseURL URLByAppendingPathComponent:[NSString stringWithFormat:@"apps/%@/authorize", self.encodedAppIdentifier]];
[[UIApplication sharedApplication] openURL:hockeyWebbasedLoginURL];
}
- (BOOL) handleOpenURL:(NSURL *) url
sourceApplication:(NSString *) sourceApplication
annotation:(id) annotation {
BOOL isValidURL = NO;
NSString *udid = [self UDIDFromOpenURL:url annotation:annotation isValidURL:&isValidURL];
if(NO == isValidURL) {
//do nothing, was not for us
return NO;
}
if(udid){
[self didAuthenticateWithToken:udid];
} else {
//reset auth-token
self.authenticationToken = nil;
if(self.validationType == BITAuthenticatorValidationTypeOptional) {
//dismiss view-controller if login was optional
[_authenticationController dismissModalViewControllerAnimated:YES];
_authenticationController = nil;
} else {
//keep the viewcontroller and thus block the app
}
}
return YES;
}
- (NSString *) UDIDFromOpenURL:(NSURL *) url annotation:(id) annotation isValidURL:(BOOL*) isValid{
NSString *urlScheme = [NSString stringWithFormat:@"ha%@", self.appIdentifier];
if([[url scheme] isEqualToString:urlScheme]) {
if(isValid) {
*isValid = YES;
}
NSString *query = [url query];
NSString *udid = nil;
//there should actually only one
static NSString * const UDIDQuerySpecifier = @"udid";
for(NSString *queryComponents in [query componentsSeparatedByString:@"&"]) {
NSArray *parameterComponents = [queryComponents componentsSeparatedByString:@"="];
if(2 == parameterComponents.count && [parameterComponents[0] isEqualToString:UDIDQuerySpecifier]) {
udid = parameterComponents[1];
break;
}
}
return udid;
} else {
if(isValid) {
*isValid = NO;
}
return nil;
}
}
#pragma mark - Validation Pseudo-Delegate
- (void)validationFailedWithError:(NSError *)validationError completion:(tValidationCompletion) completion{
if(completion) {