この記事で紹介すること
iOSアプリでFacebookアカウントを介してCognitoでAWSへアクセス!!
(AWS素人が調べた内容なので誤りがある可能性があります)
Facebook App の登録
Facebook認証をiOSアプリから利用するために、そのiOSアプリをFacebook Appとして登録する。
手順
1 https://developers.facebook.com/ にアクセス
2 My Apps からAdd a New Appを押して、AppIDを取得する.
3 Getting Startedの内容に従って、iOSアプリからFacebookにログインできるようにする。(手順に従えば、Facebookログインボタンまで簡単に追加できるはず!!)
※ もし手順どおりInfo.plistにURL schemesも登録したのに、それが見つからない!!って怒られた場合は、Info.plistをテキスト形式で表示してみると良いかも。 FacebookAppIDの最初に空白が入ってたりするのに気づけるかもしれない...
FacebookApp用のテストユーザーについて
FacebookAppのテスト用ユーザーを作成する場合は、My AppsページのRolesからTestUsersを作成できる。
他のFacebookアカウントで認証するには
一度Facebookへ認証した後ログアウトするだけでは、他のユーザーで
認証できない(認証済みとして、勝手にログインしてしまう)。その場合はFacebookアプリの方で一度ログアウトすると、他のユーザーでログインできるようになる。
AWS Cognito
Identity pool の作成
1 AWS Cognitoのページにアクセス.(東京リージョンはまだない)
2 Create new Identity poolを選ぶ
3 Identity pool nameを入力する。(アプリ名など)
4 Unauthenticated identitiesを有効にするか選ぶ。(アプリが未認証のゲストユーザーを利用する場合は有効にする。今回は無効。)
5 Authentication providersを選択する。今回はFacebookを選び、FacebookAppのApp IDを入力する。
6 認証用のIAMロールと未認証用のIAMロールの作成を許可する。
IAM ロール ポリシーの編集.(必要であれば)
3 AWS Cognito Identity poolで作成した, __XXX__Auth_Roleを編集する。
4 例えばS3へユーザー毎にファイル追加と取得のアクセス許可を出す例.
前提
S3へ保存するファイルパスは、以下の形式.
mybucket/cognito-identity/ファイル名
※ cognito-identityがユーザーのID.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::mybucket/${cognito-identity.amazonaws.com:sub}",
"arn:aws:s3:::mybucket/${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}
- ポリシー変数を利用するために、"Version": "2012-10-17"は必須。
- ${cognito-identity.amazonaws.com:sub}は、cognitoで認証したユーザーのIDを表すポリシー変数。
参考
AWS STS ウェブ ID フェデレーションについて
http://docs.aws.amazon.com/ja_jp/STS/latest/UsingSTS/web-identity-federation.html
CognitoとFacebookログインの連携例
手順: Facebook認証できたら、CognitoへFacebookのtokenを設定して、AWSへ認証する.
AppDelegate
@implementation AppDelegate
// Cognitoのサンプルコードでは、Cognitoの認証をおこなっているけど、
// FacebookSDKの処理のみにする。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return [[FBSDKApplicationDelegate sharedInstance] application:application
didFinishLaunchingWithOptions:launchOptions];
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
ViewController(Facebookのログインボタンを表示しているController)
便宜上ViewControllerでFacebookボタンを表示しているとする。
// ログイン/ログアウト結果を取得できるようにFBSDKLoginButtonDelegateを追加.
@interface ViewController : <FBSDKLoginButtonDelegate>
ログインボタン
参考
https://developers.facebook.com/docs/facebook-login/ios/v2.3
https://developers.facebook.com/docs/facebook-login/permissions
FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init];
loginButton.center = self.view.center;
loginButton.readPermissions = @[@"public_profile", @"email"];
// delete追加
loginButton.delegate = self;
[self.view addSubview:loginButton];
FBSDKLoginButtonDelegate実装
-(void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error {
if( !error ) {
if( !result.isCancelled ) {
[self authorizeAWS];
}
}
}
-(void)authorizeAWS {
NSDictionary* logins = @{@"graph.facebook.com": [FBSDKAccessToken currentAccessToken].tokenString};
// AWS Cognitoのサンプルコード.
AWSCognitoCredentialsProvider* credentialProvider =
[[AWSCognitoCredentialsProvider alloc] initWithRegionType:CognitoRegionType /* Cognitoのリージョン */
identityPoolId:CognitoIdentityPoolId /* CognitoのIdentityPoolId */];
// ここでFacebookのログイン情報を設定.
credentialProvider.logins = logins;
AWSServiceConfiguration* configuration =
[[AWSServiceConfiguration alloc] initWithRegion:DefaultServiceRegionType /* S3などサービスのあるリージョン */ credentialsProvider:credentialProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;
self.credentialProvider = credentialProvider;
Cognitoで認証したユーザーIDの取得.
AWSCognitoCredentialsProvider::credentialProvider.getIdentityId で取得できるが、 以下のコードを実行しないとnilが返ってくる。
※ 適切な挿入箇所は未調査なので、とりあえず、上のauthorizedAWSメソッドの直後に実行してます。
stackoverflow
http://stackoverflow.com/questions/25245236/aws-cognito-identity-null
// Cognitoのユーザー毎のIDを
[[credentialProvider getIdentityId] continueWithBlock:^id(BFTask *task){
if (task.error == nil)
{
NSString* cognitoId = credentialProvider.identityId;
NSLog(@"cognitoId: %@", cognitoId);
}
else
{
NSLog(@"Error : %@", task.error);
}
return nil;
}];
}
ViewController初期化時
- (void)viewDidLoad {
[super viewDidLoad];
// 表示時にすでに認証済みなら、自動的にAWSヘログイン
if( [FBSDKAccessToken currentAccessToken] ) {
[self authorizeAWS];
}
}
以上で、Facebookアカウントを介してAWSへアクセスができる。(間違いがある可能性は十分あります。気になる点があれば指摘ください.)
おまけ Facebookからログアウト
Facebookログインと同じ処理で、ログアウトボタンを表示できる。
FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init];
loginButton.center = self.view.center;
loginButton.readPermissions = @[@"public_profile", @"email"];
loginButton.delegate = self;
[self.view addSubview:loginButton];
-(void)loginButtonDidLogOut:(FBSDKLoginButton *)loginButton {
NSLog(@"logout facebook result.");
[self.tableView reloadData];
[loginButton removeFromSuperview];
[self logoutAws];
}
-(void)logout {
[self.credentialProvider clearCredentials];
self.credentialProvider = nil;
}
おまけ Facebook profile(ユーザー名など)の取得.
Facebook認証に成功した後、遅れてprofileが取得できるようなので、NSNotificationCenterでProfile変化を受信できるようにする。
- (void)viewDidLoad {
[super viewDidLoad];
[FBSDKProfile enableUpdatesOnAccessTokenChange:YES];
if( [FBSDKAccessToken currentAccessToken] ) {
[self authorizeAWS];
}
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(fbSDKProfileDidChangeNotification:) name:FBSDKProfileDidChangeNotification object:nil];
}
-(void)fbSDKProfileDidChangeNotification:(NSNotificationCenter*)center {
NSLog(@"something change...%@", [FBSDKProfile currentProfile]);
}
参考
Cognitoでユーザー認証:http://docs.aws.amazon.com/cognito/devguide/identity/?platform=ios
AWS STS ウェブ ID フェデレーションについて:
http://docs.aws.amazon.com/ja_jp/STS/latest/UsingSTS/web-identity-federation.html