Dockerコンテナへflow.run_local_serverをリダイレクトする方法(Google OAuth)
突然のエラー
2023年9月。久々にDockerコンテナ上のアプリからYouTube Data APIを触ってみると、2022年(?)までつかえていたPythonコードがエラー。
AttributeError: 'InstalledAppFlow' object has no attribute 'run_console'
run_consoleはコード実行の認可にかかわるメソッド。dir関数でしらべてみると、たしかにInstalledAppFlowオブジェクトにはrun_console属性がなく、実行できなくなった模様。
コード実行前に下記ライブラリの更新をしていたので、これが原因と判断。
- google-auth
- google-auth-httplib2
- google-auth-oauthlib
原因追及
これまで使えていたメソッドがエラーを出すだけじゃなく、それ自体がなくなってしまうというのはけっこうな異常事態な気がしたので調査。
同じような問題にぶちあたった人は海外含めているようで、いくつかの質問サイトで議論されていた。
結論としては、下記のセキュリティ強化によるものだろうと。時期的にも合致。
公式にrun_consoleは使えなくなったから存在自体なくしてしまったと。いうわけで、ライブラリのバージョンをダウングレードするとか、ソースコードをちょこっといじるといったハックは使えないと判断。
リダイレクト
run_consoleの代わりは一択で、run_local_serverを選ばざるを得ない。が、run_consoleを使っていた理由はrun_local_serverによる認可プロセスがうまくいかなかったからだ。
run_local_serverはブラウザ上での操作後、リダイレクトしてアプリにフローを引き継ぐ。しかし、Docker上のアプリではリダイレクト先の指定方法がよくわからないのだ。
この点はやはり日本でも海外でも話題になっている。どうすればうまくいくのか?と。
現時点での答えは下記にあった。
かなり息の長いIssueで、2020年に開始されて、2023年まで断続的に議論が進行している。
要点は2点。
- コンテナ起動時に-p 8080:8080のオプションをつけろ
- flow.run_local_server(bind_addr="0.0.0.0")と引数を設定しろ
以上。
すこし詳しく
-p 8080:8080
下記サイトによれば、run_local_serverは引数にportがあって、8080がデフォルトだ。
google-auth-oauthlib.readthedocs.io
なので、ポートフォワードでdockerコンテナの内と外をつないでやればいい。
もし8080ポート以外を設定したければ、引数としてport=xxxxと明示すればいい(はず)。
bind_addr="0.0.0.0"
run_local_serverの引数にbind_addr(またはhost?)を設定するとリダイレクト先が指定できる。
デフォルトが"localhost"だから、dockerを使わない場合はこれでうまくいくらしい。
dockerを使いたければ"0.0.0.0"を指定する。
イメージ
run_local_serverを実行すると、docker内にサーバーが立ち上がる。このサーバーは認可プロセスの完了を待ち受ける。
認可プロセス自体はdockerの外(ブラウザ上)で進めるから、完了後はリダイレクトでこのdocker内サーバーに伝えなければならない。
伝えるためにどこで待ち受け中かを指定したいのだが、dockerの外から内へはlocalhost("127.0.0.1")では伝わらない。
"0.0.0.0:8080"みたいに指定してやる必要がある。