Google APIでOAuth2.0を利用するためのGoogle Console設定手順(画面キャプチャ付)

NeoMutt(https://neomutt.org/)でGmailを送受信するために行った、Google Consoleでの設定手順。

Google APIを使ったアプリを使いたい or 作りたいけど何をやればいいのかサッパリ、、、

という僕みたいな人向け。

Gmail以外のAPIでもOAuth2.0を利用する場合は、同じ様な手順になると思うのでご参考までに。

そもそもOAuth2.0って何ぞやという人は、先に下の記事をご覧下さいまし。

hacolab.hatenablog.com

説明の前に

手順の説明画像中に特にコメントがない箇所は、単純に赤枠で示したメニューやボタンをクリックしてね。

また、以降の説明でいう「アプリ」はOAuth2.0でいうところの「クライアント」のことになるよ。

1. プロジェクトの作成

まずは下のページからプロジェクトを作る。(利用するアカウントでログインしてね)

console.developers.google.com

f:id:hacolab:20200528154926p:plain


Google Consoleで識別するためのプロジェクト名を入力して「作成」をクリック。

f:id:hacolab:20200528154930p:plain


プロジェクトを作成したら、下のような画面が出ると思う。

f:id:hacolab:20200528154934p:plain

2. APIの有効化

次に、アプリから利用するAPIを有効にしておく。
画面上部にある検索フォームに使いたいAPI名などを入力して、利用するAPIを選択しよう。
下はGmail APIを選択する例。

f:id:hacolab:20200528154820p:plain


選択したAPIの画面が出たら、「有効にする」をクリック。

f:id:hacolab:20200528154825p:plain


完了したら、下のようなトラフィック情報などの画面が出ると思う。

f:id:hacolab:20200528154829p:plain

3. 認可画面の構成設定

次に、アプリが初回アクセスするときなどに表示する認可画面の設定を行う。

f:id:hacolab:20200528154833p:plain

「外部」を選択して、「作成」をクリック。(僕の場合「内部」は選べなかった)

f:id:hacolab:20200528154837p:plain

適当なアプリ名を入力して、「スコープを追加」を選択。
他にも認可画面時に表示するロゴとかリンクとか指定できるっぽい。

f:id:hacolab:20200528154841p:plain

許可するスコープを選択して「OK」をクリック。

f:id:hacolab:20200528154846p:plain

選択したAPIが追加されていることを確認したら「保存」をクリック。

f:id:hacolab:20200528154850p:plain

完了したら、下の確認ステータスなどの画面が出ると思う。

f:id:hacolab:20200528154855p:plain

4. 認証情報の作成(アプリの登録とクライアントIDの取得)

最後に、利用するアプリを登録して、クライアントIDとシークレットを取得する。

f:id:hacolab:20200528154913p:plain

「アプリケーションの種類」は各自のアプリに合わせて設定してね。

f:id:hacolab:20200528154917p:plain

アプリを登録できたら、クライアントIDとクライアントシークレットが表示される。
きっと後で使うので、コピペして保存しておこう。

f:id:hacolab:20200528154921p:plain

以上で、Google Console側の設定は終わり。

補足) 認可情報の確認とリセット方法

クライアントIDなどを確認したい、またはリセットしたいときなどは以下の画面から。

f:id:hacolab:20200528154901p:plain

f:id:hacolab:20200528154908p:plain

参考

NeoMuttのデフォルトキーバインドと対応関数

NeoMuttを起動して?で表示されるやつ。

見づらいのでブラウザ、スマホ用。

多いなぁ。

キーバインド一覧

