APIキー、OAuthクライアントID、サービスアカウントキーの違い:Google APIs
GoogleのサービスをAPI経由で利用する際、大きく3つの認証情報が登場します。「APIキー」、「OAuth2.0クライアントID」、「サービスアカウントキー」です。本投稿ではこれらの用途をざっくりと整理し、取得方法、Pythonでの使い方の違いを説明します。
まとめ
- Google APIsを使うには、下表の3ついずれかの認証情報が必要です
- APIでどういうデータに、どういう形でアクセスするかに依って使うべき認証情報が異なります
- いずれの認証情報もGoogle Cloud Consoleの
APIとサービス > 認証情報
から作成することができます
# | 必要となるもの | アクセス可能なデータ | 誰としてアクセスするか | 具体例 |
---|---|---|---|---|
1 | APIキー | 一般公開データ | 匿名ユーザ | YouTubeにある動画をアプリケーション経由で検索する |
2 | OAuth2.0クライアトID | 一般公開データ/ユーザーデータ | ユーザアカウント | あるユーザ(エンドユーザ)の代わりにユーザのGoogleドライブにアプリケーションを経由でデータを保存 |
3 | サービスアカウントキー | 一般公開データ/ユーザーデータ | サービスアカウント | 共同作業メンバのGoogleカレンダー情報にアプリケーションを経由してアクセスする |
基本事項のおさらい
認証情報について理解する上で知っておいたほうが良い基本事項についてまとめます。必要ない方は飛ばしてください。
APIの性質
API(Application Programming Interface)はサービスを外部のプログラムやアプリケーションから利用できるようにした窓口です。例えば、Google MapはGoogleのサービスの一つで、普通私たちユーザはブラウザやGoogle Map Appを自分で操作してGoogle Mapを利用します。一方で自身が開発するアプリの中でGoogle Map機能の一部を利用したい場合は、アプリの中のプログラムを介してGoogle Map機能を操作する必要があります。ここで利用されるのがAPIというプログラムから呼び出すインターフェースです。
一般にAPIはプログラムやアプリケーションから利用されます。
認証情報の役割
Google は許可されたアプリケーションからしかAPI利用をさせてくれません。そのため我々API利用者はGoogleアカウントを作成し、Google Cloud Console内でAPIを利用するアプリケーションの登録を行う必要があります。
つまりどの開発者が登録した、どのアプリケーションがAPIを叩いているのかをGoolge様にお知らせするのがAPIキーやOAuth2.0クライアトIDなど認証情報の役割の一つです。
またAPI利用は使用量の無料枠上限を超えると課金が発生します。API利用がどのアプリでどの程度発生しているかをGoogle様にお知らせするのも認証情報の役割です。課金管理はプロジェクト単位で行われるため認証情報はGoogleアカウント内のプロジェクトと紐付ける必要があります。これが認証情報を作成する際にプロジェクトが必要な理由です。
3つの認証情報は想定される利用シーンが異なる
APIキー、OAuth2.0クライアントID、サービスアカウントキーの3種類のいずれかがあればAPIを使うことが可能です。ただし三者は用途が異なり、用途にあった認証情報を選択するのが自然です。たとえば一般公開データにしかアクセスしないのに、OAuthクライアントIDを使う必要はありません。用途に応じた必要最低限の認証情報を使います。
以上を踏まえて3つの認証情報をそれぞれ見ていきましょう。
1. APIキー
まずはAPIキーについてです。Google Cloud ドキュメント:API キーの使用には次のように説明されています。
API キーは、プリンシパルなしでアプリケーションを識別する暗号化された単純な文字列です。一般公開データに匿名でアクセスする場合に便利で、割り当てや課金のために API リクエストをプロジェクトに関連付けるために使用されます。
YouTubeでの検索機能のように一般公開データにのみアクセスできれば十分な場合、利用者にユーザアカウントでログインしてもらうような必要はありません。このようなケースではAPIキーを使ってAPIを利用します。APIキーは暗号化された単純な文字列で、作成も取り扱いも比較的簡単です。
取得方法
事前にGoogle Cloud アカウント作成とプロジェクト作成が必要です。まだな方は以下のサイトなどを参考にして、アカウントとプロジェクト作成を行ってください。
Google アカウントを作成する(Gmail アドレスも同時に作成) | MAGELLAN BLOCKS
Google アカウントを作成する(Gmail アドレスも同時に作成) | MAGELLAN BLOCKS
プロジェクト作成が完了したら次の手順でAPIキーを作成します。
1. プロジェクトを選択
Google Cloud Consoleにログインして、APIを利用するプロジェクトを選択します。
APIとサービス > 認証情報
2. APIキーの作成
「認証情報の作成」をクリック
「APIキー」を選択
APIキーが表示されたボックスの右側にあるコピーマークをクリックし、閉じる
3. キーで利用するAPIを制限する(オプショナル)
作成直後の状態ではすべてのAPIの利用が可能となっているので、利用したいAPIのみに制限します
作成したAPIキーを選択
APIの制限 > キーを制限
Pythonでの利用例
例として、PythonからAPIキーを使ってYouTubeのsearchAPIを使うサンプルコードを掲載します。 下記コードのYOUTUBE_API_SERVICE_NAME
やYOUTUBE_API_VERSION
を変えるといろいろなAPIを使えるようになります。
from googleapiclient.discovery import build # 利用するAPIサービス YOUTUBE_API_SERVICE_NAME = 'youtube' YOUTUBE_API_VERSION = 'v3' # APIキーを指定 YOUTUBE_API_KEY = 'Your-API-KEY-here' # API のビルドと初期化 youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=YOUTUBE_API_KEY) # YouTubeでキーワード検索(視聴数の多い順) q = 'Overjoyed' response = youtube.search().list(part='snippet', q=q, order='viewCount', type='video',).execute() response >>> # 出力 {'etag': 'QvSya4g44W8aUkApKibFr-o5JqA', 'items': [{'etag': 'Jw9SPInmYcoJg21LlKvbdDhk1IU', 'id': {'kind': 'youtube#video', 'videoId': '_a1LogyX9Uw'}, 'kind': 'youtube#searchResult', 'snippet': {'channelId': 'UCOo4Oc-PYSrzEeappVyoM-Q', 'channelTitle': 'beechoppers', 'description': 'please enjoy the music! music and ' 'lyrics by stevie wonder clip design by ' 'R. Norton.', 'liveBroadcastContent': 'none', ...
2.OAuth2.0クライントID
アプリ経由で利用者のGoogleドライブにファイルを保存をする場合など、アプリケーションがエンドユーザーに代わって Google Cloud APIs にアクセスします。このケースで利用するのがOAuth2.0クライアントIDです。OAuth2.0プロトコルを利用することで、アプリケーションが特定ユーザとしてサービスを利用します。その際に許可する権限の範囲(スコープ)も制限します。
OAuth2.0クライントIDは、OAuth2.0クライアントクレデンシャル(資格情報)というJSONファイルとしてダウンロードし利用することが多いと思います。OAuth2.0クライアントクレデンシャルには、OAuth2.0認証を利用するアプリの情報(クライアントID、クライアントシークレット)が含まれます。クレデンシャルはGoogle様にアプリ開発者がOAuth認証を行う資格があることを示します。
取得方法
OAuth認証は作成する同意画面の設定やアプリの種類など状況によって適切に設定する必要がありますが、本投稿ではテストとして最短で利用する手順を書いてみます。
1.同意画面の設定
OAuth認証では、認証時ユーザにログインをしてもらったり、許可してもらう権限の範囲を示す必要があるため、認証画面に表示する情報は重要です。以下はconnpassにTwitterアカウントでログインする際のOAuth認証画面です。画面にはconnpassのロゴなど表示され、どのアプリがアカウント情報を利用しようとしているかひと目で分かります。
このユーザに同意を求める部分の設定を「同意画面の設定」から行っていきます。今回はテストなのでなるべく手軽に行うことを目指します。
APIキー同様、まずGoogle Cloud Consoleにログインして、APIを利用するプロジェクトを選択します。
APIとサービス > OAuth同意画面を選択し、適当なアプリ名とメールアドレスを入力します
UserTypeを聞かれるので、今回は「外部」を選びます。「内部」は使ったことありませんが、G Suiteの組織内で利用するときに使うようです。
省略できる箇所は省略し、試すのに必要最低限な入力をして「保存して次へ」で進めます。入力が必要なのはメールアドレスのみです。実際にアプリを開発する際はスコープなど慎重に設定しましょう。
2.OAuthクライアントIDの作成
「+認証情報を作成」から「OAuthクライアントID」を選択します
アプリケーションの種類はここでは、デスクトップを選択しています
これでOAuthクライアントクレデンシャルが作成されました
「OK」を押して、作成されたIDの右にある↓矢印からJSONをダウンロードします。
これでOAuthクライアントIDを含む、OAuthクライアントクレデンシャルが発行されました。
Pythonでの利用例
例として、PythonからOAuthクレデンシャルを使ってYouTubeのplaylistAPIを使うサンプルコードを掲載します。以下はOAuth認証用の関数を定義をしています。この関数を使ってOAuth認証をし、その後ユーザデータにアクセスします。今回はYouTubeに自分用の再生リストを作成したいと思います。実行のコードを下部にあります。
'''OAuth認証用の関数''' import os import pickle import numpy as np import pandas as pd from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request def get_credentials(client_secret_file, scopes, token_storage_pkl='token.pickle'): '''google_auth_oauthlibを利用してOAuth2認証 下記URLのコードをほぼそのまま利用。Apache 2.0 https://developers.google.com/drive/api/v3/quickstart/python#step_1_turn_on_the_api_name ''' creds = None # token.pickleファイルにユーザのアクセス情報とトークンが保存される # ファイルは初回の認証フローで自動的に作成される if os.path.exists(token_storage_pkl): with open(token_storage_pkl, 'rb') as token: creds = pickle.load(token) # 有効なクレデンシャルがなければ、ユーザーにログインしてもらう if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( client_secret_file, scopes=scopes) creds = flow.run_local_server(port=0) # クレデンシャルを保存(次回以降の認証のため) with open(token_storage_pkl, 'wb') as token: pickle.dump(creds, token) return creds
以下のコードのCLIENT_SECRET_FILE
に先程ダウンロードしたJSONを指定してください。これを実行するとまずOAuth認証のためにブラウザが立ち上がり利用者にGoogleアカウントでのログインを求めます。
認証が終わると「再生リストテスト」という名で空の再生リストが作成されます。
'''OAuth認証と再生リストの作成''' # 利用するAPIサービス YOUTUBE_API_SERVICE_NAME = 'youtube' YOUTUBE_API_VERSION = 'v3' # OAuthのスコープとクレデンシャルファイル YOUTUBE_READ_WRITE_SCOPE = 'https://www.googleapis.com/auth/youtube' CLIENT_SECRET_FILE = 'client_secret.json' # OAuth認証:クレデンシャルを作成 creds = get_credentials( client_secret_file=CLIENT_SECRET_FILE, scopes=YOUTUBE_READ_WRITE_SCOPE ) # API のビルドと初期化 youtube_auth = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, credentials=creds) # Add Playlist # This code creates a new, private playlist in the authorized user's channel. playlists_insert_response = youtube_auth.playlists().insert( part="snippet,status", body=dict( snippet=dict( title='再生リストテスト', description='APIで作成したプレイリスト' ), status=dict( privacyStatus="private" ) ) ).execute()
3. サービスアカウントキー
サービスアカウントはアカウントの一種です。アカウントなのでメールアドレスが割り当てられますが、アプリケーションが利用するアカウントなのでユーザアカウントとは異なり、ログインなどはできません。利用者がこのアプリケーション用のアカウントとデータを共有することで、プログラムからユーザデータへのアクセスが可能になります。APIはこのサービスアカウントの代わってサービスの操作を行います。
用途としてはたとえば、自分のGoogleカレンダーをサービスアカウントと共有し、アプリケーションからAPI経由で閲覧や編集するなどがあります。
サービスアカウントキーでの認証は、一般にサービスアカウントクレデンシャルというJSONファイルを使って行われます。サービスアカウントクレデンシャルにはアカウントのメールアドレスや、鍵情報、クライントIDなど認証に必要な情報が含まれています。これまでの認証と違ってアカウント認証もこの資格情報で行います。
取得方法
1. プロジェクトを選択
Google Cloud Consoleにログインして、APIを利用するプロジェクトを選択します。
APIとサービス > 認証情報
2. サービスアカウントキーの作成
「+認証情報を作成」から「サービスアカウント」を選択
サービスアカウント名を入力
続行を選んで、完了します。
3. 鍵ペアの作成
作成したサービスアカウントを選んで
鍵を追加で、「新しい鍵を追加」してJSONを選びます。 ついでに、上部のメールアドレスもコピーしておきましょう。
保存した.json
ファイルを認証に利用します。
Pythonでの利用例
例として、Pythonからサービスアカウントキーを用いてGoogle スプレッドシートのセルの値を取得してみます。まずClould Consoleの各プロジェクトでGoogle Sheet APIを有効にしておきましょう。
APIとサービス > ライブラリ
検索窓でsheet
を入力して、Google Sheets APIを選ぶ
次の準備として、Google スプレッドシートで新規にスプレッドシートを作成し、作成したシートをサービスアカウントと共有(編集権限を与える)しておく必要があります。
何か入力して、右上の「share」を押下
さきほどメモったサービスアカウントのメールアドレスを貼り付けて「OK」を押して、シート共有します。
さらにシートのURLから以下のsheet_id
をメモっておきましょう
https://docs.google.com/spreadsheets/d/<sheet_id>
実行するコードこちらです。これでシートの値が取得できます。
from googleapiclient.discovery import build from google.oauth2 import service_account CREDENTIAL_FILE = 'credential_json_path' credentials =\ service_account.Credentials.from_service_account_file(CREDENTIAL_FILE) SAMPLE_SPREADSHEET_ID = '1CL0pg_LDpASaHQqagDxBDKonmD64NRS6CQnpAbVDjhs' SAMPLE_RANGE_NAME = 'Sheet1!A1:B4' # Sheets APIビルド service = build('sheets', 'v4', credentials=credentials) # セルの値を取得 sheet = service.spreadsheets() result = sheet.values().get(spreadsheetId=SAMPLE_SPREADSHEET_ID, range=SAMPLE_RANGE_NAME).execute() values = result.get('values') >>> # 出力 [['1', 'あ'], ['2', 'い'], ['3', 'う']]
APIで権限まわりは混乱しがちですね。ちょっと長くなりましたが整理してみました。日々精進