概要
Patreon の API を使うには OAuth で取得したアクセストークンが必要になります
アクセストークンは 31 日 (2678400 秒) で expire になってしまうのでそのタイミングで再度認証が必要になります
Patreon にはアクセストークンをリフレッシュする仕組みがあり refresh_token
を使うことでアクセストークンを更新することができます
今回はリフレッシュのやり方の紹介とアクセストークンの管理方法を考えたいと思います
環境
- macOS 10.14.3
- Ruby 2.5.1p57
- patreon 0.5.0
- Redis 4.0.9
リフレッシュするコード
アクセストークンをリフレッシュだけなら以下の通り簡単です
oauth_client = Patreon::OAuth.new(client_id, client_secret)
tokens = oauth_client.refresh_token(refresh_token, redirect_uri)
tokens['access_token']
これで OK です
client_id
, client_secret
は Patreon でクライアントアプリを登録した際に発行される定数です
変更されることはありません
問題になるのは refresh_token
です
アクセストークンをリフレッシュすると、この refresh_token
も更新されます
refresh_token
も定数であれば何も考えず上記のコードを呼ぶだけなのですが refresh_toke
も更新されるのでそうは行かなくなります
今回は Redis を使ってトークンの管理と更新の仕組みを考え見ます
Redis を使ったトークン管理のサンプルコード
準備とサンプルコードの全体は以下の通りです
bundle init
vim Gemfile
gem "patreon"
gem "redis"
bundle install --path vendor
vim app.rb
require 'patreon'
require 'redis'
require 'json'
require 'date'
client_id = 'xxxxxxx'
client_secret = 'xxxxxxx'
redirect_uri = 'http://localhost:9292/'
cli = Redis.new
tokens = JSON.parse(cli.get('tokens'))
token = tokens['access_token']
register = tokens['register_date']
if register.nil? || (Date.today - Date.parse(register)).to_i > 30
refresh_token = tokens['refresh_token']
oauth_client = Patreon::OAuth.new(client_id, client_secret)
tokens = oauth_client.refresh_token(refresh_token, redirect_uri)
tokens.store('register_date', Date.today)
cli.set('tokens', tokens.to_json)
token = tokens['access_token']
end
puts token
解説
大まかな流れとしては
- Redis にトークンのキャッシュがあるかチェック
- ない場合は新規でトークン取得
- ある場合は
register_date
をチェック - すでに 30 日を越えている場合はトークンをリフレッシュ
- キャッシュがあり期限を越えていない場合はキャッシュにあるトークンを取得
という流れになります
おそらくアクセストークンをクライアント側で管理する場合はだいたいこんな流れになると思います
Patreon から tokens を取得すると以下のような JSON が取得できます
{
"access_token": "single use token",
"refresh_token": "single use token",
"expires_in": "token lifetime duration",
"scope": "token scopes",
"token_type": "Bearer"
}
expires_in
にはトークンの期限が切れるまでの秒が格納されています
取得後すぐだと「2678400」が格納されています
残り時間なので随時減らさないとダメですがクライアント側ではそうも行かないので代わりに register_date
を登録しています
register_date
が 30 日以前であればリフレッシュトークン呼びます
またそもそも登録されていない場合もリフレッシュトークンを呼びます
今回の方法の事前に refresh_token
を Redis に格納しておく必要があります
一度登録すれば FLUSHALL などをしない限り再度登録する必要はないのですが、この方法だと始めだけは必ず必要になります
クライアントの管理画面でリフレッシュトークンが取得できるのでそこで取得して以下のような感じでリフレッシュトークンを Redis に登録します
set tokens '{"refresh_token":"xxxxxxx"}'
これであとは放置しておけばトークンの更新がスクリプトを呼ばれるたびに自動で行われるので管理の必要がなくなります
改善点
やはり refresh_token
を最初に Redis に格納するのが面倒だなと思います
単純にコード内で変数として持っておいてもいいですが、アプリが再起動すると消えるのでキャッシュ側をあくまでも優先するようにしましょう
素直に新規でトークンを取得すればいいじゃないかと思うかもしれません
新規で取得する場合は get_tokens
という関数を呼び出すのですが、この場合は当然 OAuth 認証になるのでブラウザを立ち上げ認証ページで認証しなければなりません
またリダイレクト URL も必要になるので Web アプリを用意しなければいけなくなります
なので refresh_token
関数を呼ぶことでトークンの取得と再取得も行っています
refresh_token
はブラウザを開いて認証するがありません
最後に
Patreon のアクセストークンをクライアント側で管理する方法を考えてみました
Redis を使うので、それだけで面倒が増えるので微妙な気がしますが一番てっとり早いかなと思います
例えばローカルのファイルなどでもいいのですが、そうなるとアプリがスケールすることができません
アクセストークンが expire したら手動で更新する方法でもいいかと思いますが、それも面倒なので Redis で管理したほうがいいかなという感じです
他にいい方法があれば教えていただきたいです
0 件のコメント:
コメントを投稿