Pull to refresh

Яндекс OAuth авторизация в iOS

Reading time 4 min
Views 6.3K
Для вызовов API Яндекса приложению нужен токен. Получить его можно двумя способами. Первый способ самый простой — спрашиваем у пользоватея его логин и пароль и делаем POST-запрос на oauth.yandex.ru/token. Но есть пара проблем: пользователь может не захотеть доверить свой пароль от учетной записи стороннему приложению, да и сам Яндекс не рекомендует так делать. Второй немного более сложный в реализации способ и является предметом топика — OAuth авторизация.

Регистрация приложения


Процедура подробно описана на api.yandex.ru/oauth/doc/dg/tasks/register-client.xml.

На этапе регистрации придумываем url-схему



И запоминаем Id приложения



Возможные варианты реализации


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

Тут возможны два подхода.
1) Регистрируем приложение обработчиком указанной URL-схемы в системе. Открываем пользователю Safari с формой авторизации и ждем перезапуска приложения.
Регистрация приложения обработчиком URL-схемы подробно описана здесь

2) Показываем UIWebView и в его делегатских методах отлавливаем переход по нашей схеме.

Второй подход мне кажется более простым, т.к. во-первых пользователь не покидает наше приложение, а во-вторых авторизация через Яндекс может быть едиственным способом входа в наше приложение.

Пишем код


Создаем тестовый проект в XCode.





Добавляем в проект YandexOauthViewController.* (ссылка на исходный код в конце статьи).

В YandexOauthViewController.h изменяем в следующих строках значения на ваши:

#define URL_SCHEME @"iostestapp"
#define CLIENT_ID @"6ef1c6dc6f134a2daa67cc905e5c1a3d"


Во ViewController.h импортируем YandexOauthViewController.h и обявляем себя «реализатором» протокола YandexOauthViewControllerDelegate.

#import <UIKit/UIKit.h>

#import "YandexOauthViewController.h"

@interface ViewController : UIViewController <YandexOauthViewControllerDelegate>

@end


В тестовом приложении будем авторизировать пользвателя при запуске. Для этого во ViewController.m изменяем метод ViewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    
    YandexOauthViewController *cntrl = [[YandexOauthViewController alloc] init];
    cntrl.delegate = self;
    [self.navigationController presentModalViewController:cntrl animated:YES];
}


Какой еще self.navigationController, спросите вы и будете правы — навигейшен контроллера еще нет, поэтому добавляем его в AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.viewController];
    
    self.window.rootViewController = nav;
    [self.window makeKeyAndVisible];
    return YES;
}


Запускаем приложение и видим так нужную нам форму авторизации.



Кнопка слева (с крестиком) убирает форму авторизации с экрана, а правая кнопка возвращает пользователя на страницу авторизации. Дело в том, что в некоторых случаях Яндекс теряет цель нашего захода в авторизацию и и отображает профиль пользователя из которого нам токен уже не передадут.

После ввода логина пароля и, в некоторых случаях, подтверждения постоянной авторизации на данном устройстве Яндекс перенаправляет нас по URL-схеме указанной прирегистрации приложения. Рассмотрим перехват этого перехода в файле YandexOauthViewController.m.

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    //Получаем URL
    NSURL *url = [request URL];
    
    //Проверяем на соответствие пользовательской URL-схеме
    if ([url.scheme isEqualToString:URL_SCHEME])
    {
        //убираем индикатор сетевой активности
        UIApplication* app = [UIApplication sharedApplication];
        app.networkActivityIndicatorVisible = NO;
        
        //разбираем URL на отдельные элементы
        //наш токен будет в массиве arr под индексом 2
        NSArray *arr = [[url description] componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"#=&"]];
        
        //говорим делегату об успешной авторизации и передаем токен
        if ([delegate respondsToSelector:@selector(yandexOauthViewController:succesfullLoginWithToken:)])
        {
            [delegate yandexOauthViewController:self succesfullLoginWithToken:[arr objectAtIndex:2]];
        }
        
        //запрещаем UIWebView открывать URL
        return NO;
    }
    
    //разрешаем UIWebView переход по URL
    return YES;
}


Осталось в ViewController.m реализовать протокол YandexOauthViewControllerDelegate.

- (void)yandexOauthViewController:(YandexOauthViewController *)controller 
         succesfullLoginWithToken:(NSString *)token
{
    [self.navigationController dismissModalViewControllerAnimated:YES];
    
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Авторизация удалась" 
                                                    message:[NSString stringWithFormat:@"Токен %@",token]                                                    
                                                   delegate:nil 
                                          cancelButtonTitle:@"Ok" 
                                          otherButtonTitles:nil];
    
    [alert show];
}




Спасибо всем кто дочитал до этого места.

Ссылки


1) Проект: github.com/eltiren/YandexOauth
2) Документация по Яндекс OAuth: api.yandex.ru/oauth/doc/dg/concepts/About.xml
Tags:
Hubs:
+13
Comments 10
Comments Comments 10

Articles