質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1175閲覧

GoogleCalendarAPIをOAuth2.0無しで表示させられるようにしたい。

退会済みユーザー

退会済みユーザー

総合スコア0

Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

2クリップ

投稿2019/01/07 07:27

編集2019/01/07 07:29

GoogleCalendarAPIのQuickstartsを参考にしたのですが、このサンプルのままだと認証ボタンを押して、Googleのログインを行わないとカレンダーが表示されません。
また、appendしたhtmlがそのまま文字で表示されてしまいます。

  1. Googleのログインなしに、ページロード時に表示させる方法
  2. appendしたhtmlの訂正方法

の2点について教えてください。

html

1<!-- Quickstarts参照 --> 2<!DOCTYPE html> 3<html> 4 <head> 5 <title>Google Calendar API Quickstart</title> 6 <meta charset="utf-8" /> 7 </head> 8 <body> 9 <p>Google Calendar API Quickstart</p> 10 11 <!--Add buttons to initiate auth sequence and sign out--> 12 <button id="authorize_button" style="display: none;">Authorize</button> 13 <button id="signout_button" style="display: none;">Sign Out</button> 14 15 <pre id="content" style="white-space: pre-wrap;"></pre> 16 17 <script type="text/javascript"> 18 // Client ID and API key from the Developer Console 19 var CLIENT_ID = 'クライアントID'; 20 var API_KEY ='APIKey'; 21 // Array of API discovery doc URLs for APIs used by the quickstart 22 var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"]; 23 // Authorization scopes required by the API; multiple scopes can be 24 // included, separated by spaces. 25 var SCOPES = "https://www.googleapis.com/auth/calendar.readonly"; 26 var authorizeButton = document.getElementById('authorize_button'); 27 var signoutButton = document.getElementById('signout_button'); 28 /** 29 * On load, called to load the auth2 library and API client library. 30 */ 31 function handleClientLoad() { 32 gapi.load('client:auth2', initClient); 33 } 34 /** 35 * Initializes the API client library and sets up sign-in state 36 * listeners. 37 */ 38 function initClient() { 39 gapi.client.init({ 40 apiKey: API_KEY, 41 clientId: CLIENT_ID, 42 discoveryDocs: DISCOVERY_DOCS, 43 scope: SCOPES 44 }).then(function () { 45 // Listen for sign-in state changes. 46 gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus); 47 // Handle the initial sign-in state. 48 updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get()); 49 authorizeButton.onclick = handleAuthClick; 50 signoutButton.onclick = handleSignoutClick; 51 }, function(error) { 52 appendPre(JSON.stringify(error, null, 2)); 53 }); 54 } 55 /** 56 * Called when the signed in status changes, to update the UI 57 * appropriately. After a sign-in, the API is called. 58 */ 59 function updateSigninStatus(isSignedIn) { 60 if (isSignedIn) { 61 authorizeButton.style.display = 'none'; 62 signoutButton.style.display = 'block'; 63 listUpcomingEvents(); 64 } else { 65 authorizeButton.style.display = 'block'; 66 signoutButton.style.display = 'none'; 67 } 68 } 69 /** 70 * Sign in the user upon button click. 71 */ 72 function handleAuthClick(event) { 73 gapi.auth2.getAuthInstance().signIn(); 74 } 75 /** 76 * Sign out the user upon button click. 77 */ 78 function handleSignoutClick(event) { 79 gapi.auth2.getAuthInstance().signOut(); 80 } 81 /** 82 * Append a pre element to the body containing the given message 83 * as its text node. Used to display the results of the API call. 84 * 85 * @param {string} message Text to be placed in pre element. 86 */ 87 function appendPre(message) { 88 var pre = document.getElementById('content'); 89 var textContent = document.createTextNode(message + '\n'); 90 pre.appendChild(textContent); 91 } 92 /** 93 * Print the summary and start datetime/date of the next ten events in 94 * the authorized user's calendar. If no events are found an 95 * appropriate message is printed. 96 */ 97 function listUpcomingEvents() { 98 gapi.client.calendar.events.list({ 99 'calendarId': 'カレンダーID', 100 //'timeMin': (new Date()).toISOString(), 101 'showDeleted': false, 102 'singleEvents': true, 103 'maxResults': 10, 104 'orderBy': 'startTime' 105 }).then(function(response) { 106 var events = response.result.items; 107 appendPre('Upcoming events:'); 108 if (events.length > 0) { 109 for (i = 0; i < events.length; i++) { 110 var event = events[i]; 111 var when = event.start.dateTime; 112 if (!when) { 113 when = event.start.date; 114 } 115 appendPre('<article><h1>'+event.summary+'</h1><p>' + when + '</p></article>') 116 } 117 } else { 118 appendPre('No upcoming events found.'); 119 } 120 }); 121 } 122 </script> 123 124 <script async defer src="https://apis.google.com/js/api.js" 125 onload="this.onload=function(){};handleClientLoad()" 126 onreadystatechange="if (this.readyState === 'complete') this.onload()"> 127 </script> 128 </body> 129</html>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/01/07 09:26