キー 関数 概要
^B M <enter-command>s... call urlview to extract URLs out of a message
^D delete-thread スレッドのメッセージをすべて削除
^E edit-type 添付ファイルの content-type を編集
^F forget-passphrase wipe passphrases from memory
<Tab> next-new-then-unread 次の新着または未読のメッセージへ移動
<Enter> display-message メッセージを表示
^K extract-keys サポートされている公開鍵を抽出
<Return> display-message メッセージを表示
^N next-thread 次のスレッドに移動
^P previous-thread 前のスレッドに移動
^R read-thread 現在のスレッドを既読にする
^T untag-pattern パターンに一致したメッセージのタグをはずす
^U undelete-thread スレッドのすべてのメッセージの削除状態を解除
<Esc><Tab> previous-new-then-unre 前の新着または未読メッセージに移動
<Esc>C decode-copy text/plain にデコードしたコピーを作成
<Esc>P check-traditional-pgp 旧形式の PGP をチェック
<Esc>V collapse-all すべてのスレッドを展開/非展開
<Esc>b M <search>~b search in message bodies
<Esc>c change-folder-readonly 読み出し専用モードで別のフォルダをオープン
<Esc>d delete-subthread 副スレッドのメッセージをすべて削除
<Esc>e resend-message 現在のメッセージを新しいものの原形として利用
<Esc>i change-newsgroup-reado 読み出し専用モードで別のニュースグループをオープン
<Esc>k mail-key PGP 公開鍵をメール送信
<Esc>l show-limit 現在有効な制限パターンの値を表示
<Esc>n next-subthread 次のサブスレッドに移動
<Esc>p previous-subthread 前のサブスレッドに移動
<Esc>r read-subthread 現在のサブスレッドを既読にする
<Esc>s decode-save text/plain にデコードしたコピーを作成し削除
<Esc>t tag-thread 現在のスレッドにタグを付ける
<Esc>u undelete-subthread サブスレッドのすべてのメッセージの削除を解除
<Esc>v collapse-thread 現在のスレッドを展開/非展開
<Space> display-message メッセージを表示
# break-thread スレッドをはずす
$ sync-mailbox 変更をメールボックスに保存
% toggle-write メールボックスに変更を書き込むかどうかを切替
& link-threads タグ付きメッセージを現在位置につなぐ
. mailbox-list 新着メールのあるメールボックスを一覧表示
@ display-address 送信者の完全なアドレスを表示
C copy-message メッセージをファイルやメールボックスにコピー
D delete-pattern パターンに一致したメッセージを削除
F flag-message 「重要」フラグの切替
G fetch-mail POP サーバからメールを取得
J next-entry 次のエントリに移動
K previous-entry 前のエントリに移動
L list-reply 指定済みメーリングリスト宛てに返信
M show-log-messages show log (and debug) messages
N toggle-new メッセージの「新着」フラグを切替
O sort-reverse メッセージを逆順で整列
P parent-message スレッドの親メッセージに移動
Q query 外部プログラムにアドレスを問い合わせ
R recall-message 書きかけのメッセージを呼び出す
T tag-pattern パターンに一致したメッセージにタグを付ける
U undelete-pattern パターンに一致したメッセージの削除状態を解除
V show-version NeoMutt のバージョンの番号と日付を表示
W clear-flag メッセージのステータスフラグを解除
Y edit-label メッセージのラベルを追加、編集、削除
a create-alias メッセージの送信者から別名を作成
b bounce-message メッセージを他のユーザに再送
c change-folder 別のフォルダをオープン
d delete-message 現在のエントリを削除
e edit-or-view-raw-messa 元のメッセージを編集、読み取り専用の場合は閲覧のみ
f forward-message コメント付きでメッセージを転送
g group-reply すべての受信者に返信
h display-toggle-weed メッセージを表示し、ヘッダ抑止を切替
i change-newsgroup 別のニュースグループをオープン
j next-undeleted 次の未削除メッセージに移動
k previous-undeleted 前の未削除メッセージに移動
l limit パターンに一致したメッセージだけ表示
m mail 新規メッセージを作成
o sort-mailbox メッセージを整列
p print-message 現在のエントリを印刷
q quit 変更をメールボックスに保存後終了
r reply メッセージに返信
s save-message メール/添付ファイルをボックス/ファイルに保存
u undelete-message エントリの削除状態を解除
v view-attachments MIME 添付ファイルを表示
w set-flag メッセージにステータスフラグを設定
x exit このメニューを終了
y M <change-folder>? show incoming mailboxes list
| pipe-message メッセージ/添付ファイルをコマンドにパイプ
~ mark-message 現在のメッセージに戻るホットキーマクロを作成
<Down> next-undeleted 次の未削除メッセージに移動
<Up> previous-undeleted 前の未削除メッセージに移動

