From 3a9afea39b32b8940edaea14882c5a2604f9f120 Mon Sep 17 00:00:00 2001 From: MikhailKupriyanov Date: Mon, 6 Jul 2015 23:37:38 +0300 Subject: [PATCH 01/10] add vkontakte --- .../SimpleAuthFaceBookWebProvider.h | 12 ++ .../SimpleAuthFaceBookWebProvider.m | 192 ++++++++++++++++++ ...impleAuthVKontakteWebLoginViewController.h | 12 ++ ...impleAuthVKontakteWebLoginViewController.m | 40 ++++ 4 files changed, 256 insertions(+) create mode 100644 Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.h create mode 100644 Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.m create mode 100644 Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.h create mode 100644 Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.m diff --git a/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.h b/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.h new file mode 100644 index 0000000..d47d055 --- /dev/null +++ b/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.h @@ -0,0 +1,12 @@ +// +// SimpleAuthVKontakteWebProvider.h +// SimpleAuth +// +// Created by Caleb Davenport on 7/6/15. +// + +#import "SimpleAuthProvider.h" + +@interface SimpleAuthVKontakteWebProvider : SimpleAuthProvider + +@end diff --git a/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.m b/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.m new file mode 100644 index 0000000..4d77749 --- /dev/null +++ b/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.m @@ -0,0 +1,192 @@ +// +// SimpleAuthVKontakteWebProvider.m +// SimpleAuth +// +// Created by Caleb Davenport on 7/6/15. +// + +#import "SimpleAuthVKontakteWebProvider.h" +#import "SimpleAuthVKontakteWebLoginViewController.h" + +#import "UIViewController+SimpleAuthAdditions.h" +#import + +@implementation SimpleAuthVKontakteWebProvider + +#pragma mark - SimpleAuthProvider + ++ (NSString *)type { + return @"vkontakte-web"; +} + + ++ (NSDictionary *)defaultOptions { + + // Default present block + SimpleAuthInterfaceHandler presentBlock = ^(UIViewController *controller) { + UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:controller]; + navigation.modalPresentationStyle = UIModalPresentationFormSheet; + UIViewController *presented = [UIViewController SimpleAuth_presentedViewController]; + [presented presentViewController:navigation animated:YES completion:nil]; + }; + + // Default dismiss block + SimpleAuthInterfaceHandler dismissBlock = ^(id controller) { + [controller dismissViewControllerAnimated:YES completion:nil]; + }; + + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithDictionary:[super defaultOptions]]; + dictionary[SimpleAuthPresentInterfaceBlockKey] = presentBlock; + dictionary[SimpleAuthDismissInterfaceBlockKey] = dismissBlock; + dictionary[SimpleAuthRedirectURIKey] = @"https://oauth.vk.com/blank.html"; + dictionary[@"scope"] = @[ @"email, offline" ]; + return dictionary; +} + + +- (void)authorizeWithCompletion:(SimpleAuthRequestHandler)completion { + [[[self accessToken] + flattenMap:^(NSDictionary *response) { + NSArray *signals = @[ + [self accountWithAccessToken:response], + [RACSignal return:response] + ]; + return [self rac_liftSelector:@selector(dictionaryWithAccount:accessToken:) withSignalsFromArray:signals]; + }] + subscribeNext:^(id x) { + completion(x, nil); + } + error:^(NSError *error) { + completion(nil, error); + }]; +} + + +#pragma mark - Private + +- (RACSignal *)accessToken { + return [RACSignal createSignal:^RACDisposable *(id subscriber) { + dispatch_async(dispatch_get_main_queue(), ^{ + SimpleAuthFacebookWebLoginViewController *login = [[SimpleAuthFacebookWebLoginViewController alloc] initWithOptions:self.options]; + + login.completion = ^(UIViewController *controller, NSURL *URL, NSError *error) { + SimpleAuthInterfaceHandler block = self.options[SimpleAuthDismissInterfaceBlockKey]; + block(controller); + + // Parse URL + NSString *fragment = [URL fragment]; + NSDictionary *dictionary = [CMDQueryStringSerialization dictionaryWithQueryString:fragment]; + id token = dictionary[@"access_token"]; + id expiration = dictionary[@"expires_in"]; + + // Check for error + if (!token || !expiration) { + [subscriber sendError:error]; + return; + } + + // Send completion + [subscriber sendNext:dictionary]; + [subscriber sendCompleted]; + }; + + SimpleAuthInterfaceHandler block = self.options[SimpleAuthPresentInterfaceBlockKey]; + block(login); + }); + return nil; + }]; +} + + +- (RACSignal *)accountWithAccessToken:(NSDictionary *)accessToken { + return [RACSignal createSignal:^RACDisposable *(id subscriber) { + NSDictionary *parameters = @{ @"access_token" : accessToken[@"access_token"] }; + NSString *URLString = [NSString stringWithFormat: + @"https://graph.facebook.com/me?%@", + [CMDQueryStringSerialization queryStringWithDictionary:parameters]]; + NSURL *URL = [NSURL URLWithString:URLString]; + NSURLRequest *request = [NSURLRequest requestWithURL:URL]; + [NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 99)]; + NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; + if ([indexSet containsIndex:statusCode] && data) { + NSError *parseError = nil; + NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError]; + if (dictionary) { + [subscriber sendNext:dictionary]; + [subscriber sendCompleted]; + } + else { + NSMutableDictionary *dictionary = [NSMutableDictionary new]; + if (parseError) { + dictionary[NSUnderlyingErrorKey] = parseError; + } + NSError *error = [NSError errorWithDomain:SimpleAuthErrorDomain code:SimpleAuthErrorInvalidData userInfo:dictionary]; + [subscriber sendNext:error]; + } + } + else { + NSMutableDictionary *dictionary = [NSMutableDictionary new]; + if (connectionError) { + dictionary[NSUnderlyingErrorKey] = connectionError; + } + dictionary[SimpleAuthErrorStatusCodeKey] = @(statusCode); + NSError *error = [NSError errorWithDomain:SimpleAuthErrorDomain code:SimpleAuthErrorNetwork userInfo:dictionary]; + [subscriber sendError:error]; + } + }]; + return nil; + }]; +} + + +- (NSDictionary *)dictionaryWithAccount:(NSDictionary *)account accessToken:(NSDictionary *)accessToken { + NSMutableDictionary *dictionary = [NSMutableDictionary new]; + + // Provider + dictionary[@"provider"] = [[self class] type]; + + // Credentials + NSTimeInterval expiresAtInterval = [accessToken[@"expires_in"] doubleValue]; + NSDate *expiresAtDate = [NSDate dateWithTimeIntervalSinceNow:expiresAtInterval]; + dictionary[@"credentials"] = @{ + @"token" : accessToken[@"access_token"], + @"expires_at" : expiresAtDate + }; + + // User ID + dictionary[@"uid"] = account[@"id"]; + + // Raw response + dictionary[@"extra"] = @{ + @"raw_info" : account + }; + + // Profile image + NSString *avatar = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?type=large", account[@"id"]]; + + // Location + NSString *location = account[@"location"][@"name"]; + + // User info + NSMutableDictionary *user = [NSMutableDictionary new]; + if (account[@"email"]) { + user[@"email"] = account[@"email"]; + } + user[@"name"] = account[@"name"]; + user[@"first_name"] = account[@"first_name"]; + user[@"last_name"] = account[@"last_name"]; + user[@"image"] = avatar; + if (location) { + user[@"location"] = location; + } + user[@"verified"] = account[@"verified"] ?: @NO; + user[@"urls"] = @{ + @"Facebook" : account[@"link"], + }; + dictionary[@"info"] = user; + + return dictionary; +} + +@end diff --git a/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.h b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.h new file mode 100644 index 0000000..fa77d0e --- /dev/null +++ b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.h @@ -0,0 +1,12 @@ +// +// SimpleAuthVKontakteWebLoginViewController.h +// SimpleAuth +// +// Created by Mike Cooper on 7/6/15. +// + +#import "SimpleAuthWebViewController.h" + +@interface SimpleAuthVKontakteWebLoginViewController : SimpleAuthWebViewController + +@end diff --git a/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.m b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.m new file mode 100644 index 0000000..0968e6a --- /dev/null +++ b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.m @@ -0,0 +1,40 @@ +// +// SimpleAuthVKontakteWebLoginViewController.m +// SimpleAuth +// +// Created by Mike Cooper on 7/6/15. + +// + +#import "SimpleAuthVKontakteWebLoginViewController.h" + +@implementation SimpleAuthVKontakteWebLoginViewController + +#pragma mark - SimpleAuthWebViewController + +- (instancetype)initWithOptions:(NSDictionary *)options requestToken:(NSDictionary *)requestToken { + if ((self = [super initWithOptions:options requestToken:requestToken])) { + self.title = @"VKontakte"; + } + return self; +} + +- (NSURLRequest *)initialRequest { + NSDictionary *parameters = @{ + @"client_id" : self.options[@"app_id"], + @"redirect_uri" : self.options[SimpleAuthRedirectURIKey], + @"response_type" : @"token", + @"scope" : [self.options[@"permissions"] componentsJoinedByString:@","], + @"display" : @"mobile", + @"v" : @"5.34" + }; + + NSString *URLString = [NSString stringWithFormat: + @"https://oauth.vk.com/authorize?%@", + [CMDQueryStringSerialization queryStringWithDictionary:parameters]]; + NSURL *URL = [NSURL URLWithString:URLString]; + + return [NSURLRequest requestWithURL:URL]; +} + +@end From 76dd5f618b34dc232a61ff05fc4abcefa9f6859f Mon Sep 17 00:00:00 2001 From: MikhailKupriyanov Date: Tue, 7 Jul 2015 21:48:10 +0300 Subject: [PATCH 02/10] add VKontakte provider --- Example/Podfile.lock | 9 +- Example/SimpleAuth/Providers.plist | 1 + Example/SimpleAuth/SADAppDelegate.m | 3 + ...impleAuthVKontakteWebLoginViewController.h | 2 +- ...impleAuthVKontakteWebLoginViewController.m | 7 +- ...der.h => SimpleAuthVKontakteWebProvider.h} | 2 +- .../SimpleAuthVKontakteWebProvider.m | 169 ++++++++++++++++++ Pod/Resources/ru.lproj/Localizable.strings | 10 ++ SimpleAuth.podspec | 6 + 9 files changed, 200 insertions(+), 9 deletions(-) rename Pod/Providers/VKontakteWeb/{SimpleAuthFaceBookWebProvider.h => SimpleAuthVKontakteWebProvider.h} (78%) create mode 100644 Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebProvider.m create mode 100644 Pod/Resources/ru.lproj/Localizable.strings diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 826f91f..6eb4463 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -31,6 +31,7 @@ PODS: - SimpleAuth/Tumblr (= 0.3.9) - SimpleAuth/Twitter (= 0.3.9) - SimpleAuth/TwitterWeb (= 0.3.9) + - SimpleAuth/VKontakteWeb (= 0.3.9) - SimpleAuth/BoxWeb (0.3.9): - SimpleAuth/Core - SimpleAuth/Core (0.3.9): @@ -72,13 +73,15 @@ PODS: - SimpleAuth/TwitterWeb (0.3.9): - cocoa-oauth - SimpleAuth/Core + - SimpleAuth/VKontakteWeb (0.3.9): + - SimpleAuth/Core DEPENDENCIES: - SimpleAuth (from `..`) EXTERNAL SOURCES: SimpleAuth: - :path: ".." + :path: .. SPEC CHECKSUMS: CMDQueryStringSerialization: 03c5d9847a4eaa2b3e4e439ce1ae24f914cc7fe1 @@ -86,6 +89,6 @@ SPEC CHECKSUMS: ISO8601: 8805b6cd6b2d0f7e594f7c5b50e8b00b51695ac0 NSData+Base64: 4e84902c4db907a15673474677e57763ef3903e4 ReactiveCocoa: e2db045570aa97c695e7aa97c2bcab222ae51f4a - SimpleAuth: bc7d594f90711a7e6ef7624dce5aa8c8b09770ab + SimpleAuth: 84c0a98a8797f3b9400d699f3a2c7e3be5dde1ca -COCOAPODS: 0.36.4 +COCOAPODS: 0.37.2 diff --git a/Example/SimpleAuth/Providers.plist b/Example/SimpleAuth/Providers.plist index efa2451..624ff1a 100644 --- a/Example/SimpleAuth/Providers.plist +++ b/Example/SimpleAuth/Providers.plist @@ -19,5 +19,6 @@ trello-web box-web onedrive-web + vkontakte-web diff --git a/Example/SimpleAuth/SADAppDelegate.m b/Example/SimpleAuth/SADAppDelegate.m index 98a5cb2..348c459 100644 --- a/Example/SimpleAuth/SADAppDelegate.m +++ b/Example/SimpleAuth/SADAppDelegate.m @@ -88,6 +88,9 @@ - (void)configureAuthorizaionProviders { // client_id and client_secret are required SimpleAuth.configuration[@"onedrive-web"] = @{}; + + // client_id is required + SimpleAuth.configuration[@"vkontakte-web"] = @{}; } diff --git a/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.h b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.h index fa77d0e..89d5fca 100644 --- a/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.h +++ b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.h @@ -2,7 +2,7 @@ // SimpleAuthVKontakteWebLoginViewController.h // SimpleAuth // -// Created by Mike Cooper on 7/6/15. +// Created by Mikhail Kupriyanov on 7/7/15. // #import "SimpleAuthWebViewController.h" diff --git a/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.m b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.m index 0968e6a..3fa2d84 100644 --- a/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.m +++ b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebLoginViewController.m @@ -2,8 +2,7 @@ // SimpleAuthVKontakteWebLoginViewController.m // SimpleAuth // -// Created by Mike Cooper on 7/6/15. - +// Created by Mikhail Kupriyanov on 7/7/15. // #import "SimpleAuthVKontakteWebLoginViewController.h" @@ -21,10 +20,10 @@ - (instancetype)initWithOptions:(NSDictionary *)options requestToken:(NSDictiona - (NSURLRequest *)initialRequest { NSDictionary *parameters = @{ - @"client_id" : self.options[@"app_id"], + @"client_id" : self.options[@"client_id"], @"redirect_uri" : self.options[SimpleAuthRedirectURIKey], @"response_type" : @"token", - @"scope" : [self.options[@"permissions"] componentsJoinedByString:@","], + @"scope" : [self.options[@"permission"] componentsJoinedByString:@","], @"display" : @"mobile", @"v" : @"5.34" }; diff --git a/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.h b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebProvider.h similarity index 78% rename from Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.h rename to Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebProvider.h index d47d055..a3cff9c 100644 --- a/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.h +++ b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebProvider.h @@ -2,7 +2,7 @@ // SimpleAuthVKontakteWebProvider.h // SimpleAuth // -// Created by Caleb Davenport on 7/6/15. +// Created by Mikhail Kupriyanov on 7/7/15. // #import "SimpleAuthProvider.h" diff --git a/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebProvider.m b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebProvider.m new file mode 100644 index 0000000..12763f4 --- /dev/null +++ b/Pod/Providers/VKontakteWeb/SimpleAuthVKontakteWebProvider.m @@ -0,0 +1,169 @@ +// +// SimpleAuthVKontakteWebProvider.m +// SimpleAuth +// +// Created by Mikhail Kupriyanov on 7/7/15. +// + +#import "SimpleAuthVKontakteWebProvider.h" +#import "SimpleAuthVKontakteWebLoginViewController.h" + +#import "UIViewController+SimpleAuthAdditions.h" +#import + +static const NSString *kVersion_api = @"5.34"; + +@implementation SimpleAuthVKontakteWebProvider + +#pragma mark - SimpleAuthProvider + ++ (NSString *)type { + return @"vkontakte-web"; +} + + ++ (NSDictionary *)defaultOptions { + + // Default present block + SimpleAuthInterfaceHandler presentBlock = ^(UIViewController *controller) { + UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:controller]; + navigation.modalPresentationStyle = UIModalPresentationFormSheet; + UIViewController *presented = [UIViewController SimpleAuth_presentedViewController]; + [presented presentViewController:navigation animated:YES completion:nil]; + }; + + // Default dismiss block + SimpleAuthInterfaceHandler dismissBlock = ^(id controller) { + [controller dismissViewControllerAnimated:YES completion:nil]; + }; + + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithDictionary:[super defaultOptions]]; + dictionary[SimpleAuthPresentInterfaceBlockKey] = presentBlock; + dictionary[SimpleAuthDismissInterfaceBlockKey] = dismissBlock; + dictionary[SimpleAuthRedirectURIKey] = @"https://oauth.vk.com/blank.html"; + dictionary[@"permission"] = @[ @"email, offline" ]; + dictionary[@"v"] = [kVersion_api copy]; + return dictionary; +} + +- (void)authorizeWithCompletion:(SimpleAuthRequestHandler)completion { + [[[self accessToken] + flattenMap:^RACStream *(NSString *response) { + NSArray *signals = @[ + [self accountWithAccessToken:response], + [RACSignal return:response] + ]; + return [self rac_liftSelector:@selector(dictionaryWithAccount:accessToken:) withSignalsFromArray:signals]; + }] + subscribeNext:^(NSDictionary *response) { + completion(response, nil); + } + error:^(NSError *error) { + completion(nil, error); + }]; +} + + +#pragma mark - Private + +- (RACSignal *)accessToken { + return [RACSignal createSignal:^RACDisposable *(id subscriber) { + dispatch_async(dispatch_get_main_queue(), ^{ + SimpleAuthVKontakteWebLoginViewController *login = [[SimpleAuthVKontakteWebLoginViewController alloc] initWithOptions:self.options]; + login.completion = ^(UIViewController *login, NSURL *URL, NSError *error) { + SimpleAuthInterfaceHandler dismissBlock = self.options[SimpleAuthDismissInterfaceBlockKey]; + dismissBlock(login); + + // Parse URL + NSString *fragment = [URL fragment]; + NSDictionary *dictionary = [CMDQueryStringSerialization dictionaryWithQueryString:fragment]; + NSString *access_token = dictionary[@"access_token"]; + + // Check for error + if (![access_token length]) { + [subscriber sendError:error]; + return; + } + + // Send completion + [subscriber sendNext:dictionary]; + [subscriber sendCompleted]; + }; + + SimpleAuthInterfaceHandler block = self.options[SimpleAuthPresentInterfaceBlockKey]; + block(login); + }); + return nil; + }]; +} + + +- (RACSignal *)accountWithAccessToken:(NSDictionary *) dictionaryWithAccessToken { + return [RACSignal createSignal:^RACDisposable *(id subscriber) { + NSString *accessToken = dictionaryWithAccessToken[@"access_token"]; + NSString *user_id = dictionaryWithAccessToken[@"user_id"]; + NSString *fields = @"sex, bdate, city, country, photo_50, photo_100, photo_200_orig, photo_200, photo_400_orig, photo_max, photo_max_orig, photo_id, online, online_mobile, domain, has_mobile, contacts, connections, site, education, universities, schools, can_post, can_see_all_posts, can_see_audio, can_write_private_message, status, last_seen, common_count, relation, relatives, counters, screen_name, maiden_name, timezone, occupation,activities, interests, music, movies, tv, books, games, about, quotes, personal, friend_status"; + + NSDictionary *parameters = @{ @"access_token" : accessToken , @"user_id" : user_id, @"fields" : fields, @"v" : self.options[@"v"] }; + NSString *query = [CMDQueryStringSerialization queryStringWithDictionary:parameters]; + NSString *URLString = [NSString stringWithFormat:@"https://api.vk.com/method/users.get?%@", query]; + NSURL *URL = [NSURL URLWithString:URLString]; + NSURLRequest *request = [NSURLRequest requestWithURL:URL]; + [NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue + completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 99)]; + NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; + if ([indexSet containsIndex:statusCode] && data) { + NSError *parseError = nil; + NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError]; + if (dictionary) { + [subscriber sendNext:dictionary]; + [subscriber sendCompleted]; + } + else { + [subscriber sendError:parseError]; + } + } + else { + [subscriber sendError:connectionError]; + } + }]; + return nil; + }]; +} + + +#pragma mark - Private + +- (NSDictionary *)dictionaryWithAccount:(NSDictionary *)account accessToken:(NSDictionary *)accessToken{ + NSMutableDictionary *dictionary = [NSMutableDictionary new]; + NSArray *dataArray = (NSArray *) account[@"response"]; + NSDictionary *data = dataArray.lastObject; + // Provider + dictionary[@"provider"] = [[self class] type]; + + // Credentials + dictionary[@"credentials"] = @{ + @"access_token" : accessToken[@"access_token"], + @"expires_in" : accessToken[@"expires_in"] + }; + + // User ID + dictionary[@"user_id"] = accessToken[@"user_id"];; + + // Raw response + dictionary[@"extra"] = @{ + @"raw_info" : data + }; + + // User info + NSMutableDictionary *user = [NSMutableDictionary new]; + user[@"first_name"] = data[@"first_name"]; + user[@"last_name"] = data[@"last_name"]; + user[@"photo_max_orig"] = data[@"photo_max_orig"]; + + dictionary[@"user_info"] = user; + + return dictionary; +} +@end diff --git a/Pod/Resources/ru.lproj/Localizable.strings b/Pod/Resources/ru.lproj/Localizable.strings new file mode 100644 index 0000000..9a45a48 --- /dev/null +++ b/Pod/Resources/ru.lproj/Localizable.strings @@ -0,0 +1,10 @@ +/* + SimpleAuth.strings + SimpleAuth + + Created by Mikhail Kupriyanov on 7/7/15. + +*/ + +// General strings +"CANCEL" = "Отмена"; diff --git a/SimpleAuth.podspec b/SimpleAuth.podspec index 6125ab9..1eb9cbf 100755 --- a/SimpleAuth.podspec +++ b/SimpleAuth.podspec @@ -128,4 +128,10 @@ Pod::Spec.new do |s| ss.private_header_files = 'Pod/Providers/OneDriveWeb/*.h' end + s.subspec 'VKontakteWeb' do |ss| + ss.dependency 'SimpleAuth/Core' + ss.source_files = 'Pod/Providers/VKontakteWeb' + ss.private_header_files = 'Pod/Providers/VKontakteWeb/*.h' + end + end From 4259029da16ae50e0219301208ad4b25183dcbcb Mon Sep 17 00:00:00 2001 From: MikhailKupriyanov Date: Tue, 7 Jul 2015 21:53:59 +0300 Subject: [PATCH 03/10] fix readme --- Readme.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Readme.markdown b/Readme.markdown index 2a88cc2..434e48a 100644 --- a/Readme.markdown +++ b/Readme.markdown @@ -16,6 +16,7 @@ SimpleAuth currently has the following providers: - [Google](https://github.com/calebd/SimpleAuth/wiki/Google) - [Box](https://github.com/calebd/SimpleAuth/wiki/Box) - [OneDrive](https://github.com/calebd/SimpleAuth/wiki/OneDrive) +- [VKontakte](https://github.com/calebd/SimpleAuth/wiki/VKontakte) ## Installing @@ -97,3 +98,4 @@ Special thanks to my friend [@soffes](https://twitter.com/soffes) for advising o - [mouhcine](https://github.com/mouhcine): Meetup provider - [iamabhiee](https://github.com/iamabhiee): LinkedIn provider - [aschuch](https://github.com/aschuch): Sina Weibo provider +- [Mikhail_Kupriyanov](https://github.com/MikhailKupriyanov): VKontakte provider From 3c85b9c72f561144ff1dffdaff8c3a8910fdbfa6 Mon Sep 17 00:00:00 2001 From: MikhailKupriyanov Date: Fri, 10 Jul 2015 19:52:18 +0300 Subject: [PATCH 04/10] fix --- Pod/Resources/ru.lproj/Localizable.strings | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 Pod/Resources/ru.lproj/Localizable.strings diff --git a/Pod/Resources/ru.lproj/Localizable.strings b/Pod/Resources/ru.lproj/Localizable.strings deleted file mode 100644 index 9a45a48..0000000 --- a/Pod/Resources/ru.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -/* - SimpleAuth.strings - SimpleAuth - - Created by Mikhail Kupriyanov on 7/7/15. - -*/ - -// General strings -"CANCEL" = "Отмена"; From 3b8830c9f37fa5f337318355dc11c5a61b00dd6e Mon Sep 17 00:00:00 2001 From: MikhailKupriyanov Date: Thu, 6 Aug 2015 21:47:11 +0300 Subject: [PATCH 05/10] delete file --- .../SimpleAuthFaceBookWebProvider.m | 192 ------------------ 1 file changed, 192 deletions(-) delete mode 100644 Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.m diff --git a/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.m b/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.m deleted file mode 100644 index 4d77749..0000000 --- a/Pod/Providers/VKontakteWeb/SimpleAuthFaceBookWebProvider.m +++ /dev/null @@ -1,192 +0,0 @@ -// -// SimpleAuthVKontakteWebProvider.m -// SimpleAuth -// -// Created by Caleb Davenport on 7/6/15. -// - -#import "SimpleAuthVKontakteWebProvider.h" -#import "SimpleAuthVKontakteWebLoginViewController.h" - -#import "UIViewController+SimpleAuthAdditions.h" -#import - -@implementation SimpleAuthVKontakteWebProvider - -#pragma mark - SimpleAuthProvider - -+ (NSString *)type { - return @"vkontakte-web"; -} - - -+ (NSDictionary *)defaultOptions { - - // Default present block - SimpleAuthInterfaceHandler presentBlock = ^(UIViewController *controller) { - UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:controller]; - navigation.modalPresentationStyle = UIModalPresentationFormSheet; - UIViewController *presented = [UIViewController SimpleAuth_presentedViewController]; - [presented presentViewController:navigation animated:YES completion:nil]; - }; - - // Default dismiss block - SimpleAuthInterfaceHandler dismissBlock = ^(id controller) { - [controller dismissViewControllerAnimated:YES completion:nil]; - }; - - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithDictionary:[super defaultOptions]]; - dictionary[SimpleAuthPresentInterfaceBlockKey] = presentBlock; - dictionary[SimpleAuthDismissInterfaceBlockKey] = dismissBlock; - dictionary[SimpleAuthRedirectURIKey] = @"https://oauth.vk.com/blank.html"; - dictionary[@"scope"] = @[ @"email, offline" ]; - return dictionary; -} - - -- (void)authorizeWithCompletion:(SimpleAuthRequestHandler)completion { - [[[self accessToken] - flattenMap:^(NSDictionary *response) { - NSArray *signals = @[ - [self accountWithAccessToken:response], - [RACSignal return:response] - ]; - return [self rac_liftSelector:@selector(dictionaryWithAccount:accessToken:) withSignalsFromArray:signals]; - }] - subscribeNext:^(id x) { - completion(x, nil); - } - error:^(NSError *error) { - completion(nil, error); - }]; -} - - -#pragma mark - Private - -- (RACSignal *)accessToken { - return [RACSignal createSignal:^RACDisposable *(id subscriber) { - dispatch_async(dispatch_get_main_queue(), ^{ - SimpleAuthFacebookWebLoginViewController *login = [[SimpleAuthFacebookWebLoginViewController alloc] initWithOptions:self.options]; - - login.completion = ^(UIViewController *controller, NSURL *URL, NSError *error) { - SimpleAuthInterfaceHandler block = self.options[SimpleAuthDismissInterfaceBlockKey]; - block(controller); - - // Parse URL - NSString *fragment = [URL fragment]; - NSDictionary *dictionary = [CMDQueryStringSerialization dictionaryWithQueryString:fragment]; - id token = dictionary[@"access_token"]; - id expiration = dictionary[@"expires_in"]; - - // Check for error - if (!token || !expiration) { - [subscriber sendError:error]; - return; - } - - // Send completion - [subscriber sendNext:dictionary]; - [subscriber sendCompleted]; - }; - - SimpleAuthInterfaceHandler block = self.options[SimpleAuthPresentInterfaceBlockKey]; - block(login); - }); - return nil; - }]; -} - - -- (RACSignal *)accountWithAccessToken:(NSDictionary *)accessToken { - return [RACSignal createSignal:^RACDisposable *(id subscriber) { - NSDictionary *parameters = @{ @"access_token" : accessToken[@"access_token"] }; - NSString *URLString = [NSString stringWithFormat: - @"https://graph.facebook.com/me?%@", - [CMDQueryStringSerialization queryStringWithDictionary:parameters]]; - NSURL *URL = [NSURL URLWithString:URLString]; - NSURLRequest *request = [NSURLRequest requestWithURL:URL]; - [NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { - NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 99)]; - NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; - if ([indexSet containsIndex:statusCode] && data) { - NSError *parseError = nil; - NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError]; - if (dictionary) { - [subscriber sendNext:dictionary]; - [subscriber sendCompleted]; - } - else { - NSMutableDictionary *dictionary = [NSMutableDictionary new]; - if (parseError) { - dictionary[NSUnderlyingErrorKey] = parseError; - } - NSError *error = [NSError errorWithDomain:SimpleAuthErrorDomain code:SimpleAuthErrorInvalidData userInfo:dictionary]; - [subscriber sendNext:error]; - } - } - else { - NSMutableDictionary *dictionary = [NSMutableDictionary new]; - if (connectionError) { - dictionary[NSUnderlyingErrorKey] = connectionError; - } - dictionary[SimpleAuthErrorStatusCodeKey] = @(statusCode); - NSError *error = [NSError errorWithDomain:SimpleAuthErrorDomain code:SimpleAuthErrorNetwork userInfo:dictionary]; - [subscriber sendError:error]; - } - }]; - return nil; - }]; -} - - -- (NSDictionary *)dictionaryWithAccount:(NSDictionary *)account accessToken:(NSDictionary *)accessToken { - NSMutableDictionary *dictionary = [NSMutableDictionary new]; - - // Provider - dictionary[@"provider"] = [[self class] type]; - - // Credentials - NSTimeInterval expiresAtInterval = [accessToken[@"expires_in"] doubleValue]; - NSDate *expiresAtDate = [NSDate dateWithTimeIntervalSinceNow:expiresAtInterval]; - dictionary[@"credentials"] = @{ - @"token" : accessToken[@"access_token"], - @"expires_at" : expiresAtDate - }; - - // User ID - dictionary[@"uid"] = account[@"id"]; - - // Raw response - dictionary[@"extra"] = @{ - @"raw_info" : account - }; - - // Profile image - NSString *avatar = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?type=large", account[@"id"]]; - - // Location - NSString *location = account[@"location"][@"name"]; - - // User info - NSMutableDictionary *user = [NSMutableDictionary new]; - if (account[@"email"]) { - user[@"email"] = account[@"email"]; - } - user[@"name"] = account[@"name"]; - user[@"first_name"] = account[@"first_name"]; - user[@"last_name"] = account[@"last_name"]; - user[@"image"] = avatar; - if (location) { - user[@"location"] = location; - } - user[@"verified"] = account[@"verified"] ?: @NO; - user[@"urls"] = @{ - @"Facebook" : account[@"link"], - }; - dictionary[@"info"] = user; - - return dictionary; -} - -@end From e8ee65f6579f68acb8ed5c54f0ff5549cf4f6ae6 Mon Sep 17 00:00:00 2001 From: MikhailKupriyanov Date: Mon, 10 Aug 2015 13:33:22 +0300 Subject: [PATCH 06/10] Add default fields for Facebook api v2.4 --- Pod/Providers/Facebook/SimpleAuthFacebookProvider.m | 5 ++++- Pod/Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m b/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m index a9cd267..4eb89f3 100644 --- a/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m +++ b/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m @@ -65,7 +65,10 @@ - (RACSignal *)systemAccount { - (RACSignal *)remoteAccountWithSystemAccount:(ACAccount *)account { return [RACSignal createSignal:^RACDisposable *(id subscriber) { NSURL *URL = [NSURL URLWithString:@"https://graph.facebook.com/me"]; - SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodGET URL:URL parameters:nil]; + NSDictionary *parameters = @{ + @"fields" : @"name,last_name,verified,email,link" + }; + SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodGET URL:URL parameters:parameters]; request.account = account; [request performRequestWithHandler:^(NSData *data, NSHTTPURLResponse *response, NSError *connectionError) { NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 99)]; diff --git a/Pod/Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m b/Pod/Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m index 411cfdf..ccfd984 100644 --- a/Pod/Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m +++ b/Pod/Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m @@ -101,7 +101,10 @@ - (RACSignal *)accessToken { - (RACSignal *)accountWithAccessToken:(NSDictionary *)accessToken { return [RACSignal createSignal:^RACDisposable *(id subscriber) { - NSDictionary *parameters = @{ @"access_token" : accessToken[@"access_token"] }; + NSDictionary *parameters = @{ + @"access_token" : accessToken[@"access_token"], + @"fields" : @"name,first_name,last_name,verified,email,location,link" + }; NSString *URLString = [NSString stringWithFormat: @"https://graph.facebook.com/me?%@", [CMDQueryStringSerialization queryStringWithDictionary:parameters]]; From c9a1d70d7d6c4c8b784f04005f0e2b02c550acb9 Mon Sep 17 00:00:00 2001 From: MikhailKupriyanov Date: Thu, 13 Aug 2015 18:00:12 +0300 Subject: [PATCH 07/10] fix FB response fields --- Pod/Providers/Facebook/SimpleAuthFacebookProvider.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m b/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m index 4eb89f3..2e540df 100644 --- a/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m +++ b/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m @@ -66,7 +66,7 @@ - (RACSignal *)remoteAccountWithSystemAccount:(ACAccount *)account { return [RACSignal createSignal:^RACDisposable *(id subscriber) { NSURL *URL = [NSURL URLWithString:@"https://graph.facebook.com/me"]; NSDictionary *parameters = @{ - @"fields" : @"name,last_name,verified,email,link" + @"fields" : @"name,first_name,last_name,verified,email,location,link" }; SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodGET URL:URL parameters:parameters]; request.account = account; From 067a21100ff47d07720905046f56ecf3adec81b1 Mon Sep 17 00:00:00 2001 From: MikhailKupriyanov Date: Sat, 29 Aug 2015 12:05:21 +0300 Subject: [PATCH 08/10] add re-auth Facebook --- Example/SimpleAuth/SADAppDelegate.m | 1 + Pod/Core/SimpleAuth.h | 24 +++++++ Pod/Core/SimpleAuth.m | 27 ++++++++ Pod/Core/SimpleAuthProvider.h | 1 + Pod/Core/SimpleAuthProvider.m | 5 ++ .../Facebook/SimpleAuthFacebookProvider.m | 3 +- .../SimpleAuthFaceBookWebProvider.m | 63 +++++++++++++++++++ 7 files changed, 123 insertions(+), 1 deletion(-) diff --git a/Example/SimpleAuth/SADAppDelegate.m b/Example/SimpleAuth/SADAppDelegate.m index 348c459..a6919a6 100644 --- a/Example/SimpleAuth/SADAppDelegate.m +++ b/Example/SimpleAuth/SADAppDelegate.m @@ -51,6 +51,7 @@ - (void)configureAuthorizaionProviders { // app_id is required SimpleAuth.configuration[@"facebook"] = @{}; + // app_secret optional required for re-authorization of token SimpleAuth.configuration[@"facebook-web"] = @{}; // client_id and redirect_uri are required diff --git a/Pod/Core/SimpleAuth.h b/Pod/Core/SimpleAuth.h index 38edcea..c8965ea 100644 --- a/Pod/Core/SimpleAuth.h +++ b/Pod/Core/SimpleAuth.h @@ -46,6 +46,30 @@ */ + (void)authorize:(NSString *)provider options:(NSDictionary *)options completion:(SimpleAuthRequestHandler)completion; +/** + Perform re-authorization with the given provider and all previously configured + and default provider options. This is for providers where the token expires and you + want to renew the non expired token. + + @param token the unexpired token recieved from the service + @param completion Called on the main queue when the operation is complete. + + @see +authorize:options:completion: + */ ++ (void)reAuthorize:(NSString *)provider token:(NSString *)token completion:(SimpleAuthRequestHandler)completion; + +/** + Perform re-authorization with the given provider and all previously configured + and default provider options. This is for providers where the token expires and you + want to renew the non expired token. + + @param token the unexpired token recieved from the service + @param completion Called on the main queue when the operation is complete. + + @see +authorize:options:completion: + */ ++ (void)reAuthorize:(NSString *)type options:(NSDictionary *)options token:(NSString *)token completion:(SimpleAuthRequestHandler)completion; + /** Determine whether the provider can handle the callback URL or not. diff --git a/Pod/Core/SimpleAuth.m b/Pod/Core/SimpleAuth.m index 3037b4f..f35f977 100644 --- a/Pod/Core/SimpleAuth.m +++ b/Pod/Core/SimpleAuth.m @@ -62,6 +62,33 @@ + (void)authorize:(NSString *)type options:(NSDictionary *)options completion:(S }]; } ++ (void)reAuthorize:(NSString *)type token:(NSString *)token completion:(SimpleAuthRequestHandler)completion { + [self reAuthorize:type options:nil token:token completion:completion]; +} + + ++ (void)reAuthorize:(NSString *)type options:(NSDictionary *)options token:(NSString *)token completion:(SimpleAuthRequestHandler)completion{ + // Load the provider class + Class klass = [self providers][type]; + NSAssert(klass, @"There is no class registered to handle %@ requests.", type); + + // Create options dictionary + NSDictionary *defaultOptions = [klass defaultOptions]; + NSDictionary *registeredOptions = [self configuration][type]; + NSMutableDictionary *resolvedOptions = [NSMutableDictionary new]; + [resolvedOptions addEntriesFromDictionary:defaultOptions]; + [resolvedOptions addEntriesFromDictionary:registeredOptions]; + [resolvedOptions addEntriesFromDictionary:options]; + + // Create the provider and run authorization + SimpleAuthProvider *provider = [(SimpleAuthProvider *)[klass alloc] initWithOptions:resolvedOptions]; + [provider reAuthorizeWithToken:token completionHandler:^(id responseObject, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(responseObject, error); + }); + [provider class]; // Kepp the provider around until the callback is complete + }]; +} + (BOOL)handleCallback:(NSURL *)URL { NSParameterAssert(URL != nil); diff --git a/Pod/Core/SimpleAuthProvider.h b/Pod/Core/SimpleAuthProvider.h index a531d37..57534ce 100644 --- a/Pod/Core/SimpleAuthProvider.h +++ b/Pod/Core/SimpleAuthProvider.h @@ -20,5 +20,6 @@ - (instancetype)initWithOptions:(NSDictionary *)options; - (void)authorizeWithCompletion:(SimpleAuthRequestHandler)completion; +- (void)reAuthorizeWithToken:(NSString *)token completionHandler:(SimpleAuthRequestHandler)completion; @end diff --git a/Pod/Core/SimpleAuthProvider.m b/Pod/Core/SimpleAuthProvider.m index e1ec723..05ac21b 100644 --- a/Pod/Core/SimpleAuthProvider.m +++ b/Pod/Core/SimpleAuthProvider.m @@ -53,4 +53,9 @@ - (void)authorizeWithCompletion:(SimpleAuthRequestHandler)completion { [self doesNotRecognizeSelector:_cmd]; } +- (void)reAuthorizeWithToken:(NSString *)token completionHandler:(SimpleAuthRequestHandler)completion { + // Provider doesn't have a re authorize token method setup revert back to standard authorization + [self authorizeWithCompletion:completion]; +} + @end diff --git a/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m b/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m index 2e540df..ca880e6 100644 --- a/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m +++ b/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m @@ -143,7 +143,8 @@ - (NSDictionary *)infoDictionaryWithRemoteAccount:(NSDictionary *)remoteAccount if (location) { dictionary[@"location"] = location; } - + if (remoteAccount[@"verified"]) + user[@"verified"] = remoteAccount[@"verified"]; dictionary[@"urls"] = @{ @"Facebook": remoteAccount[@"link"] }; diff --git a/Pod/Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m b/Pod/Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m index ccfd984..9fa7334 100644 --- a/Pod/Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m +++ b/Pod/Providers/FacebookWeb/SimpleAuthFaceBookWebProvider.m @@ -62,6 +62,27 @@ - (void)authorizeWithCompletion:(SimpleAuthRequestHandler)completion { }]; } +- (void)reAuthorizeWithToken:(NSString *)token completionHandler:(SimpleAuthRequestHandler)completion{ + if (token.length <= 0) { + // There is no token so we are going to use the standard login method + [self authorizeWithCompletion:completion]; + return; + } + [[[self reAuthAccessTokenWithToken:token] + flattenMap:^(NSDictionary *response) { + NSArray *signals = @[ + [self accountWithAccessToken:response], + [RACSignal return:response] + ]; + return [self rac_liftSelector:@selector(dictionaryWithAccount:accessToken:) withSignalsFromArray:signals]; + }] + subscribeNext:^(id x) { + completion(x, nil); + } + error:^(NSError *error) { + completion(nil, error); + }]; +} #pragma mark - Private @@ -98,6 +119,48 @@ - (RACSignal *)accessToken { }]; } +- (RACSignal *)reAuthAccessTokenWithToken:(NSString *)preToken { + return [RACSignal createSignal:^RACDisposable *(id subscriber) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSDictionary *parameters = @{ + @"client_id" : self.options[@"app_id"], + @"grant_type" :@"fb_exchange_token", + @"response_type" : @"token", + @"grant_type" :@"fb_exchange_token", + @"client_secret" : self.options[@"app_secret"], + @"fb_exchange_token" : preToken + }; + + NSString *URLString = [NSString stringWithFormat: + @"https://graph.facebook.com/oauth/access_token?%@", + [CMDQueryStringSerialization queryStringWithDictionary:parameters]]; + NSError *responseError = nil; + NSURLResponse *response = nil; + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:URLString]]; + NSData *dataResponse = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&responseError]; + if (!responseError){ + NSString *responseString = [[NSString alloc] initWithData:dataResponse encoding:NSUTF8StringEncoding]; + NSDictionary *dictionary = [CMDQueryStringSerialization dictionaryWithQueryString:responseString]; + id token = dictionary[@"access_token"]; + id expiration = dictionary[@"expires"]; + + // Check for error + if (!token || !expiration) { + [subscriber sendError:[NSError errorWithDomain:@"Missing token or experation from facebook" code:101 userInfo:nil]]; + return; + } + // Send completion + [subscriber sendNext:@{@"access_token" : token, @"expires_in" : expiration}]; + [subscriber sendCompleted]; + } + else { + [subscriber sendError:responseError]; + return ; + } + }); + return nil; + }]; +} - (RACSignal *)accountWithAccessToken:(NSDictionary *)accessToken { return [RACSignal createSignal:^RACDisposable *(id subscriber) { From 3626975c417dbe2518574412b3f74bd4e0b35e3c Mon Sep 17 00:00:00 2001 From: MikhailKupriyanov Date: Sat, 29 Aug 2015 14:39:54 +0300 Subject: [PATCH 09/10] fix dictionary --- Pod/Providers/Facebook/SimpleAuthFacebookProvider.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m b/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m index ca880e6..6c00b1c 100644 --- a/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m +++ b/Pod/Providers/Facebook/SimpleAuthFacebookProvider.m @@ -144,7 +144,7 @@ - (NSDictionary *)infoDictionaryWithRemoteAccount:(NSDictionary *)remoteAccount dictionary[@"location"] = location; } if (remoteAccount[@"verified"]) - user[@"verified"] = remoteAccount[@"verified"]; + dictionary[@"verified"] = remoteAccount[@"verified"]; dictionary[@"urls"] = @{ @"Facebook": remoteAccount[@"link"] }; From 3a30b547faa64cfe7c6f9f531b33ab38b6854122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B8=D1=85=D0=B0=D0=B8=D0=BB=20=D0=9A=D1=83=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=D1=8F=D0=BD=D0=BE=D0=B2?= Date: Fri, 11 Dec 2015 17:19:10 +0300 Subject: [PATCH 10/10] RAC 2.5 dependency for (Objective-C) --- SimpleAuth.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SimpleAuth.podspec b/SimpleAuth.podspec index 1eb9cbf..576a92b 100755 --- a/SimpleAuth.podspec +++ b/SimpleAuth.podspec @@ -12,7 +12,7 @@ Pod::Spec.new do |s| s.subspec 'Core' do |ss| ss.source_files = 'Pod/Core' ss.public_header_files = 'Pod/Core/SimpleAuth.h', 'Pod/Core/SimpleAuthDefines.h' - ss.dependency 'ReactiveCocoa' + ss.dependency 'ReactiveCocoa', '~>2.5' ss.dependency 'CMDQueryStringSerialization' ss.ios.frameworks = 'UIKit'