Google Calendar APIにサービスアカウントでアクセスする。
サービスアカウントの使い方を知りたくて試したメモ。
OAuth サービス アカウント - AdWords API — Google Developers
Adwordsの説明だけどこれと同じ方法でGoogle Appsのカレンダーにもアクセスできる。
注意点など
- ServiceAccountを使用してGoogle Appsに接続する場合はユーザーによる認可をドメイン管理のManage API client accessに登録することで代替できる。
- 認可を代替できると書いたが、ドメインに所属しているユーザーに対してブラウザを使用した認可フローをしなくてよいという意味。しかしユーザーの指定は必要。コードでいうとsetServiceAccountUser("who@example.com")しないとcredential.refreshTokenできない。
- 会議室リソースは実はドメインがresource.calendar.google.comなので、Google Appsの契約ドメインではないため、会議室アカウントになりすましたりもできない。
- 今回は会議室一覧をsetServiceAccountUserなしでできないかなとおもったのだけど、Google Calendar APIだけだとそれはできなかった。
ということで一度特権管理者的な人にOAuth2のフローで認可してもらう方がよい。もしくは一度アカウントを取得するためにアカウント(メールアドレス)を入力してもらって、Serviceアカウントではそのアカウントを使用するかということになる。
ちなみに夜間バッチ的なプログラムであれば大変よい。
package example; import java.io.File; import java.io.FileReader; import java.util.Arrays; import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.gson.GsonFactory; import com.google.api.services.calendar.Calendar; import com.google.api.services.calendar.CalendarScopes; public class ServiceAccountAccess { public static void main(String[] args) throws Exception{ JsonFactory jsonfactory = new GsonFactory(); HttpTransport transport = new NetHttpTransport(); GoogleClientSecrets secret = GoogleClientSecrets.load(jsonfactory, new FileReader("client_secret.json")); String service_account = (String)secret.getWeb().get("client_email"); String client_id = secret.getWeb().getClientId(); GoogleCredential credential = new GoogleCredential.Builder() .setTransport(transport) .setJsonFactory(jsonfactory) .setClientSecrets(secret) .setServiceAccountId(service_account) .setServiceAccountPrivateKeyFromP12File(new File("service_account.p12")) .setServiceAccountScopes(Arrays.asList(CalendarScopes.CALENDAR)) .setServiceAccountUser("who@example.com") // ドメインのユーザーを指定する必要あり .build(); if(needRefresh(credential) && !credential.refreshToken()){ return ; } Calendar service = new Calendar.Builder(transport, jsonfactory, credential) .setApplicationName(client_id) .build(); System.out.println(service.events().list("room_resource@resource.calendar.google.com").execute().toPrettyString()); } public static boolean needRefresh(GoogleCredential credential){ return credential.getExpiresInSeconds() == null || credential.getExpiresInSeconds() < 60; } }