Google OAuth で認証できるところまで動かしてみた(後編)
はじめに
前編では、Android Studio にプロジェクトを作成して、 backend モジュールを動かすところまでを書きました。
Google OAuth で認証できるところまで動かしてみた(前編) - NOSIX
後編では、Google の OAuth を利用して認証するところまで書きます。
Google Developer Console でプロジェクトを作成
前編では GAE をローカル環境で動かすところまでになっていますので、サーバー上で動かすために Google Developer Console でプロジェクトを作成します。
プロジェクトの認証情報を設定
OAuth を利用するために Client ID を取得する必要があります。
Google Developer Console > API Manager > 認証情報。
OAuth 2.0 Client ID を選択します。
ユーザーに表示される同意画面の設定を行います。サービス名はユーザーに表示されるので、ユーザーにとってわかりやすい名前を。
Client ID を発行
ウェブアプリケーション用の Client ID を発行します。名前の項目は何に使用されるか不明ですが、たぶん Google Developer Console 上でクライアントを区別するために使う程度かと思います。アプリ作成者がわかる名前をつければよいのかと思います。「承認済みの…」項目は、Google Endpoints を使用する今回の手順では不要です。
ソースコードを編集
準備が整ったので、ソースコードを変更します。サーバー側 MyEndpoint.kt の API 定義に scopes, clientIds を追加し、メソッドに未認証時の処理を追加します。
... import com.google.appengine.api.oauth.OAuthRequestException import com.google.appengine.api.users.User ... @Api(name = "myApi", version = "v1", scopes = arrayOf("https://www.googleapis.com/auth/userinfo.email"), clientIds = arrayOf("発行された Client ID"), namespace = ApiNamespace( ownerDomain = "backend.sayhello.anyspirit.org", ownerName = "backend.sayhello.anyspirit.org", packagePath = "" ) ) class MyEndpoint { /** A simple endpoint method that takes a name and says Hi back */ @ApiMethod(name = "sayHi") fun sayHi(@Named("name") name: String, auth: User?): MyBean { auth ?: throw OAuthRequestException("You need auth.") val response = MyBean() response.data = "Hi, " + name return response } }
未認証の場合には、OAuthRequestException を投げるようにするみたいです。
Using Auth with Endpoints - Java — Google Cloud Platform
クライアント側 index.html を編集します。
... <div class="row"> <a class="btn btn-primary" href="#" onclick="auth();">Sign in!</a> <a class="btn btn-primary" href="#" onclick="signout();">Sign out!</a> </div> ... <script type="text/javascript"> // A function that attaches a "Say Hello" button click handler function enableClick() { document.getElementById('helloButton').onclick = function() { var name = document.getElementById('nameInput').value; gapi.client.myApi.sayHi({'name': name}).execute( function(response) { var outputAlertDiv = document.getElementById('outputAlert'); outputAlertDiv.style.visibility = 'visible'; if (!response.error) { outputAlertDiv.className = 'alert alert-success'; outputAlertDiv.innerHTML = '<h2>' + response.result.data + '</h2>'; } else if (response.error) { outputAlertDiv.className = 'alert alert-danger'; outputAlertDiv.innerHTML = '<b>Error Code: </b>' + response.error.code + ' [' + response.error.message + ']'; } } ); return false; } } SCOPES = ['https://www.googleapis.com/auth/userinfo.email']; CLIENT_ID = '発行された Client ID'; function init() { var apisToLoad; var loadCallback = function() { if (--apisToLoad == 0) { //signin(true, userAuthed); // 読み込み完了時に自動的に認証 } }; apisToLoad = 2; // must match number of calls to gapi.client.load() var apiRoot = 'https://' + window.location.host + '/_ah/api'; if (window.location.hostname == 'localhost' || window.location.hostname == '127.0.0.1' || ((window.location.port != "") && (window.location.port > 1023))) { // We're probably running against the DevAppServer apiRoot = 'http://' + window.location.host + '/_ah/api'; } gapi.client.load('myApi', 'v1', loadCallback, apiRoot); gapi.client.load('oauth2', 'v2', loadCallback); } function signin(mode, authorizeCallback) { gapi.auth.authorize({ client_id: CLIENT_ID, scope: SCOPES, immediate: mode}, authorizeCallback); } function userAuthed() { var request = gapi.client.oauth2.userinfo.get().execute(function(resp) { if (!resp.code) { enableClick(); } }); } function auth() { signin(false, userAuthed); } function signout() { gapi.auth.setToken(null); } </script>
enableClick function は元々のままです。init function は参考サイトの内容を持ってきています。
Using Endpoints in a JavaScript Client - Java — Google Cloud Platform
動作確認
完成したので動かしてみます。未認証状態では、Say Hello ボタンを押しても何もおこりません。userAuthed function にて認証完了時に enableClick function を実行するようになっています。
sign in ボタンを押すとリクエスト許可を求める画面がでるので、許可します。前に設定したサービス名が表示されています。
認証済みの状態で Say Hello ボタンを押してみると結果が返ってきました。
sign out ボタンを押して再び未認証の状態に戻します。この状態で Say Hello を押すとエラーが発生します。