[AWS][Android] Amazon Cognito のモバイルユーザー認証を使って、AndroidからAWSリソースを利用してみた。

2014.08.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Amazon Cognito

今回は、Cognitoを利用してAWSリソースが利用できるようなので、androidでその辺りを調査してみました。

[以下、公式より引用] Amazon Cognito を使用すると、AWS のセキュリティのベストプラクティスを簡単に実装できます。Amazon Cognito を使用すると、アプリケーションの各ユーザーには、Amazon S3 や Amazon DynamoDB といった他の AWS サービスにアクセスするために使用できる、権限の制限された一時的な AWS 認証情報 1 揃いが付与されます。つまり、アプリケーションでセキュリティ認証情報のハードコーディングを行わなくても、アプリケーションから必要なリソースにアクセスできることになり、ユーザーに優れた体験を提供できます。

とりあえず使ってみる

Amazon Congnitoを利用する(Poolの作成)

Cognitoを利用するにはCognito identity pool というのを作成します。 作成方法はこちらを参照してください。 [AWS][iOS] Amazon Cognito のモバイルユーザー認証 & データ同期 を iOS で使ってみた

利用料金は、無料利用枠内であれば、1か月につき 10GB の容量と100万回の同期オペレーションが利用できます。 詳細についは、公式ページをご確認ください。

SDKのインポート

まずは、こちらから AWS SDK for Androidをダウンロードします。

aws-android-sdk-2.0.5-core.jarをプロジェクトにインポートします。

スクリーンショット 2014-08-18 17.26.47

後は、ネットワーク接続が必要なのでパーミッションを追加しておきます。

<uses-permission android:name="android.permission.INTERNET"/>

Credentialsを取得してみる

ひとまず、サンプルコードを参考に以下のようにしてみました。 How to Authenticate Users

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

import com.amazonaws.android.auth.CognitoCredentialsProvider;
import com.amazonaws.auth.AWSSessionCredentials;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);


		(new Thread(new Runnable() {
			@Override
			public void run() {
				CognitoCredentialsProvider cognitoProvider = new CognitoCredentialsProvider(
					    MainActivity.this, // get the context for the current activity
					    "XXXXXXXXXXXX",    // AWS Account ID
					    "us-east-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX",       // Identity Pool ID
					    "arn:aws:iam::XXXXXXXXXX:role/YourAuthRoleName",    // AuthRoleName
					    "arn:aws:iam::XXXXXXXXXX:role/YourUnauthRoleName"   // UnauthRoleName
					);
				
				AWSSessionCredentials credentials = cognitoProvider.getCredentials();
				
				Log.d("credentials" , "accessKey:" + credentials.getAWSAccessKeyId());
				Log.d("credentials" , "secretKey:" + credentials.getAWSSecretKey());
			}
		})).start();

	}

}

CognitoCredentialsProviderのコンストラクタに、AWS Account ID, Identity Pool ID, Role ARNを設定します。 Identity Pool ID は Cognito の [Edit Identity Pool] 内に表示されています。 Role ARNは、IAM メニュー内の[Roles]をクリックし、Cognitoの登録時に作成されたRole名をクリックすると、一番上に表示されています。

CognitoProvider#getCredentials()では、非同期での処理が必要になりますので、簡単ですがとりあえずThreadで実装しました。

実行すると、CognitoProvider#getCredentials()で取得したCredentialsのAccess_KeyとSecret_Keyがログに表示されると思います。

スクリーンショット 2014-08-18 18.22.29

ログを見ると、SharedPreferencesにキャッシュされるようですね。ちなみに、ライブラリのソースコードをのぞいたら、1時間毎に更新されるようでした。

AWSリソースを利用する

Access_KeyとSecret_Keyが取得できたということは、これでAWSリソースにもアクセスできますね!

それでは試しに、先日書いたブログのソースを変更して、kinesisにアクセスしてみます。

private AmazonKinesisClient kinesisInit() {

	// String accessKey = "xxxxxxxxxx";
	// String secretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
	//
	// AWSCredentials credentials = new BasicAWSCredentials(accessKey,secretKey);

	CognitoCredentialsProvider cognitoProvider = new CognitoCredentialsProvider(
		    getActivity(), // get the context for the current activity
		    "XXXXXXXXXXXX",
		    "us-east-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX",
		    "arn:aws:iam::XXXXXXXXXX:role/YourAuthRoleName",
		    "arn:aws:iam::XXXXXXXXXX:role/YourUnauthRoleName"
		);

	String endpoint = "https://kinesis.ap-northeast-1.amazonaws.com";
	AmazonKinesisClient client = new AmazonKinesisClient(cognitoProvider);
	client.setEndpoint(endpoint);

	return client;

}

これで実行してみたら、どうでしょう? 動きましたか?

 

落ちますね。。。 おそらく、権限がないと怒られることでしょう。

Roleに権限を追加

デフォルトで作成した、CognitoのユーザロールはCognito以外のアクセス権限がないので、権限を追加します。

IAM のメニューから [Roles]を選択し、Cognito登録時に作成したRole名を選択します。(今回は Facebookなどの認証をしていないので、UnauthのRoleだけで大丈夫です。)

スクリーンショット 2014-08-18 18.42.08_2

Attach Role Policyから、 Amazon Kinesis Full Accessを追加します。 (実運用などで厳密にやる場合はPolicy GeneratorなどでAction毎に権限を付与した方がいいと思います。)

これで、再度実行するとちゃんと接続できました。

まとめ

世の中には、このようなAWSアカウントの乗っ取りもあるようなので、Access_KeyとSecret_Keyの取り扱いには十分注意したほうがいいですね。 上記のようなgithub以外でも、アプリのソースコードにハードコーディングしている場合は、アプリを解析された場合に同じことが起こるので、こちらも注意が必要です。(自分でサンプルコード書いておいてアレですが。。。) 特にAndroidでは、ソースコードを簡単に解析される可能性があるのでセキュリティ関連は、より注視していきたいですね。

以上です