Google Appsでユーザーの外部アプリケーションの認可状況を監査する
Google AppsのAdmin Reports APIでドメインのユーザーの外部アプリの認可状況がとれるようになったのでメモ
Reports API: Authorization Tokens Activity Report - Admin SDK — Google Developers
ソースコードは文末、今回はサービスアカウントで行っているが、認可時に特権管理者であればもちろんOK。
- 通常のユーザーでは https://www.googleapis.com/auth/admin.reports.audit.readonly の権限をもってないので自身の認可記録をみることができない
- 監査したい対象のユーザーはプライマリメールアドレスで指定する。
- ドメインのユーザー全員を見たいときはallを指定
これになぜ興味をもったかというとGoogleのOAuth2のドキュメントに
Using OAuth 2.0 to Access Google APIs - Google Accounts Authentication and Authorization — Google Developersの項が増えて、accesstokenが25個までとなったため。
There is currently a 25-token limit per Google user account. If a user account has 25 valid tokens, the next authentication request succeeds, but quietly invalidates the oldest outstanding token without any user-visible warning.
(意訳)
https://developers.google.com/accounts/docs/OAuth2#expiration
Googleのアカウント毎にアクセストークンは25個までです。もしユーザーが有効なアクセストークンを25個もっていた場合、次の認可リクエストに成功するとユーザーへの警告などもなく、有効期限が古いものから順に無効化されていきます。
アカウント毎と書いてあるけど、これはプロジェクトかクライアントIDだろうな。本当にアカウントなのかな? とか、oldest outstanding tokenってrefreshTokenがあるから、有効期限が古いものからだろうなとかおもうことはあるが、ユーザーへの警告などもなく無効化されていきますが凶暴だなとおもうわけです。
担当している製品では1アカウントで複数の端末にアプリをインストールするのだけれど、この制限で最大25台毎(推奨は15 - 20)に1アカウント必要になったため、accesstokenの一覧がほしいんだけど、これまでそれに類するものが取得できなかったので、これでできそうということでやってみた。
package com.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.admin.reports.Reports; import com.google.api.services.admin.reports.ReportsScopes; public class ListDomainAccessTokenAudit { public static void main(String[] args) throws Exception{ JsonFactory jsonfactory = new GsonFactory(); HttpTransport transport = new NetHttpTransport(); // APIコンソールで取得出来る。中身はサービスアカウントのIDとclient_id,client_secret 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(); // 事前準備としてGoogle Appsの管理コンソールでOAuthアクセスできるようにしておく GoogleCredential credential = new GoogleCredential.Builder() .setTransport(transport) .setJsonFactory(jsonfactory) .setClientSecrets(secret) .setServiceAccountId(service_account) // ドメイン管理者としてアクセス .setServiceAccountUser("admin@example.com") // サービスアカウントでアクセスするので、秘密鍵が必要。 // APIコンソールから取得出来る証明書から設定 .setServiceAccountPrivateKeyFromP12File(new File("service_account.p12")) // 監査用のスコープを設定する .setServiceAccountScopes(Arrays.asList(ReportsScopes.ADMIN_REPORTS_AUDIT_READONLY)) .build(); // accessTokenを取得 if(!credential.refreshToken()){ return ; } Reports reports = new Reports.Builder(transport, jsonfactory, credential) .setApplicationName(client_id) .build(); // 全員分を取りたいときはuser@example.comの代わりにallを指定する System.out.println(reports.activities().list("user@example.com", "token").execute().toPrettyString()); } }