Java 用 Google API クライアント ライブラリで OAuth 2.0 を使用する

概要

目的: このドキュメントでは、 GoogleCredential Google サービスで OAuth 2.0 認証を行うためのユーティリティ クラスです。対象 一般的な OAuth 2.0 関数の詳細については、 OAuth 2.0 と Java 用 Google OAuth クライアント ライブラリ

概要: Google サービスに保存されている保護されたデータにアクセスするには、次を使用します。 認可には OAuth 2.0 を使用します。 Google API は、さまざまな種類のクライアント アプリケーションで OAuth 2.0 フローをサポートしています。 これらのフローのどれでも、クライアント アプリケーションは、 クライアント アプリケーションと保護されたデータのオーナーにのみ関連付けられている あります。アクセス トークンは、サービス アカウントによってアクセスされる クライアント アプリケーションがアクセスできるデータの種類を定義します( 「タスクの管理」など)。OAuth 2.0 の重要な目標は、安全で信頼性の高い 保護されたデータに簡単にアクセスでき、潜在的な影響を最小限に抑えられます。 盗まれた場合にも記録されます。

Java 用 Google API クライアント ライブラリの OAuth 2.0 パッケージは、 インフラストラクチャの Java 用 Google OAuth 2.0 クライアント ライブラリ

詳細については、次のパッケージの Javadoc のドキュメントをご覧ください。

Google API Console

Google API にアクセスするには、 認証と請求のための Google API Console インストール型アプリケーションでもモバイルアプリでも ウェブサーバー、ブラウザで実行されるクライアントなどです。

認証情報を適切に設定する手順については、 API Console ヘルプ

認証情報

GoogleCredential

GoogleCredential 保護されたリソースにアクセスするための OAuth 2.0 用のスレッドセーフなヘルパークラスです。 アクセス トークンを使用します。たとえば、すでにアクセス トークンがある場合は、 は、次の方法でリクエストを送信できます。

GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Plus plus = new Plus.builder(new NetHttpTransport(),
                             GsonFactory.getDefaultInstance(),
                             credential)
    .setApplicationName("Google-PlusSample/1.0")
    .build();

Google App Engine の ID

この代替クルデンシャルは、Terraform の Google App Engine App Identity Java API。 認証情報とは異なり、認証情報ではクライアント アプリケーションが App Identity API は、エンドユーザーのデータへのアクセスを 独自のデータで処理できます。

AppIdentityCredential を使用する (google-api-client-appengine) この認証情報は、Google App Engine にすべて管理されるため、はるかにシンプルです。 できます。必要な OAuth 2.0 スコープのみを指定します。

urlshortener-robots-appengine-sample からのコード例:

static Urlshortener newUrlshortener() {
  AppIdentityCredential credential =
      new AppIdentityCredential(
          Collections.singletonList(UrlshortenerScopes.URLSHORTENER));
  return new Urlshortener.Builder(new UrlFetchTransport(),
                                  GsonFactory.getDefaultInstance(),
                                  credential)
      .build();
}

データストア

アクセス トークンには通常 1 時間の有効期限があり、その後は 使用しようとするとエラーが発生します。 GoogleCredential 自動的に「更新」されます。つまり、このトークンから 発行します。これは、有効期間の長い更新トークンによって行われます。 トークンでアクセス トークンを 認証コードフロー中の access_type=offline パラメータ(参照: GoogleAuthorizationCodeFlow.Builder.setAccessType(String))。

ほとんどのアプリケーションでは、認証情報のアクセス トークンや あります。認証情報のアクセス トークンや更新トークンを保持するには、 DataStoreFactory の独自の実装を指定する。 StoredCredential を使用する。 または、ライブラリで提供されている以下の実装のいずれかを使用できます。

  • AppEngineDataStoreFactory: Google App Engine Data Store API を使用して認証情報を保持します。
  • MemoryDataStoreFactory: 「永続化」メモリ内に認証情報を保存できます。これは、プロセスの存続期間中に短期的なストレージとしてのみ有用です。
  • FileDataStoreFactory: 認証情報がファイルに保持されます。

App Engine ユーザー: AppEngineCredentialStore は非推奨となっており、まもなく削除されます。Google Cloud コンソールの AppEngineDataStoreFactory StoredCredential を使用します。 認証情報が従来の方法で保存されている場合は、追加された ヘルパー メソッド migrateTo(AppEngineDataStoreFactory) または migrateTo(DataStore) 移行する必要があります

次を使用: DataStoreCredentialRefreshListener GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener) を使用して認証情報を設定します。

認可コードフロー

認可コードフローを使用して、エンドユーザーがアプリケーションに アクセスを許可できます。このフローのプロトコルは、 指定 認可コードの付与

