omniauthを読んでみる


version: v1.6.1
requestを捌いてる部分と、その先の処理部分を少し読んでみる.

omniauth, oauth自体についての説明は省略する.

entry point

strategyの宣言

OmniAuth::Builder class gives you an easy way to specify multiple strategies.

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :developer unless Rails.env.production?
  provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
end

開発中のアプリケーション内でstorategyを宣言するときは, OmniAuth::Builder#provider でかく.

lib/omniauth/builder.rb

L47-59
def provider(klass, *args, &block)
  # ...
  begin
    # omniauth-xxx gem の読み込み
    middleware = OmniAuth::Strategies.const_get(OmniAuth::Utils.camelize(klass.to_s).to_s)
  rescue NameError
    raise(LoadError.new("Could not find matching strategy for #{klass.inspect}. You may 
  need to install an additional gem (such as omniauth-#{klass})."))
  end
end

args.last.is_a?(Hash) ? args.push(options.merge(args.pop)) : args.push(options)
# rack middleware の生成
use middleware, *args, &block

OminAuth::Builder#provider は omniauth-xxx gem を読み込んで rack middleware を生成

Rack middleware

lib/omniauth/strategy.rb

rack middleware なので call から
https://github.com/omniauth/omniauth/blob/master/lib/omniauth/strategy.rb#L175-L190

L175-190
def call!(env)
  # ...
  return mock_call!(env) if OmniAuth.config.test_mode
  return options_call if on_auth_path? && options_request?
  return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
  return callback_call if on_callback_path?
  return other_phase if respond_to?(:other_phase)
  @app.call(env)
end

各フェーズのリクエストをdispatchしてる
mock_call とか options_call は本質から少しそれるので省略.
request_callcallback_call を見てみる

request_call

L200-220
def request_call # rubocop:disable CyclomaticComplexity, MethodLength, PerceivedComplexity
  # ...
  if options.form.respond_to?(:call)
    log :info, 'Rendering form from supplied Rack endpoint.'
    options.form.call(env)
  elsif options.form
    log :info, 'Rendering form from underlying application.'
    call_app!
  else
    if request.params['origin']
      env['rack.session']['omniauth.origin'] = request.params['origin']
    elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/)
      env['rack.session']['omniauth.origin'] = env['HTTP_REFERER']
    end
    request_phase
  end
end

request_phase

抽象メソッド
https://github.com/omniauth/omniauth/blob/v1.6.1/lib/omniauth/strategy.rb#L313-L318

# @abstract This method is called when the user is on the request path. You should
# perform any information gathering you need to be able to authenticate
# the user in this phase.
def request_phase
   raise(NotImplementedError)
end

omniauth-oauth2でoverwriteしてる
https://github.com/intridea/omniauth-oauth2/blob/464fcef6c0a5f1a7526b9701cec37f342ce57ae3/lib/omniauth/strategies/oauth2.rb#L47-L49

def request_phase
  redirect client.auth_code.authorize_url({:redirect_uri => callback_url}.merge(authorize_params))
end

認証urlに飛ばしてredirect_urlに戻ってくる

callback_call

https://github.com/omniauth/omniauth/blob/v1.6.1/lib/omniauth/strategy.rb#L222-L231 -> callback_phase -> call_app!

def call_app!(env = @env)
  @app.call(env)
end

サービスからのcallbackを受け取ってアプリケーションに戻す


かんそう

かなりさらっとしてるからいつかもうちょいちゃんとよみたい