一般的なキーバインド:

キー 関数 概要
<Enter> select-entry 現在のエントリを選択
^L refresh 画面をクリアし再描画
<Return> select-entry 現在のエントリを選択
<Esc>/ search-reverse 逆順の正規表現検索
! shell-escape サブシェルでコマンドを起動
* last-entry 最後のエントリに移動
/ search 正規表現検索
1 jump インデックス番号に飛ぶ
2 jump インデックス番号に飛ぶ
3 jump インデックス番号に飛ぶ
4 jump インデックス番号に飛ぶ
5 jump インデックス番号に飛ぶ
6 jump インデックス番号に飛ぶ
7 jump インデックス番号に飛ぶ
8 jump インデックス番号に飛ぶ
9 jump インデックス番号に飛ぶ
: enter-command neomuttrc のコマンドを入力
; tag-prefix 次に入力する機能をタグ付きメッセージに適用
< previous-line 一行上にスクロール
= first-entry 最初のエントリに移動
> next-line 一行下にスクロール
? help この画面
H top-page ページの一番上に移動
L bottom-page ページの一番下に移動
M middle-page ページの中央に移動
Z previous-page 前のページに移動
[ half-up 半ページ上にスクロール
] half-down 半ページ下にスクロール
j next-entry 次のエントリに移動
k previous-entry 前のエントリに移動
n search-next 次に一致するものを検索
q exit このメニューを終了
t tag-entry メッセージにタグ付け
z next-page 次ページへ移動
<Down> next-entry 次のエントリに移動
<Up> previous-entry 前のエントリに移動
<Left> previous-page 前のページに移動
<Right> next-page 次ページへ移動
<Home> first-entry 最初のエントリに移動
<F1> M <shell-escape> le... show NeoMutt documentation
<PageDown> next-page 次ページへ移動
<PageUp> previous-page 前のページに移動
<End> last-entry 最後のエントリに移動

未バインドの機能:

関数 概要
catchup ニュースグループ内の記事を全て既読にする
change-vfolder open a different virtual folder
compose-to-sender compose new message to the current message sender
decrypt-copy 復号化したコピーを作成
decrypt-save 復号化したコピーを作ってから削除
edit edit the raw message (edit and edit-raw-message are synonyms)
edit-raw-message edit the raw message (edit and edit-raw-message are synonyms)
entire-thread メッセージに関連したスレッド全体を読む
followup-message followup to newsgroup
forward-to-group ニュースグループへ転送
get-children 全ての子メッセージを取得
get-message get message with Message-Id
get-parent 親メッセージを取得
group-chat-reply reply to all recipients preserving To/Cc
imap-fetch-mail IMAP サーバからメールを取得
imap-logout-all すべての IMAP サーバからログアウト
limit-current-thread limit view to current thread
modify-labels (notmuch/imap) タグを変更
modify-labels-then-hide modify (notmuch/imap) tags and then hide message
modify-tags (notmuch/imap) タグを変更
modify-tags-then-hide modify (notmuch/imap) tags and then hide message
next-new 次の新着メッセージに移動
next-unread 次の未読メッセージへ移動
next-unread-mailbox 新着のある次のメールボックスを開く
post-message post message to newsgroup
previous-new 前の新着メッセージに移動
previous-unread 前の未読メッセージに移動
purge-message ごみ箱に入れず、現在のエントリを即座に削除
purge-thread ごみ箱に入れず、現在のエントリを即座に削除
quasi-delete NeoMuttから削除。ディスク上のデータは変更しない
reconstruct-thread reconstruct thread containing current message
root-message スレッドのルートメッセージに移動
sidebar-next (サイドバー) 次のメールボックスを選択
sidebar-next-new (サイドバー) 次の新着ありメールボックスを選択
sidebar-open (サイドバー) 選択したメールボックスをオープン
sidebar-page-down (サイドバー) 1ページ下にスクロール
sidebar-page-up (サイドバー) 1ページ上にスクロール
sidebar-prev (サイドバー) 前のメールボックスを選択
sidebar-prev-new (サイドバー) 前の新着ありメールボックスを選択
sidebar-toggle-virtual toggle between mailboxes and virtual mailboxes
sidebar-toggle-visible サイドバーを(不)可にする
tag-subthread 現在のサブスレッドにタグを付ける
toggle-read toggle view of read messages
vfolder-from-query クエリからバーチャルフォルダを作成
vfolder-from-query-readonly クエリから読み取り専用のバーチャルフォルダを作成
vfolder-window-backward shifts virtual folder time window backwards
vfolder-window-forward shifts virtual folder time window forwards
view-raw-message show the raw message
check-stats calculate message statistics for all mailboxes
current-bottom スクリーンの一番下にエントリ移動
current-middle スクリーンの中央にエントリ移動
current-top スクリーンの一番上にエントリ移動
end-cond 条件付き実行の終了 (何もしない)
search-opposite 逆順で一致するものを検索
tag-prefix-cond 次に入力する機能をタグ付きメッセージにのみ適用
what-key 次に押すキーのコードを表示

