今日の役に立たない一言 - Today’s Trifle! -

古い記事ではさまざまなテーマを書いていますが、2007年以降はプログラミング関連の話がほとんどです。

JavaScript ClientからApp EngineのCloud EndpointsでOauth2認証する方法

試行錯誤してできるようになったので、簡単にまとめる。
基本的にはここに書いてあるとおり。

To use a Google Cloud Endpoint, you'll need to use the Google JavaScript client library. The code you need to add to use Endpoints is minimal, consisting of:
Google App Engine — Google Developers

var ROOT = 'https://<your-app-id>.appspot.com/_ah/api';
var CLIENT_ID = 'xxxxxxxxxxxxxxx.apps.googleusercontent.com';
var SCOPES = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile';

function init() {
	var apisToLoad;
	var callback = function() {
		 if (--apisToLoad == 0) {
		      signin(true, userAuthed);
		 }
	}
	apisToLoad = 2; // must match number of calls to gapi.client.load()
	gapi.client.load('<your-app-id>', 'v1', callback, ROOT);
	gapi.client.load('oauth2', 'v2', callback);
}

function signin(mode, callback) {
	gapi.auth.authorize({client_id: CLIENT_ID,
    		scope: SCOPES, immediate: mode},
		callback);
}

function userAuthed() {
	var request = gapi.client.oauth2.userinfo.get().execute(function(resp) {
   		if (!resp.code) {
			// 認証後の処理
		}
	});
}

最初のはまりポイントは、401エラー。上記のコードだけだと認証のウィンドウが開かない。というのは、init()の中でsignin(true, hoge)を呼び出してる。そうすると、この先で呼び出してる gapi.auth.authorize() の mode に true が渡される。
最初に書いた、「Google App Engine — Google Developers」の中程にパラメータの説明がある。

mode is either false or true, depending on whether or not you’d like to present the explicit authorization window to the user. If the user has never authorized your application before, calling authorize with mode: true (no authorization window) will fail. The correct situation to use each modes is described below.

ユーザーが一度も認証してなかったら、trueだと(認証ウィンドウを開かないから)失敗するよって書いてある。
なので、次のコードを追加してね、って書いてある。

<a href="#" onclick="auth();" id="signinButton">Sign in!</a>

function auth() {
  signin(false, userAuthed);
};

で、追加したリンクをクリックするとウィンドウが開くようにはなるけど、表示内容は認証の内容ではなくてエラー。次のハードルが「エラー origin_mismatch」だった。

ぐぐったら、StackOverflow に、http と https の違いでしょって書いてあったから、ボタンを設置してあるページのURLスキームを http から https に変えてやるだけであっさりと認証できるようになった。

つまり、ローカルで OAuth2 認証のテストしようとすると、ローカルのJettyに https でアクセスできるようにする必要があるので要注意。