各種APIのtoken認証でFirebsaeのJWTを利用する。
before_action :confirm_token
class Token
def self.decode_firebase_token(token)
options = {
algorithm: 'RS256',
iss: "https://securetoken.google.com/project-id",
verify_iss: true,
aud: "project-id", # 各々の環境で
verify_aud: true,
verify_iat: true,
}
payload, _ = JWT.decode(token, nil, true, options) do |header|
cert = fetch_certificates[header['kid']]
if cert.present?
OpenSSL::X509::Certificate.new(cert).public_key
else
nil
end
end
payload
end
private
def self.fetch_certificates
cached = Rails.cache.read(CERTS_CACHE_KEY)
return cached if cached.present?
res = Net::HTTP.get_response(URI(CERTS_URI))
raise 'Fetch certificates error' unless res.is_a?(Net::HTTPSuccess)
body = JSON.parse(res.body)
expires_at = Time.zone.parse(res.header['expires'])
Rails.cache.write(CERTS_CACHE_KEY, body, expires_in: expires_at - Time.current)
body
end
end
これをActionController::APIで実行できるようにした
class ApiController < ActionController::API
include ActionController::HttpAuthentication::Token::ControllerMethods
rescue_from StandardError, with: :render_error
# login用
def authenticate_user
authenticate_or_request_with_http_token do |token, options|
@user = User.find_by_token(token) if token
if @user.present?
session[:user_token] = token
render 'login', formats: 'json', handlers: 'jbuilder'
end
end
end
# ユーザーのtoken確認
def confirm_token
authenticate_or_request_with_http_token do |token, options|
payload = Token.decode_firebase_token(token)
@user = User.find_by_uid(payload['user_id'])
return true if @user.present?
end
end
decodeに成功すると以下のようなデータが取得できる
[4] pry(main)> Token.decode_firebase_token(token)
{"name"=>"田中 太郎",
"picture"=>
"https://lh3.googleusercontent.com/a-/AOh14Gjur08Fo658PaLa7ayODJjhp2wlxuTJTnhB5IRE=s96-c",
"iss"=>"https://securetoken.google.com/test-application",
"aud"=>"test-application",
"auth_time"=>1602738540,
"user_id"=>"zQf3Rjnlg9eGGNhCjy9faEkHFKC3",
"sub"=>"zQf3Rjnlg9eGGNhCjy9faEkHFKC3",
"iat"=>1602738541,
"exp"=>1602742141,
"email_verified"=>true,
"firebase"=>
{"identities"=>
{"google.com"=>["107844820690293321413"],
"sign_in_provider"=>"google.com"}}
=> {"name"=>"田中 太郎",
"picture"=>"https://lh3.googleusercontent.com/a-/AOh14Gjur08Fo658PaLa7ayODJjhp2wlxuTJTnhB5IRE=s96-c",
"iss"=>"https://securetoken.google.com/dev-friendly",
"aud"=>"test-application",
"auth_time"=>1602738540,
"user_id"=>"zQf3Rjnlg9eGGNhCjy9faEkHFKC3",
"sub"=>"zQf3Rjnlg9eGGNhCjy9faEkHFKC3",
"iat"=>1602738541,
"exp"=>1602742141,
"email_verified"=>true,
"firebase"=>{"identities"=>{"google.com"=>["107844820690293321413"], "email"=>["
[email protected]"]}, "sign_in_provider"=>"google.com"}}
[参考]
https://satococoa.hatenablog.com/entry/2018/10/05/210933