確認環境

PC Thinkpad X1 Carbon 2nd Gen
OS FreeBSD 12.1-RELEASE-p5
NeoMutt NeoMutt 20200320

OAuth2.0コトハジメ

はじめに

『世界のまん中が視たい』(意訳:Gmailをコンソールで読みたい)

コトは、そんな人類共通のささやかな夢からハジマッタ。

椎名林檎 - 自由へ道連れ from 真空地帯

今回はひとまず夢の実現は置いといて。

逸る命を抑えながら、名前しか知らない「OAuth2.0」について調べてみたよ。

しかも図まで描いてみた。

何かツッコミあればコメント下さいまし。

概要

OAuth2.0は認可のためのフレームワーク

「認証」とは、相手が誰なのかを確認すること。

「認可」とは、相手があるリソースへアクセスするのを許可すること。

OAuth2.0は、HTTPサービスをサードパーティ製アプリから利用することを想定した、「認可」フレームワークとのこと。

OAuth2.0を使うと何が嬉しいの?

OAuth2.0を使えば、HTTPサービスへの認証情報(IDやパスワードなど)をサードパーティ製のアプリに渡さなくて済む。

BASIC認証の場合

HTTPサービスを利用する場合、認証情報でサービスへ認証した後に個人的なリソースへアクセスできるようになる。

使用前に認証情報を直接入力させるアプリも多い。
しかし、パスワードなどを毎回入力するのは面倒だ。

アプリによっては次回以降の入力を省くために認証情報を保存しておくかもしれない。
そしてそれが誰かに盗まれるかもしれない。

いや、そもそもそのアプリ自体が悪意のある誰かが用意したトラップかもしれない。

いずれにせよ、認証情報が流出するリスクが増える
流出した場合、悪意のある誰かが勝手にログインし、やりたい放題される危険がある。

OAuth2.0の場合

一方、OAuth2.0の場合、HTTPサービスへの認証情報をアプリに渡さない。

認証情報の代わりに、アクセス可能な範囲と有効期限が記されたチケットをアプリに渡す。
アプリはこのチケットを使って、HTTPサービスのリソースにアクセスできる。

もし仮に、このチケットが流出してしまったとしよう。
しかし、このチケットを使ってアクセスできるのは、予め許可した範囲内のリソースのみだ。
認証情報そのものが流出した場合よりは、被害範囲を限定できる
また、チケットには期限があり、リスクに晒される期間も限定できる

というのが、OAuth2.0を使う際のメリットとして大きく主張されているっぽい。

OAuth2.0を利用する流れ

OAuth2.0を利用する流れを図にしてみた。

f:id:hacolab:20200523105133p:plain

なお、以下の点に注意。

  • OAuth2.0の認可方式は4つ定義されている
    • 上図はそのうちの一つ「認可コードによる認可」
  • クライアントはPCネイティブアプリを想定
  • やりとりしているデータはあくまで抜粋
    • 具体的には各サービスの仕様を参照
  • リフレッシュトークンはオプション仕様
    • Googleは対応してるっぽいよ

OAuth2.0の標準仕様は以下を参照してね。
(以降、単に「仕様」といったらこの仕様のことだよ)

