これに約2日を費やした後、私は少しガタガタしています。OpenID ではなく OAuth2 を選択した今では、Authenticate と Authorize の違いについてはかなり精通しています。
Android アプリでユーザーを認証するいくつかの方法を提供する必要があります。そのうちの 1 つは Google アカウントで、後で Facebook と Twitter のアカウントも使用します。AccountManager クラスを使用して、(今のところ) ユーザーのメール アドレスを確認するための OAuth アクセス トークンを取得しようとしています。目標は、ユーザーがすでに Android デバイスに保存されている Google アカウントを持っている場合、パスワードを入力しなくても、アプリを一度認証でき、Android から再度ログインする必要がないことです。
Google 独自の AccountManager を使用することにしました。これは、ブラウザ ウィンドウを開くことさえせずに、Android フレームワークでネイティブに処理することが約束されていたからです。AccountManager をサポートする最初のレベルである Google API バージョン 7 (Android 2.1) のライブラリ/ビルド ターゲットを使用しています。
私はこの 2 つの異なる方法を試しました。1 つは Account オブジェクトを指定しない AccountManager.getAuthTokenByFeatures() を使用する方法で、もう 1 つはそのようなオブジェクトを指定する場合に getAuthToken() を使用する方法です。
いずれの場合も、(予想どおり) 呼び出しが完了し、アプリを承認するかどうかを尋ねる承認ダイアログがアプリケーションに表示されます。ここまでは順調ですね。拒否すると、プログラムは予想どおりの例外をスローします。同意すると、「Google サインイン」ダイアログが表示され、アカウントのパスワードを求められます。アカウントをデバイスに追加したときに、すでにパスワードを入力していることに注意してください。ダイアログにパスワードを入力すると、「承認中」の待機画面が表示された後、同じダイアログが再び表示されます。奇妙なことに、正しいパスワードを入力すると、「Authorizing」待機画面に少し時間がかかるようです。そのため、トークンを正常に取得するコード パスに到達できないようです。
AUTH_TOKEN_TYPE が何であるか、または userinfo.email の URL が文書化されていないという事実について Google が明確ではないことについて発散するのは魅力的ですが、ここで何が間違っているのかを学び、これを乗り越えたいと思います。
これが私のコードです。私はこれを監視します。もちろん、質問があれば喜んでお答えします。現在、ネットワーク トラフィックをキャプチャして、何が問題なのかについてさらに詳しい情報が得られるかどうかを確認するつもりです。
認証画面 (OK) とパスワード ダイアログ (OK 未満) を示す画像は次のとおりです 。
public void loginToGoogle() {
System.out.println("Starting");
AccountManagerFuture<Bundle> bundleFuture =
AccountManager.get(_activity).getAuthTokenByFeatures(
"com.google",
"https://www.googleapis.com/auth/userinfo.email",
null,
_activity,
null,
null,
new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
Bundle bundle;
try {
bundle = future.getResult();
for (String s : bundle.keySet()) {
System.out.println("Found key: "+ s);
}
System.out.println(bundle.getString(AccountManager.KEY_ACCOUNT_NAME));
System.out.println(bundle.getString(AccountManager.KEY_AUTHTOKEN));
//Use Token
} catch (OperationCanceledException e) {
Log.e("e", e.getMessage(), e);
System.out.println("User appears to have denied auth request");
} catch (AuthenticatorException e) {
Log.e("e", e.getMessage(), e);
} catch (IOException e) {
Log.e("e", e.getMessage(), e);
}
}
},
null);
System.out.println("Done with AccountManager call");
}