Node-RED の OAuth2 で refresh token が再起動で消えてしまう件

環境

Node-RED v0.19.5

TL;DL

Node-RED は credential の値の永続化をデプロイのタイミングでしか行わない。 そのため、いくつかの OAuth2 のプラグインは Node-RED を再起動したタイミングで refresh token を忘れてしまうため、再度 OAuth2 の設定をしなおす必要がある。 該当の Issue は https://github.com/node-red/node-red/issues/1055

node-red-contrib-fitbit-token

私は Fitbit の OAuth2 の access token を expire なしで取れるノードを自作している。

https://github.com/mallowlabs/node-red-contrib-fitbit-token

f:id:mallowlabs:20190114122407p:plain

このノードで access token を取得して、FItbit API を叩くことで、Mackerel に心拍数を送ったり、Slack に送って体重を通知したりしている。

この Node が Node-RED を再起動すると、refresh token が invalid になってしまい、再度ログインが必要なるという問題に悩まされていた。

Node-RED のソースを読む

Node-RED のソースを読むと、credential の 永続化はワークフローのデプロイのタイミングでしか行われていないことがわかった。 つまり refresh token を更新した結果は、メモリ上でしか保存されないので、当然 Node-RED を再起動すると refresh token が失われて、access token を refresh できなくなる。

その知識をもとに、GitHub を見るとたしかに Provide a way to programmatically save Credentials nodes (OAUTH) #1055 という issue があった。 どうやら既知の問題なので今後に期待ということがわかった。

解決策

Node-RED の credential API を使っている限り、永続化はできないので、refresh token のみ別のストレージに保存する必要がある。 私は Node-RED を IBM Blumix 上で動かしているので、 Cloudant DB に保存することにした。

対応した diff がこちら

https://github.com/mallowlabs/node-red-contrib-fitbit-token/commit/8cc70027cc2ec6e5e356b0d2f1e65149fcba4cbd?w=1

これで IBM Blumix 上で動作させることが必須になる代わりに、 Node-RED を再起動しても Fitbit の再ログインが求められることはなくなった。

まとめ

Node-RED の OAuth2 を扱うノードが再起動によって refresh token を忘れてしまうという事実はあまり知られていないと感じたので、記事にしてみた。 これを知らずに自分の書いたコードがどこか間違っていると思い続けて調査に無限の時間を費やしたのでこの記事で誰かが救われると嬉しい。