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.
![図7 「Information Property List」に[Add Row]](https://image.itmedia.co.jp/ait/articles/1106/08/r1307.gif)



