SafariでOAuth認証ページを開くためのURLスキーム
URLスキームというのは、URLを構成する要素です。URLは、一般的に以下の構造をしています。
【スキーム】:【何らかの文字列】
例えば、以下がスキームです。
- 「http:////www.example.com/」の「http」の部分
- 「mailto:hoge@example.com」の「mailto」の部分
Safari上で「mailto:hoge@example.com」にアクセスしようとすると、メーラが起動し、「hoge@example.com」宛のメールを新規作成する画面になります。
このように、「mailto」スキームに対してメーラを起動するのと同様に、「独自のスキームに対して特定のアプリケーションを起動させ、起動直後に、そのURLに応じてアプリケーションが何らかの処理を行う」といったことができます。
なぜURLスキーム使うか
Facebook SDK for iOSを利用し、Safariを使ったログインを行うためには、スキーム「fb【アプリケーションID】」に対してアプリケーションが起動する仕組みが必要です。
なぜ、これが必要になるかというと、アプリケーションからOAuthページをSafariで開き、ユーザーがSafariで処理を済ませた時点でアクセストークンなどをアプリケーションが受け取る必要があるからです。こういった使い方を想定し、Facebookのモバイルアプリケーション用認証ページは、認証が済んだ後に「fb【アプリケーションID】:……」というURLを開かせるようになっています。
流れとしては、以下のようになります。
- Safariで認証ページを開く
- ユーザーが認証を行う
- 「fb【アプリケーションID】:……」というURLを開く
- アプリが起動、HelloFbAppDelegateの「handleOpenURL」メソッドが呼ばれ、リクエストされたURLに含まれたアクセストークンを取得できる
URLスキームの定義方法
URLスキームは[Resources]→「【アプリケーション名】-Info.plist」ファイル内で定義します。
まずファイルを開き、「Information Property List」の行で右クリック(もしくは[Ctrl]キーを押しながらクリック)し、メニューから[Add Row]を選択します。
Keyに「URL types」と入力します(入力中に補完候補が出ます)。
「URL types」の行を開くと「Item 0」という行があります。この行で右クリック(または[Ctrl]キーを押しながらクリック)し、メニューから[Add Row]を選択。追加された行のKeyの値を「URL Schemes」にします。
「URL Schemes」の行を開くと、「Item 0」という行があります。この行の「Value」を「fb【アプリケーションID】」にします。
これで、「【アプリケーションID】:【なんらかの文字列】」というURLに対して、このアプリケーションが開くようになりました。
OAuth APIでログインしてプロフィールを取得
OAuth APIを使ってログインし、ログインができたらGraph APIを使ってユーザーのプロフィールを取得するという簡単なアプリケーションを作ってみます。
アプリケーションの構成は、以下の3つのクラスのヘッダファイルと実装ファイル、計6ファイルです。
- アプリケーションデリゲートである「HelloFbAppDelegate」
- メイン画面の「HelloFbViewController」
- ログインボタン「LoginButton」(「UIButton」のサブクラス)
まずは、ソースコード全体をざっとご覧ください。
#import <Foundation/Foundation.h> @interface LoginButton : UIButton { BOOL loggedIn; } @property (readonly) BOOL loggedIn; -(void) setLoginStatus: (BOOL) loginStatus; @end
#import "LoginButton.h" @implementation LoginButton @synthesize loggedIn; -(void) setLoginStatus: (BOOL) loginStatus { loggedIn = loginStatus; [self setImage:[UIImage imageNamed:(loggedIn)?@"LogoutNormal.png":@"LoginNormal.png"] forState:UIControlStateNormal]; } @end
#import <UIKit/UIKit.h> #import "Facebook.h" #import "FBLoginDialog.h" #import "LoginButton.h" @interface HelloFbViewController : UIViewController <FBSessionDelegate, FBRequestDelegate> { IBOutlet LoginButton* loginButton; IBOutlet UILabel* profileLabel; Facebook *facebook; } @property(readonly) Facebook *facebook; -(IBAction) login: (id) sender; -(IBAction) getMyProfile: (id) sender; @end
#import "HelloFbViewController.h" @implementation HelloFbViewController @synthesize facebook; static NSString* APPLICATION_ID = @"XXXXXXXX"; - (void)viewDidLoad { [super viewDidLoad]; facebook = [[Facebook alloc] initWithAppId: APPLICATION_ID]; [facebook setSessionDelegate:self]; } -(IBAction) login: (id) sender { if (!loginButton.loggedIn) { NSArray *permissions = [[NSArray arrayWithObjects: @"read_stream",@"publish_stream",nil] retain]; facebook = [[Facebook alloc] initWithAppId: APPLICATION_ID]; [facebook authorize:permissions delegate:self]; } else { [facebook logout:self]; } } - (void)fbDidLogin { NSLog(@"HelloFbViewController.fbDidLogin"); [loginButton setLoginStatus:YES]; } - (void)fbDidNotLogin:(BOOL)cancelled { [loginButton setLoginStatus:NO]; } - (void)fbDidLogout { NSLog(@"HelloFbViewController.fbDidLogout"); [loginButton setLoginStatus:NO]; } -(IBAction) getMyProfile: (id) sender{ [facebook requestWithGraphPath:@"me" andDelegate:self]; } - (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response { NSLog(@"HelloFbViewController.didReceiveResponse"); }; - (void)request:(FBRequest *)request didLoad:(id)result { NSLog(@"HelloFbViewController.didLoad"); NSDictionary *myProfile = (NSDictionary *) result; [profileLabel setText: [myProfile objectForKey:@"name"]]; } - (void)request:(FBRequest *)request didFailWithError:(NSError *)error { NSLog(@"HelloFbViewController.didFailWithError"); }; - (void)dealloc { [loginButton release]; [profileLabel release]; [super dealloc]; } @end
#import <UIKit/UIKit.h> @class HelloFbViewController; @interface HelloFbAppDelegate : NSObject { UIWindow *window; HelloFbViewController *viewController; } @property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, retain) IBOutlet HelloFbViewController *viewController; @end
#import "HelloFbAppDelegate.h" #import "HelloFbViewController.h" @implementation HelloFbAppDelegate @synthesize window; @synthesize viewController; #pragma mark - #pragma mark Application lifecycle - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *) launchOptions { NSLog(@"HelloFbAppDelegate.didFinishLaunchingWithOptions"); [self.window addSubview:viewController.view]; [self.window makeKeyAndVisible]; return YES; } - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { NSLog(@"HelloFbAppDelegate.handleOpenURL url=%@", url); return [[viewController facebook] handleOpenURL:url]; } - (void)applicationWillResignActive:(UIApplication *)application { } - (void)applicationDidEnterBackground:(UIApplication *)application { } - (void)applicationWillEnterForeground:(UIApplication *)application { } - (void)applicationDidBecomeActive:(UIApplication *)application { } - (void)applicationWillTerminate:(UIApplication *)application { } #pragma mark - #pragma mark Memory management - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { } - (void)dealloc { [viewController release]; [window release]; [super dealloc]; } @end
「HelloFbViewController.m」の以下の部分は、実際のアプリケーションIDに書き換えてください。
static NSString* APPLICATION_ID = @"XXXXXXXX";
「HelloFbViewController.xib」を開き、「IBOutlet」「IBAction」の接続を行います。
これをビルドすれば、Safariを使ったログインとログアウト、Graph APIを使ったユーザーの名前が表示できます。次ページでは、このサンプルの要点を解説します。
Copyright © ITmedia, Inc. All Rights Reserved.