以降では、各フェーズを簡単に説明していく。

少し長めなので、興味がわいた人は読んでみて下さいな。

登場人物

今回の説明に出てくる人たち。

登場人物 人物紹介
リソースサーバーが提供するHTTPサービスの利用者。
クライアントからのリソースへのアクセスを認可するひとでもある。

あるHTTPサービスをクライアント経由で使いたいと考えている。
リソースサーバーが提供するHTTPサービスを利用するアプリケーション。

ネイティブアプリや、Webアプリ、その他の何かかもしれない。

HTTPサービス提供者とは別のサードパーティー製である場合、この子にHTTPサービスにログインするための認証情報を渡したくないというのが、OAuth2.0を使うモチベーションっぽい。
認可手続きの際に利用するアプリケーション。

一般的にはWebブラウザが想定されると思う。

公式も含め、OAuthの登場人物としてはあまり紹介されない不遇な子。
あるHTTPサービスを提供するひと。
もちろん、OAuthに対応しているサービスでなければならない。

Google系サービスとか、Twitterとか、Facebookとか。
OAuthによるリソースへのアクセスを認可する手続きを担うひと。

だいたいリソースサーバーを提供する会社が用意しているかと。

1. 事前準備

f:id:hacolab:20200522172922p:plain

OAuth2.0を利用するには、まずリソースオーナーは利用したいクライアントを認可サーバーに登録しなければならない。
登録が完了したら「クライアントID」を認可サーバーから発行してもらえる。

発行された「クライアントID」をクライアントに通知する方法はアプリによると思う。
上図では、ブラウザで表示された「クライアントID」をリソースオーナーがコピペするイメージ。

補足) GoogleAPIでのクライアント登録方法

GoogleAPIでOAuth2.0を利用する場合は、Google Consoleから登録するっぽい。
(プロジェクトを作成後、「認証情報を作成」メニューからっぽい)

下の記事が画面キャプチャ付きで分かりやすいかも。

qiita.com

しかし、GmailAPIなどの各API個別の設定画面にも「認証情報を作成」メニューがあるじゃないか。

どこから登録すべきなのか、僕は世界のまん中で愛を叫びたいくらい混乱している。

Gmailだけを使用するクライアントなら、個別APIで認証情報を作成した方がいいのかしら。

2. クライアントの認可

f:id:hacolab:20200522172926p:plain

概要で説明した通り、OAuth2.0ではリソースにアクセスする際に、スコープと有効期限が記されたチケットを使う。

仕様ではこのチケットのことを「アクセストークン」と呼んでいる。

それでは、OAuth2.0の肝である認可の流れと「アクセストークン」を受け取るまでの流れを見て行こう。

と、その前に。
上図では3つのエンドポイント(URI)が登場しているので、ちょっと意識して欲しい。

  • 認可エンドポイント(赤丸): 認可手続きを要求するURI
  • トークンエンドポイント(青丸): アクセストークンを要求するURI
  • リダイレクトエンドポイント(緑丸): 認可完了時の遷移先URI (仕様ではリダイレクトURIとも)

特に、認可サーバーといっても要求によって送り先が分けられている点は実際の利用時に注意したい。

認可

クライアントは「アクセストークン」を取得するため、まず先に認可してもらう必要がある。

認可の具体的な手順はアプリやサービスによると思う。
上図では、認可エンドポイントのURIをクライアントが生成して、それをWebブラウザで開いて認可手続きを行うイメージ。

クライアントが認可する工程に直接関わらないことによって、クライアントには認証情報を渡さなくて済むようになっている。

クライントは認可手続きが外部の何らかの方法で完了した後に、認可されたことを証明する「認可コード」というチケットを受け取ればいい。

補足) 認可コードを受け取る方法

面白いなと思ったのは、認可サーバーは認可完了時にクライアントが指定したURIにHTTPリダイレクトさせる点。
HTTPの302レスポンスと共に、パラメータとして「認可コード」を返すようになっている。

これはきっと「認可コード」をクライアントが受け取る方法は、クラアント開発者に委ねるということ。

その方法はもしかすると、リダイレクト先でWebブラウザに表示された「認可コード」を、ユーザーがコピペしてクライアントに教えるのかもしれない。