このフローは GoogleAuthorizationCodeFlow を使用して実装されています。 ステップは次のとおりです。

  • エンドユーザーがアプリケーションにログインします。このユーザーを アプリケーションに固有のユーザー ID に置き換えます。
  • AuthorizationCodeFlow.loadCredential(String)) を呼び出します。 し、エンドユーザーの認証情報がすでに知っているかどうかを確認します。 あれば完了です。
  • そうでない場合は、AuthorizationCodeFlow.newAuthorizationUrl() を呼び出します。 エンドユーザーのブラウザから認証ページにアクセスし、 アプリケーションへのアクセスを制御できます。
  • その後、Google の認証サーバーはブラウザを code クエリとともにアプリケーションで指定されたリダイレクト URL パラメータを指定します。code パラメータを使用してアクセス トークンをリクエストします。 AuthorizationCodeFlow.newTokenRequest(String))。
  • AuthorizationCodeFlow.createAndStoreCredential(TokenResponse, String) を使用してください。 認証情報を保存および取得して、保護されたリソースにアクセスすることができます。

GoogleAuthorizationCodeFlow を使用しない場合は、下位レベルのクラスを使用することもできます。

Google API Console でプロジェクトを設定すると、 使用するフローに応じて、さまざまな認証情報から選択します。 詳しくは、OAuth 2.0 の設定に関する記事をご覧ください。 OAuth 2.0 のシナリオをご覧ください。 各フローのコード スニペットを以下に示します。

ウェブサーバーアプリケーション

このフローのプロトコルについては、このモジュールの ウェブサーバー アプリケーションに OAuth 2.0 を使用する

このライブラリが提供するサーブレット ヘルパークラスを使用すると、 認証コードフローについて説明します。具体的なサブクラスを指定するだけで AbstractAuthorizationCodeServlet の および AbstractAuthorizationCodeCallbackServletgoogle-oauth-client-servlet から) web.xml ファイルに追加しますユーザー、グループ チャット、 ログインし、ユーザー ID を抽出します。

public class CalendarServletSample extends AbstractAuthorizationCodeServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    // do stuff
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), GsonFactory.getDefaultInstance(),
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

public class CalendarServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet {

  @Override
  protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
      throws ServletException, IOException {
    resp.sendRedirect("/");
  }

  @Override
  protected void onError(
      HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
      throws ServletException, IOException {
    // handle error
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), GsonFactory.getDefaultInstance()
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

Google App Engine アプリケーション

App Engine の認可コードフローはサーブレットとほぼ同じ 使用する場合を除いて、Google App Engine の Users Java API。ユーザー Users Java API を有効にするには、ログインする必要があります。詳細については、 ログインしていない場合は、ユーザーをログインページにリダイレクトします。詳しくは、 セキュリティと認証 (web.xml 内)。

サーブレットの場合との主な違いは、 サブクラス AbstractAppEngineAuthorizationCodeServletAbstractAppEngineAuthorizationCodeCallbackServletgoogle-oauth-client-appengine)。 抽象サーブレット クラスを拡張して getUserId メソッドを実装します。 Users Java API を使用しますAppEngineDataStoreFactorygoogle-http-client-appengine から) Google App Engine Data Fusion の API やライブラリを使用して認証情報を Store API。

calendar-appengine-sample の例(一部変更あり)

public class CalendarAppEngineSample extends AbstractAppEngineAuthorizationCodeServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    // do stuff
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    return Utils.getRedirectUri(req);
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return Utils.newFlow();
  }
}

class Utils {
  static String getRedirectUri(HttpServletRequest req) {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  static GoogleAuthorizationCodeFlow newFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
        getClientCredential(), Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }
}

public class OAuth2Callback extends AbstractAppEngineAuthorizationCodeCallbackServlet {

  private static final long serialVersionUID = 1L;

  @Override
  protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
      throws ServletException, IOException {
    resp.sendRedirect("/");
  }

  @Override
  protected void onError(
      HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
      throws ServletException, IOException {
    String nickname = UserServiceFactory.getUserService().getCurrentUser().getNickname();
    resp.getWriter().print("<h3>" + nickname + ", why don't you want to play with me?</h1>");
    resp.setStatus(200);
    resp.addHeader("Content-Type", "text/html");
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    return Utils.getRedirectUri(req);
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return Utils.newFlow();
  }
}

その他のサンプルについては、以下をご覧ください。 storage-serviceaccount-appengine-sample.

サービス アカウント

GoogleCredential サービス アカウントもサポートしています。 認証情報とは異なり、認証情報ではクライアント アプリケーションが サービス アカウントは、クライアント アプリケーションのリソースへのアクセスを 分析できますクライアント アプリケーションは、次のコマンドを使用してアクセス トークンのリクエストに署名します。 Google API Console からダウンロードした秘密鍵。

plus-serviceaccount-cmdline-sample からのコード例:

HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
...
// Build service account credential.

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(PlusScopes.PLUS_ME));
// Set up global Plus instance.
plus = new Plus.Builder(httpTransport, jsonFactory, credential)
    .setApplicationName(APPLICATION_NAME).build();
...

その他のサンプルについては、以下をご覧ください。 storage-serviceaccount-cmdline-sample.

なりすまし