少し調べてみました。 サービスアカウントを作成すればできるみたいですが、クライアントサイドのみ(javascriptのみ)で実装しようとするとサイト訪問者にサービスアカウントの秘密鍵が見られてしまいます。 参考:https://christina04.hatenablog.com/entry/2015/06/04/224159
guest

回答1

0

ベストアンサー

興味本位で作ってみました。

このやり方はサービスアカウントの情報(秘密鍵とか)丸見えです。
サービスアカウントの権限を閲覧のみにすればバレてもいいという考え方はありかもしれません。
(google api consoleからスコープの設定は細かくできます。)

作り方としてはこのサイトのコードJWTを使ってGoogleAPIのアクセストークン取得する
コピペして、api keyとかの情報を差し替えます。
request.postの実行のレスポンスでアクセストークンが返ってくるので
window.accessTokenという変数にいれます。
このコードはnpmのモジュールを使って動作しているのでbrowserifyでbundle.jsに変換します。
index.htmlでbundle.jsを読み込みます。
受け取ったアクセストークンをgapiにセットすればログインボタンのクリックなしでカレンダーの情報がとれるようになります。

一応動作確認出来たので紹介します。
(gasで実装するのが一番楽だと思います。)

html

1ファイル名:index.html 2<!DOCTYPE html> 3<html> 4 <head> 5 <title>Google Calendar API Quickstart</title> 6 <meta charset="utf-8" /> 7 </head> 8 <body> 9 <p>Google Calendar API Quickstart</p> 10 11 <!--Add buttons to initiate auth sequence and sign out--> 12 <button id="authorize_button" style="display: none;">Authorize</button> 13 <button id="signout_button" style="display: none;">Sign Out</button> 14 15 <pre id="content" style="white-space: pre-wrap;"></pre> 16 <script src="bundle.js"></script> 17 18 <script type="text/javascript"> 19 20 // Client ID and API key from the Developer Console 21 var CLIENT_ID = '<CLIENT ID>'; 22 var API_KEY = '<API KEY>'; 23 24 // Array of API discovery doc URLs for APIs used by the quickstart 25 var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"]; 26 27 // Authorization scopes required by the API; multiple scopes can be 28 // included, separated by spaces. 29 var SCOPES = "https://www.googleapis.com/auth/calendar.readonly"; 30 31 var authorizeButton = document.getElementById('authorize_button'); 32 var signoutButton = document.getElementById('signout_button'); 33 34 /** 35 * On load, called to load the auth2 library and API client library. 36 */ 37 function handleClientLoad() { 38 gapi.load('client:auth2', initClient); 39 } 40 41 /** 42 * Initializes the API client library and sets up sign-in state 43 * listeners. 44 */ 45 function initClient() { 46 gapi.client.init({ 47 apiKey: API_KEY, 48 clientId: CLIENT_ID, 49 discoveryDocs: DISCOVERY_DOCS, 50 scope: SCOPES 51 }).then(function () { 52 // Listen for sign-in state changes. 53 //gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus); 54 gapi.client.setToken(window.accessToken); 55 listUpcomingEvents(); 56 57 // Handle the initial sign-in state. 58 //updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get()); 59 //authorizeButton.onclick = handleAuthClick; 60 //signoutButton.onclick = handleSignoutClick; 61 }, function(error) { 62 appendPre(JSON.stringify(error, null, 2)); 63 }); 64 } 65 66 /** 67 * Called when the signed in status changes, to update the UI 68 * appropriately. After a sign-in, the API is called. 69 */ 70 function updateSigninStatus(isSignedIn) { 71 if (isSignedIn) { 72 authorizeButton.style.display = 'none'; 73 signoutButton.style.display = 'block'; 74 listUpcomingEvents(); 75 } else { 76 authorizeButton.style.display = 'block'; 77 signoutButton.style.display = 'none'; 78 } 79 } 80 81 /** 82 * Sign in the user upon button click. 83 */ 84 function handleAuthClick(event) { 85 gapi.auth2.getAuthInstance().signIn(); 86 } 87 88 /** 89 * Sign out the user upon button click. 90 */ 91 function handleSignoutClick(event) { 92 gapi.auth2.getAuthInstance().signOut(); 93 } 94 95 /** 96 * Append a pre element to the body containing the given message 97 * as its text node. Used to display the results of the API call. 98 * 99 * @param {string} message Text to be placed in pre element. 100 */ 101 function appendPre(message) { 102 var pre = document.getElementById('content'); 103 var textContent = document.createTextNode(message + '\n'); 104 pre.appendChild(textContent); 105 } 106 107 /** 108 * Print the summary and start datetime/date of the next ten events in 109 * the authorized user's calendar. If no events are found an 110 * appropriate message is printed. 111 */ 112 function listUpcomingEvents() { 113 gapi.client.calendar.events.list({ 114 'calendarId': '<カレンダーID>', 115 'showDeleted': false, 116 'singleEvents': true, 117 'maxResults': 10, 118 'orderBy': 'startTime' 119 }).then(function(response) { 120 var events = response.result.items; 121 appendPre('Upcoming events:'); 122 123 if (events.length > 0) { 124 for (i = 0; i < events.length; i++) { 125 var event = events[i]; 126 var when = event.start.dateTime; 127 if (!when) { 128 when = event.start.date; 129 } 130 appendPre(event.summary + ' (' + when + ')') 131 } 132 } else { 133 appendPre('No upcoming events found.'); 134 } 135 }); 136 } 137 138 </script> 139 140 <script async defer src="https://apis.google.com/js/api.js" 141 onload="this.onload=function(){};handleClientLoad()" 142 onreadystatechange="if (this.readyState === 'complete') this.onload()"> 143 </script> 144 </body> 145</html>