その方法はもしかすると、リダイレクト先から「認可コード」を自動でクライアントに通知するのかもしれない。

あー、選べる自由があるってステキ。

しかし、自由と一緒に、変なURIにリダイレクトさせられるリスクもやってきた。

あー、自由って難しい。。。

ただ、仕様では下のような対策が一部用意されているっぽい。

アクセストークンの取得

クライアントは「認可コード」を受け取ったら、それを認可サーバーのトークンエンドポイントに送る。
正しい「認可コード」であれば、「アクセストークン」「リフレッシュトークン」を受け取ることができる。

「リフレッシュトークン」は期限切れの「アクセストークン」を更新するときに使う。
詳細は後述「4. アクセストークンの更新」を見てね。

ちなみに「認可コード」の有効期限は短めで、仕様では10分以下推奨となっている。
期限切れの場合、再度認可を行うことになってしまう。

認可後の「アクセストークン」の取得はお早めに。

3. リソースアクセス

f:id:hacolab:20200522172931p:plain

リソースへのアクセスは簡単。

リソースサーバーに目的の操作リクエストと一緒に「アクセストークン」を送ればいい。

リソースサーバーは、「アクセストークン」の期限が有効なことや、リクエストが許可されたスコープ内であることを確認する。

問題なければ、リクエストされた操作を実行してレスポンスを返す。

補足) HTTPヘッダの参考例

ちなみに仕様では、リクエスト時のHTTPヘッダの例は以下のようになっている。
Bearerの後に「アクセストークン」を含めればいいっぽい。かんたん。

  GET /resource/1 HTTP/1.1
  Host: example.com
  Authorization: Bearer mF_9.B5f-4.1JqM

あくまで参考例なので、実際は各サービスの仕様を確認してねと。

4. アクセストークンの更新

f:id:hacolab:20200522172935p:plain

「アクセストークン」には有効期限がある。(Googleでは1時間っぽい)

期限が切れていると、リクエストは拒否されてリソースにはアクセスできない。
そんなときはトークンエンドポイントに「リフレッシュトークン」を送る。
そうすれば、新しい「アクセストークン」を受け取ることができる。

ただし「リフレッシュトークン」は仕様としてはオプション扱い。
対応有無は各サービスの仕様を確認しよう。

補足) Googleのリフレッシュトークン無効化条件

ちなみに、Googleは「リフレッシュトークン」に対応している。

Googleの場合、下記条件成立時に「リフレッシュトークン」が無効化されるっぽい。
無効になったときは、再度認可から行う必要があるかと。

  • ユーザーが認可を取り消した場合
  • リフレッシュトークンが6ヶ月間未使用の場合
  • 認証パスワードを変更し、スコープにGmailが含まれていた場合
  • リフレッシュトークンの最大数を超えた場合
    • 各クライアントのユーザーごとに50個まで? エイゴヨクワカラナイ
      • There is currently a limit of 50 refresh tokens per user account per client.
    • 普通はきっと超えないけど、開発者はテスト時に注意してねとのこと

developers.google.com

さいごに

以上がOAuth2.0(認可コードによる認可)の基本的な流れになる。

僕は全体の流れと、認可手続きの具体的な流れをイメージできるまで少し時間がかかった。

なので今回は、Webブラウザを予め登場人物に加え、画面1枚に収まるくらいの図を描いてみた。
スマホで見ると文字がちょっと小さいけど。

こんな記事でも、どこかの誰かの理解の助けになったのなら嬉しい。


それにしても、ネットの海にはOAuth2.0の説明記事が溢れかえっている。
日本語の記事も多くて、僕もたくさんお世話になった。

しかしいったいこれまで、似たような説明記事がどれだけ量産されてきたのだろう。

歴史は繰り返す。

そして今日も、オースの歴史が、また1ページ・・・

備考

  • 発音は『オーオース』が一般的っぽい
  • OAuth2.0の仕様発行は2012年と割と古い
  • OAuth2.0とOAuth1.0は別物っぽい
  • OAuth2.0を拡張したOpenID Connectなるものがあるっぽい

参考