また、サービス アカウントのフローを使用して、サービス アカウントを持つユーザーの権限を借用することもできます。 できます。これは上記のサービス アカウントのフローと非常によく似ていますが、 さらに、GoogleCredential.Builder.setServiceAccountUser(String) を呼び出します。

インストールしたアプリケーション

これは、インストール済みアプリケーションで OAuth 2.0 を使用するで説明されているコマンドライン認証コードフローです。

スニペットの例 plus-cmdline-sample:

public static void main(String[] args) {
  try {
    httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
    // authorization
    Credential credential = authorize();
    // set up global Plus instance
    plus = new Plus.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName(
        APPLICATION_NAME).build();
   // ...
}

private static Credential authorize() throws Exception {
  // load client secrets
  GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
      new InputStreamReader(PlusSample.class.getResourceAsStream("/client_secrets.json")));
  // set up authorization code flow
  GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
      httpTransport, JSON_FACTORY, clientSecrets,
      Collections.singleton(PlusScopes.PLUS_ME)).setDataStoreFactory(
      dataStoreFactory).build();
  // authorize
  return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}

クライアントサイド アプリケーション

以下で説明されているブラウザベースのクライアント フローを使用するには、 クライアントサイド アプリケーションに OAuth 2.0 を使用する 通常は次の手順を行います。

  1. 次のコマンドを使用して、ブラウザのエンドユーザーを認証ページにリダイレクトします。 GoogleBrowserClientRequestUrl ブラウザ アプリケーションにエンドユーザーの保護されたデータへのアクセスを許可します。
  2. JavaScript 用の Google API クライアント ライブラリを使用する リダイレクト URI の URL フラグメントに含まれるアクセス トークンを処理 Google API Console に登録されている。

ウェブ アプリケーションの使用例:

public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
  String url = new GoogleBrowserClientRequestUrl("812741506391.apps.googleusercontent.com",
      "https://oauth2.example.com/oauthcallback", Arrays.asList(
          "https://www.googleapis.com/auth/userinfo.email",
          "https://www.googleapis.com/auth/userinfo.profile")).setState("/profile").build();
  response.sendRedirect(url);
}

Android

@ベータ版

Android で使用するライブラリ

Android 向けの開発を行っていて、使用する Google API が組み込まれている場合 の Google Play 開発者サービス ライブラリ 最適なパフォーマンスとエクスペリエンスを実現しますGoogle API に Google Play 開発者サービス ライブラリに含まれていない場合は、 Android 4.0(Ice Cream Sandwich)対応の Java 用 Google API クライアント ライブラリを使用できる 以上です。これについては、こちらで説明します。Google Java 用 API クライアント ライブラリは @Beta です。

バックグラウンド:

Eclair(SDK 2.1)以降、ユーザー アカウントは Android デバイスで管理されます アカウントマネージャーを使用してすべての Android アプリの承認は、 「新規顧客の獲得」目標を AccountManager。 アプリケーションに必要な OAuth 2.0 のスコープを指定すると、 使用するトークンです。

OAuth 2.0 スコープは、authTokenType パラメータで oauth2: として指定されます。 あります。例:

oauth2:https://www.googleapis.com/auth/tasks

Google Tasks API への読み取り/書き込みアクセスを指定します。複数の OAuth 2.0 スコープの場合は、スペース区切りのリストを使用します。

一部の API には特別な authTokenType パラメータがあり、これも機能します。たとえば 「タスクを管理」これは、上記の authtokenType の例のエイリアスです。

また、API キーを Google API Console: それ以外の場合は、AccountManager が付与するトークンは 。これに対して、API を指定することで 無料割り当てが増えます。また、必要に応じて使用量に応じたお支払い情報を設定できます。 その上にあります

コード スニペットの例 tasks-android-sample:

com.google.api.services.tasks.Tasks service;

@Override
public void onCreate(Bundle savedInstanceState) {
  credential =
      GoogleAccountCredential.usingOAuth2(this, Collections.singleton(TasksScopes.TASKS));
  SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
  credential.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
  service =
      new com.google.api.services.tasks.Tasks.Builder(httpTransport, jsonFactory, credential)
          .setApplicationName("Google-TasksAndroidSample/1.0").build();
}

private void chooseAccount() {
  startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  switch (requestCode) {
    case REQUEST_GOOGLE_PLAY_SERVICES:
      if (resultCode == Activity.RESULT_OK) {
        haveGooglePlayServices();
      } else {
        checkGooglePlayServicesAvailable();
      }
      break;
    case REQUEST_AUTHORIZATION:
      if (resultCode == Activity.RESULT_OK) {
        AsyncLoadTasks.run(this);
      } else {
        chooseAccount();
      }
      break;
    case REQUEST_ACCOUNT_PICKER:
      if (resultCode == Activity.RESULT_OK && data != null && data.getExtras() != null) {
        String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
        if (accountName != null) {
          credential.setSelectedAccountName(accountName);
          SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
          SharedPreferences.Editor editor = settings.edit();
          editor.putString(PREF_ACCOUNT_NAME, accountName);
          editor.commit();
          AsyncLoadTasks.run(this);
        }
      }
      break;
  }
}