Node.js

1ファイル名:token.js 2var request = require('superagent'); 3var crypto = require('crypto'); 4var fs = require('fs'); 5var privateKey = require('./key.json'); // private key generated on Developer Console. 6var driveScope = 'https://www.googleapis.com/auth/calendar'; 7var tokenEndpoint = 'https://www.googleapis.com/oauth2/v3/token'; 8var grantType = 'urn:ietf:params:oauth:grant-type:jwt-bearer'; 9 10var now = Math.floor( new Date().getTime() / 1000 ); 11 12var header = { 13 alg: 'RS256', 14 typ: 'JWT' 15}; 16 17var claims = { 18 iss: '<サービスアカウントのメールアドレス>', 19 scope: driveScope, 20 aud: tokenEndpoint, 21 exp: now + 3600, // maximum expiry date is 1 hour after the issued time. 22 iat: now 23}; 24 25var body = { 26 assertion: createJWT(header, claims), 27 grant_type: grantType 28} 29 30// send request to get access token 31window.accessToken; 32request.post(tokenEndpoint) 33 .set('Content-Type', 'application/x-www-form-urlencoded') // you must set this header. 34 .send(body) 35 .end(function(err, res){ 36 accessToken= res.body.access_token; 37 }); 38 39 40function createJWT(header, claims) { 41 var encodedHeader = new Buffer(JSON.stringify(header)).toString('base64'); 42 var encodedClaims = new Buffer(JSON.stringify(claims)).toString('base64'); 43 var sign = crypto.createSign('RSA-SHA256'); 44 var data = new Buffer(encodedHeader + '.' + encodedClaims); 45 46 sign.update(data); 47 signature = sign.sign(new Buffer(privateKey.private_key), 'base64'); 48 49 // JWT format is '{base64 encoded header}.{base64 encoded claims}.{signature}' 50 return [encodedHeader, encodedClaims, signature].join('.'); 51} 52

json

1ファイル名:key.json 2サービスアカウント作成でダウンロードできる秘密鍵情報

ノードモジュール:crypto, superagent
補足:token.jsは次のコマンドで変換「browserify token.js -o bundle.js」

投稿2019/01/07 13:11

編集2019/01/07 14:04
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/01/07 13:45

実装できました! サンプルコードまで考えていただきありがとうございます。
touho

2019/09/08 23:17

同じ内容で困ってました。神。 ありがたく使わせていただきます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問