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

Added iOS SF/ASWeb AuthenticationSession support #187

Merged
merged 6 commits into from
Jan 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 67 additions & 15 deletions ios/A0Auth0.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#import "A0Auth0.h"

#import <SafariServices/SafariServices.h>
#if __has_include("AuthenticationServices/AuthenticationServices.h")
#import <AuthenticationServices/AuthenticationServices.h>
#endif
#import <CommonCrypto/CommonCrypto.h>

#if __has_include("RCTUtils.h")
Expand All @@ -10,8 +13,12 @@
#import <React/RCTUtils.h>
#endif

#define ERROR_CANCELLED @{@"error": @"a0.session.user_cancelled",@"error_description": @"User cancelled the Auth"}
Copy link
Contributor

Choose a reason for hiding this comment

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

"authentication"

Copy link
Member Author

Choose a reason for hiding this comment

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

Same as before

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a message, though, so no reason not to correct it.

#define ERROR_FAILED_TO_LOAD @{@"error": @"a0.session.failed_load",@"error_description": @"Failed to load url"}
Copy link
Contributor

Choose a reason for hiding this comment

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

"URL"

Copy link
Member Author

Choose a reason for hiding this comment

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

These errors are from moving existing error responses to constants. So there is no actual change of code, only location of code.

Copy link
Contributor

Choose a reason for hiding this comment

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

☝️


@interface A0Auth0 () <SFSafariViewControllerDelegate>
@property (weak, nonatomic) SFSafariViewController *last;
@property (strong, nonatomic) NSObject *authenticationSession;
@property (copy, nonatomic) RCTResponseSenderBlock sessionCallback;
@property (assign, nonatomic) BOOL closeOnLoad;
@end
Expand All @@ -30,9 +37,15 @@ - (dispatch_queue_t)methodQueue
}

RCT_EXPORT_METHOD(showUrl:(NSString *)urlString closeOnLoad:(BOOL)closeOnLoad callback:(RCTResponseSenderBlock)callback) {
[self presentSafariWithURL:[NSURL URLWithString:urlString]];
self.closeOnLoad = closeOnLoad;
self.sessionCallback = callback;
if (@available(iOS 11.0, *)) {
self.sessionCallback = callback;
self.closeOnLoad = closeOnLoad;
[self presentAuthenticationSession:[NSURL URLWithString:urlString]];
} else {
[self presentSafariWithURL:[NSURL URLWithString:urlString]];
self.sessionCallback = callback;
self.closeOnLoad = closeOnLoad;
}
}

RCT_EXPORT_METHOD(oauthParameters:(RCTResponseSenderBlock)callback) {
Expand All @@ -58,17 +71,64 @@ - (void)presentSafariWithURL:(NSURL *)url {
self.last = controller;
}

- (void)presentAuthenticationSession:(NSURL *)url {

NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url
resolvingAgainstBaseURL:NO];
NSArray *queryItems = urlComponents.queryItems;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name=%@", @"redirect_uri"];
NSURLQueryItem *queryItem = [[queryItems
filteredArrayUsingPredicate:predicate]
firstObject];
NSString *callbackURLScheme = queryItem.value;
RCTResponseSenderBlock callback = self.sessionCallback ? self.sessionCallback : ^void(NSArray *_unused) {};

if (@available(iOS 12.0, *)) {
self.authenticationSession = [[ASWebAuthenticationSession alloc]
initWithURL:url callbackURLScheme:callbackURLScheme
completionHandler:^(NSURL * _Nullable callbackURL,
NSError * _Nullable error) {
if ([[error domain] isEqualToString:ASWebAuthenticationSessionErrorDomain] &&
[error code] == ASWebAuthenticationSessionErrorCodeCanceledLogin) {
callback(@[ERROR_CANCELLED, [NSNull null]]);
} else if(error) {
callback(@[error, [NSNull null]]);
} else if(callbackURL) {
callback(@[[NSNull null], callbackURL.absoluteString]);
}
self.authenticationSession = nil;
}];
[(ASWebAuthenticationSession*) self.authenticationSession start];
} else if (@available(iOS 11.0, *)) {
self.authenticationSession = [[SFAuthenticationSession alloc]
initWithURL:url callbackURLScheme:callbackURLScheme
completionHandler:^(NSURL * _Nullable callbackURL,
NSError * _Nullable error) {
if ([[error domain] isEqualToString:SFAuthenticationErrorDomain] &&
[error code] == SFAuthenticationErrorCanceledLogin) {
callback(@[ERROR_CANCELLED, [NSNull null]]);
} else if(error) {
callback(@[error, [NSNull null]]);
} else if(callbackURL) {
callback(@[[NSNull null], callbackURL.absoluteString]);
}
self.authenticationSession = nil;
}];
[(SFAuthenticationSession*) self.authenticationSession start];
}
}

- (void)terminateWithError:(id)error dismissing:(BOOL)dismissing animated:(BOOL)animated {
RCTResponseSenderBlock callback = self.sessionCallback ? self.sessionCallback : ^void(NSArray *_unused) {};
if (dismissing) {
[self.last.presentingViewController dismissViewControllerAnimated:animated
completion:^{
if (error) {
callback(@[error]);
callback(@[error, [NSNull null]]);
}
}];
} else if (error) {
callback(@[error]);
callback(@[error, [NSNull null]]);
}
self.sessionCallback = nil;
self.last = nil;
Expand Down Expand Up @@ -122,22 +182,14 @@ - (NSDictionary *)generateOAuthParameters {
#pragma mark - SFSafariViewControllerDelegate

- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller {
NSDictionary *error = @{
@"error": @"a0.session.user_cancelled",
@"error_description": @"User cancelled the Auth"
};
[self terminateWithError:error dismissing:NO animated:NO];
[self terminateWithError:ERROR_CANCELLED dismissing:NO animated:NO];
}

- (void)safariViewController:(SFSafariViewController *)controller didCompleteInitialLoad:(BOOL)didLoadSuccessfully {
if (self.closeOnLoad && didLoadSuccessfully) {
[self terminateWithError:[NSNull null] dismissing:YES animated:YES];
} else if (!didLoadSuccessfully) {
NSDictionary *error = @{
@"error": @"a0.session.failed_load",
@"error_description": @"Failed to load url"
};
[self terminateWithError:error dismissing:YES animated:YES];
[self terminateWithError:ERROR_FAILED_TO_LOAD dismissing:YES animated:YES];
}
}

Expand Down
10 changes: 6 additions & 4 deletions webauth/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ export default class Agent {
resolve(event.url);
};
Linking.addEventListener('url', urlHandler);
NativeModules.A0Auth0.showUrl(url, closeOnLoad, err => {
NativeModules.A0Auth0.showUrl(url, closeOnLoad, (error, redirectURL) => {
Linking.removeEventListener('url', urlHandler);
if (err) {
reject(err);
} else if (closeOnLoad) {
if (error) {
reject(error);
} else if(redirectURL) {
resolve(redirectURL);
} else if(closeOnLoad) {
resolve();
}
});
Expand Down