こんにちは。最近、Android の Google アカウントに関する質問がいくつか寄せられています。そこで、Google が勧めるベスト プラクティスのいくつかを記事にまとめて紹介いたします。今回は、
Google Play 開発者サービスの統合によって簡単に実現できる Android ベースの認証に焦点を当てます。では、始めましょう。
固有の識別子
混乱がよく生じるのが、デベロッパーがアカウント名(E メール アドレス)を Google アカウントのプライマリー キーに使用しているケースです。たとえば、ユーザーのログインに
GoogleApiClient を使用しているとき、デベロッパーは、登録されている
GoogleApiClient.ConnectedCallbacks リスナーに対する
onConnected コールバックの中で、下に示すようなコードを使っている場合があります ...
Read More
こんにちは。最近、Android の Google アカウントに関する質問がいくつか寄せられています。そこで、Google が勧めるベスト プラクティスのいくつかを記事にまとめて紹介いたします。今回は、
Google Play 開発者サービスの統合によって簡単に実現できる Android ベースの認証に焦点を当てます。では、始めましょう。
固有の識別子
混乱がよく生じるのが、デベロッパーがアカウント名(E メール アドレス)を Google アカウントのプライマリー キーに使用しているケースです。たとえば、ユーザーのログインに
GoogleApiClient を使用しているとき、デベロッパーは、登録されている
GoogleApiClient.ConnectedCallbacks リスナーに対する
onConnected コールバックの中で、下に示すようなコードを使っている場合があります。
[エラーが生じやすい擬似コード]
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
// createLocalAccount() はアプリのローカル ストレージ ストラテジーに固有
createLocalAccount(accountName);
表示やキャッシュのために E メールアドレスを保存することに問題はありませんが、ユーザーは、Google アカウントで自身のプライマリー E メール アドレスを変更する可能性があります。そういったことは様々なタイプのアカウントで起きますが、最も頻繁に発生するのが
Google Apps For Work アカウントです。
では、デベロッパーはどうしたらよいのでしょうか。Google アカウントに関連付けられているアプリのデータをキーにするときは、アカウント名ではなく、Google アカウント ID を使用します。つまり、たいていのアプリでは、アカウント ID を保存して、onConnected コールバックが呼び出されるたびに、その値を比較するだけでよく、これによって、そのデータが現在ログインしているユーザーとローカルに合致しているかを確認します。API では、アカウント ID をアカウント名から取得できるメソッドを提供しています。参考用に、スニペット例を示します。
[Google Play 開発者サービス 6.1+]
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
String accountID = GoogleAuthUtil.getAccountId(accountName);
createLocalAccount(accountID);
[Google Play 開発者サービスの以前のバージョン(クライアントをアップグレードしてください)]
Person currentUser = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
String accountID = currentUser.getID();
createLocalAccount(accountID);
こうすることで、ローカルデータは Google アカウント ID と照合されることになります。アカウント ID は ユーザーが E メールアドレスを変更した後でも変わらない固有の識別子です。
よって、上述のケースでは、データが ID をキーとしていれば、ユーザーが E メールアドレスを変更したとしても心配する必要はないのです。ユーザーが再びログインするときも、同じ ID を取得しますので、皆さんの側で何らかのデータ処理をする必要はありません。
複数アカウント
アプリが複数のアカウントによる同時接続をサポートしている場合(たとえば、下に示す Gmail ユーザー インターフェースのようなケース)、GoogleApiClients 構築時には、
setAccountName を
GoogleApiClient.Builder に対して呼び出します。このとき、アプリ内にそのアカウント名と Google アカウント ID を保存する必要があります。しかし、保存したアカウント名は、ユーザーがプライマリー E メール アドレスを変更すると、違ってしまうことになります。これに対処する最も簡単な方法は、ユーザーに再ログインを促すことです。そしてログイン後に、onConnected がコールされたときにアカウント名を更新します。ログインのたびに、こういったコードを使ってアカウント ID を比較し、そのアカウント ID に対してローカルに保存されている E メールアドレスを更新します。
[Google Play 開発者サービス 6.1+]
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
String accountID = GoogleAuthUtil.getAccountId(accountName);
// isExistingLocalAccount(), createLocalAccount(),
// getLocalDataAccountName()、および updateLocalAccountName() は、
// すべて、アプリのローカル ストレージ ストラテジーに固有のもの
boolean existingLocalAccountData = isExistingLocalAccount(accountID);
if (!existingLocalAccountData) {
// 新たなログイン
createLocalAccount(accountID, accountName);
} else {
// この Google アカウントに関する既存のローカルデータ
String cachedAccountName = getLocalDataAccountName(accountID);
if (!cachedAccountName.equals(accountName)) {
updateLocalAccountName(accountID, accountName);
}
}
このシナリオからは、すべてのデータをアプリに保存するのにアカウント ID を使用することの重要性が分かります。
オンライン データ
上記のベスト プラクティスは、アプリのウェブサーバーに Google アカウントのデータを保存する際にも当てはまります。データをこの方法でサーバーに保存し、E メール アドレスをプライマリー キーとして扱っている場合、
ID [プライマリー キー] |
フィールド 1 |
フィールド 2 |
フィールド 3 |
user1@gmail.com |
値 1 |
値 2 |
値 3 |
プライマリー キーを Google アカウント ID とする下記のモデルに移行する必要があります。
ID [プライマリー キー] |
Email |
フィールド 1 |
フィールド 2 |
フィールド 3 |
108759069548186989918 |
user1@gmail.com |
値 1 |
値 2 |
値 3 |
ウェブ サーバーから Google API コールを行わない場合は、上述の複数アカウントのサンプルコードで参照している updateLocalAccountName メソッドを実装する場合、プライマリー E メールアドレス変更をウェブ サーバーに通知するのは、Android 向けアプリケーションに任せることができるかもしれません。ウェブ サーバーから Google API のコールを行う場合は、おそらくそれは
クロス クライアント認証を使って実装したものなので、ウェブ サーバー上の OAuth2 クライアント ライブラリまたは REST エンドポイントを介して変更を検出することもできます。
まとめ
アプリで Google アカウント認証を使用するとき、ユーザーのデータを識別するには、アカウント名ではなくアカウント IDを使うのがベストな方法です。この記事では、アプリを強化するために変更作業が必要となる 3 つのケースを紹介しました。Google for Work の利用が増加しているなか、ユーザーが E メール アドレスを変更しても、アカウント ID は同じまま維持するケースが増えてくると予想されます。よって、デベロッパーの皆さんには、できるだけ早急にコードの更新計画を立てることをお勧めいたします。
Posted by
Yuichi Araki