Pull to refresh

oAuth для iOS приложений

Reading time3 min
Views12K
Экран приветствия клуба Трельяж для iPhone
Вечерело. Теплая августовская суббота предрасполагала к реализации oAuth авторизации на Google и Facebook для iOS клиента клуба интеллектуальных игр.

Поверхностный поиск в сети нам намекнул, что обе компании предоставляют средства для разработчиков, позволяющие поскорее автоматизировать эту рутину, и вернуться к более интересным задачам непосредственного программирования игрового процесса.

Быстрые ссылки на сами библиотеки: Googlegtm-oauth2, Facebookfacebook-ios-sdk

О нюансах интеграции под катом.


Google


Первым делом, идем в API Console и получаем там Client ID и Client Secret. Процедура быстрая и бесплатная.

Подключаем к проекту библиотеку gtm-oauth2. На кнопку авторизации через google вешаем что-то вроде:

#import "GTMOAuth2ViewControllerTouch.h"
...
- (void)onGoogleAuth:(id)sender 
{
    GTMOAuth2ViewControllerTouch *viewController;
    viewController = [[[GTMOAuth2ViewControllerTouch alloc] 
                       initWithScope:@"https://www.googleapis.com/auth/userinfo#email"
                       clientID:@OAUTH_GOOGLE_CLIENT_ID
                       clientSecret:@OAUTH_GOOGLE_CLIENT_SECRET
                       keychainItemName:@"OAuth2 MYAPP: Google"
                       delegate:self
                       finishedSelector:@selector(viewController:finishedWithAuth:error:)] autorelease
                      ];
    [[self navigationController] pushViewController:viewController animated:YES]; 
}

При этом откроется ViewController с браузером и стандартным web запросом аутентификации от Google. После того, как пользователь пройдет процедуру ввода email и пароля, вызовется следующая функция, где вы уже сможете взять подтвержденный email вошедшего пользователя и отреагировать на факт успешного логина:

- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
      finishedWithAuth:(GTMOAuth2Authentication *)auth
                 error:(NSError *)error {
    if (error != nil) {
        // Authentication failed
    } else {
        if (auth.canAuthorize){
            // auth.userEmail 
        }
    }
}

В нашей задаче этого было достаточно, но Google API на этом не ограничивается, и через разные scope можно запросить права для работы со многими сервисами Google. Включая youtube и buzz.

Facebook


С Facebook все немного сложнее. Вначале, как водится, нужно зарегистрировать свое «приложение» вот здесь, если, конечно вы этого не сделали раньше.

Дальше, устанавливаем в проект facebook-ios-sdk, в делегат своего класса приложения добавляем реализацию протоколов FBSessionDelegate и FBRequestDelegate

#import "FBConnect.h"

@interface AppDelegate : NSObject <UIApplicationDelegate, FBSessionDelegate, FBRequestDelegate> {
	UIWindow *window;
        ....
        Facebook* facebook;
}
....
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url;
- (void)fbDidLogin;
- (void)request:(FBRequest *)request didLoad:(id)result;
</pre></code>
Простейшая реализация выглядит примерно следующим образом:

<code><pre>
- (void)facebookLogin
{
    if (!facebook) facebook = [[Facebook alloc] initWithAppId:@FACEBOOK_APP_ID];
    [facebook authorize:nil delegate:self];
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url 
{
    return [facebook handleOpenURL:url]; 
}

- (void)fbDidLogin {
    [facebook requestWithGraphPath:@"me" andDelegate:self];
}

- (void)request:(FBRequest *)request didLoad:(id)result {
    // result - NSDictionary
};


Визуально это выглядит как выход из приожения, открытие отдельного процесса Safari, веб формы логина и подтверждения от Facebook, закрытие браузера и переоткрытие приложения с уже залогиненым пользователем. И действительно, браузер выполняется как отдельный от приложения процесс. Но как приложение при этом перехватывает возврат из браузера? Ларчик открывается относительно просто. В info.plist вашего приложения мы регистрируем тип URL который перехватывает ваше приложение, после чего Safari становится «в курсе» куда передать управление. Делаем это из Xcode следующим образом (вместо YOUAPPID пишем ID нашего приложения на Facebook):

Редактирование info.plist для обработки внешних URL


Вуаля, остается в функции request didLoad сделать реакцию на вход Facebook пользователя, и дело в шляпе.

Запрос Facebook прав, хранение сессионных ключей в KeyChains, и прочие вкусности подробно расписаны в документации. Для наших целей (простая аутентификация) вышеописанного оказалось достаточно, но возможности API там довольно широкие. Вплоть до «запостить на стену фоточку» и «отправить сообщение другу по xmpp в чятик».

Пятница, 13


Нет, мы не о маньяке в хоккейной маске и с огромным тесаком. Речь пойдет о небольшой ложке дегтя, которая выразилась в том, что все, почему-то, считают своим долгом засунуть в свою «библиотеку» из двух классов, ЕЩЕ одну реализацию JSON. Граждане, да когда же это прекратится? Тем более, и у Google и у Facebook используется одна и та же реализация. А именно SBJSON, причем разных версий и несовместимый по интерфейсам. Простой напильник, конечно же, проблему решает, но, боюсь, из-за отсутствия штатной реализации от Apple, iOS разработчикам пора придумывать новый термин Json-Hell.

Держите в проекте реализацию JSON (а также zlib, и прочий стаф) в единственном экземпляре, и да пребудет с вами сила.
Tags:
Hubs:
+23
Comments17

Articles