DRYな備忘録

Don't Repeat Yourself.

ElectronデスクトップアプリによるGoogleのOAuth2クライアント実装

目的

  • 僕が、ElectronデスクトップアプリによるOAuthプロセスを知る

うるせえ動くもん見せろ

はい。

github.com

ゴール

  • 手元のElectronアプリで、ログインユーザ(この場合、僕自身)のAPIトークンで、GoogleのなんらかのAPIが叩ける
    • ← 登録したアプリ下でわざわざ作成したAPIトークンではないのがミソ

本稿でやらないこと

  • OAuthとはなにかのもっとわかりやすいやつ(こんど別エントリで書きたい)
  • 得られたAPI Tokenの永続保存(electron-json-storageでも使う)
  • Expire時のRefreshの実装 (割愛)

参考資料

目次

  1. デスクトップアプリの設計概要
  2. Google Cloud Console での準備
  3. 最低限のElectronアプリと動線を作成
  4. OAuthクライアントの実装

1. デスクトップアプリの設計概要

こういうものをつくっていきます

f:id:otiai10:20190502154537j:plain
アプリのペーパープロトタイプ(検索の索をまちがえている)

  1. メインのウィンドウでトップ画面が開く
  2. Googleでログイン」的なボタンを押すと別ウィンドウが開く
  3. そこでGoogleにログインして、権限も許可する
  4. 成功するとそのウィンドウは消えて、メインのウィンドウで認証情報が得られる
  5. なんらかのAPI(たとえばYouTube検索API)が使える

みたいな感じで。

2. Google Cloud Console での準備

この手順はもちろん「OAuthプロバイダ」によって操作が異なります

が、

OAuthのプロトコルに則る以上、以下のものを得る・設定する手順には変わりありません

  1. クライアントID(ひつようですね)
  2. クライアントシークレット(ひつようですね)
  3. リダイレクトURI(指定可能だが、登録するひつようがある)

今回は、GoogleをOAuthプロバイダとしてこれをやっていきます。

OAuthプロトコルとしては些末なことなのでここに折りたたんでおきます😉

ⅰ) プロジェクトを作成 - Google Cloud Platform ここに行く

f:id:otiai10:20190502160416p:plain
Google Console 上で新しいプロジェクトを作成(名前なんでもいい)
ⅱ) 使う予定のAPIを有効化 f:id:otiai10:20190502160658p:plain:w320 f:id:otiai10:20190502160725p:plain:w320 f:id:otiai10:20190502160935p:plain:w320
ⅲ) (番外)アプリのAPIトークンで最終目的地を確認
これは番外なんですが、とりあえずYouTubeAPIが叩けることを確認するために、アプリのAPIトークンを作成して、APIが叩けているということをクリアにしておきたい。個人的な性癖です。でもだいじ。こういうのだいじ。 f:id:otiai10:20190502161204p:plain:w320 認証情報、から f:id:otiai10:20190502161537p:plain APIキーのほうを作成して、 f:id:otiai10:20190502161723p:plain で、`curl`で試してみる。 - Search: list  |  YouTube Data API  |  Google Developers
f:id:otiai10:20190502162551p:plain
curlで叩けている(jqとかはノリです)
User Token の場合は、`Authorization Header`に入れる必要があるが、とりあえずこのAPIを叩けることは確認できた。
ⅳ) OAuthクライアントを登録
f:id:otiai10:20190502164911p:plain f:id:otiai10:20190502165218p:plain f:id:otiai10:20190502165414p:plain このように得られました。

はい!と、いうことでね!上記3点を得ることができました!

3. 最低限のElectronアプリと動線を作成

ファイルぜんぶここで晒すのめんどくさいので、そのdiffをおいておきます。

Implement minimum transitions btw windows · otiai10/electron-playground@7085aed · GitHub

ポイントとしては、Electronにはmainプロセスとrendererプロセスがあり、rendererプロセスを起因としてGoogleの認証画面を開かせる流れなので、

  • トップ画面のrendererプロセスは「Googleでログイン」ボタンをきっかけとして、mainプロセスへipcRenderer.send('auth-start')などのメッセージを送る
  • mainプロセスは、ipcMain.on('auth-start', () => ...)などでその認証プロセスをスタートさせる
    • mainプロセスは、あたらしい画面(BrowserWindow)をつくり、Googleのページへ誘導する
    • この画面におけるGoogleとのやりとりが成功したトリガーを検知し、成果物を取得し、この画面を閉じる
    • mainプロセスは、この成果物をトップ画面へ win.send('auth-success', tokens)などで通知する
  • トップ画面は ipcRenderer.on('auth-success, tokens => ...)などでこのメッセージを受け取る
    • トップ画面は、トークンが得られたら、「Googleでログイン」ボタンを非表示にし、かわりに主なコンテンツを表示する

4. OAuthクライアントの実装

ファイルぜんぶここで晒すのめんどくさいので、そのdiffをおいておきます。

Implement OAuth handshake inside the app · otiai10/electron-playground@5f9b18e · GitHub

ポイントをいくつか列挙すると

  • これべんり GitHub - googleapis/google-auth-library-nodejs: 🔑 Google Auth Library for Node.js
  • プロバイダ(Google)画面における認証と権限許可が成功したことをデスクトップアプリでどう検知するか
    • ウェブサービスであれば、Callback URLないしRedirect URIなどと呼ばれるURLに、ブラウザがリダイレクトされる
    • ウェブサービスではない。BrowserWindowfile://から始まるURLにリダイレクトさせることを考えるが、これはプロバイダ側から許可されないことが多い
    • 苦肉の策ではあるが、BrowserWindowpage-title-updatedイベントを使い、Google上の認証認可が成功したことを検知する
  • 検知したら、codeを取得し、これをaccess tokenと交換してもらう
    • これはgoogle-auth-libraryがやってくれる。べんり。
  • あとはこれをrendererプロセスへ通知し、rendererプロセスにおいてYouTube Data API / Searchを叩けばよい

完成したものです

雑感

  • page-title-updatedとかダサすぎか
  • <template>タグべんり
  • fetchべんり
  • async/awaitべんり
  • OAuthについて学んだことをまとめようかと思ったけどちょっとだるいなこれは
  • なんか最近「おちついてやる」という能力が板についてきて、よい
  • GW長い
  • 令和!

DRYな備忘録として