Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Federating Oauth In Ruby

Federating Oauth In Ruby

Presentation given at Railsconf 2015 about a sane approach to federating Oauth in Rails by Lance Gleason of Polyglot Programming

Lance Gleason

April 21, 2015
Tweet

More Decks by Lance Gleason

Other Decks in Technology

Transcript

  1. Introductions

    View full-size slide

  2. Twitter @lgleasain
    Github lgleasain
    www.lancegleason.com
    www.polyglotprogrammincinc.com
    [email protected]

    View full-size slide

  3. http://www.polyglotprogramminginc.com/purr-
    programming-2-0/

    View full-size slide

  4. What
    Are
    Services

    View full-size slide

  5. What is
    Federation

    View full-size slide

  6. Single
    Sign On

    View full-size slide

  7. Authorization and
    Authentication

    View full-size slide

  8. Authentication
    /Authorization

    View full-size slide

  9. Single
    Point of
    Success

    View full-size slide

  10. Bad For
    Mixed
    Use

    View full-size slide

  11. Mostly
    Read Only
    Content

    View full-size slide

  12. Half Requires
    Authenication/
    Authorizaztion

    View full-size slide

  13. Needs To
    Scale

    View full-size slide

  14. gem 'doorkeeper'
    rails generate doorkeeper:install
    rails generate doorkeeper:migration
    rake db:migrate

    View full-size slide

  15. Every
    Instance
    Has To Have
    a Datastore

    View full-size slide

  16. resource_owner_authenticator do
    @user = env[:clearance].current_user
    unless @user
    session[:return_to] = request.fullpath
    redirect_to(routes.sign_in_url)
    end
    @user
    end

    View full-size slide

  17. resource_owner_authenticator do
    #could be a call to a central
    authentication service.
    @user = env[:clearance].current_user
    unless @user
    session[:return_to] = request.fullpath
    redirect_to(routes.sign_in_url)
    end
    @user
    end

    View full-size slide

  18. module OmniAuth
    module Strategies
    autoload :VulcanService, Rails.root.join('lib', 'strategies',
    'vulcan_service')
    autoload :KlingonManager, Rails.root.join('lib', 'strategies',
    'klingon_manager')
    autoload :Bieber, Rails.root.join('lib', 'strategies', 'beiber')
    end
    end
    Rails.application.config.middleware.use OmniAuth::Builder do
    provider :Vulcan, "#{APP_CONFIG['vulcan_url']}/login"
    provider :KlingonService, "#{APP_CONFIG['klingon_service_url']}/login"
    provider :BeiberManager, "#{APP_CONFIG['beiber_manager_url']}/login"
    provider :developer
    end

    View full-size slide

  19. require 'strategies/common'
    module OmniAuth
    module Strategies
    class VulcanService
    include Common
    include OmniAuth::Strategy
    args [:authentication_url]
    def request_phase
    # some request code to authenticate
    # live long and prosper
    end
    #todo: add checks to make sure the values returned here are valid
    def callback_phase
    request = Rack::Request.new env
    cookies = request.cookies
    response = Rack::Response.new
    cookie_monster = VulcanCookieMonster.new cookies
    common_vulcan_callback cookie_monster: cookie_monster, response: response,
    cookies: cookies
    end
    private
    def strategy_id
    'comcast_tve'
    end
    end
    end
    end

    View full-size slide

  20. class ApplicationController < ActionController::API
    def check_authorization
    authorization = request.headers[‘Authorization']
    if authorization
    party_response = HTTParty.get("#{APP_CONFIG['doorkeeper_service_url']}:#{ENV[DOORKEEPER_SERVICE_PORT']}/
    check_key.json",
    query: {'signature' => Hancock.sign, 'oauth_token' => authorization})
    parsed_response = party_response.parsed_response
    if parsed_response['user_key']
    expires = Marshal.load(parsed_response['expires_at'].force_encoding('UTF-8')).to_json
    @user = { 'user_id' => parsed_response['user_id'], 'user_key' => parsed_response['user_key'],
    'email' => parsed_response['email'], 'expires_at' => expires }
    else
    response.status = 401
    render json: {authorized: false} and return
    end
    end
    else
    response.status = 401
    render json: {authorized: false} and return
    end
    end
    end

    View full-size slide

  21. Single
    Point of
    Success

    View full-size slide

  22. Cached
    Delegation

    View full-size slide

  23. require 'redis'
    class ApplicationController < ActionController::API
    def check_authorization
    authorization = request.headers['Authorization']
    if authorization
    redis = Redis.new(:host => ENV['REDIS_HOST'], :port => ENV['REDIS_PORT'])
    redis_user = redis.get(authorization)
    if redis_user != nil
    @user = JSON.parse(redis_user)
    expires_at = DateTime.parse(@user['expires_at'])
    end
    if !@user or expires_at < DateTime.now
    party_response =
    HTTParty.get("#{APP_CONFIG['doorkeeper_service_url']}:#{ENV['DOORKEEPER_SERVICE_PORT']}/check_key.json",
    query: {'signature' => Hancock.sign, 'oauth_token' => authorization})
    parsed_response = party_response.parsed_response
    if parsed_response['user_key']
    expires = Marshal.load(parsed_response['expires_at'].force_encoding('UTF-8')).to_json
    @user = { 'user_id' => parsed_response['user_id'], 'user_key' => parsed_response['user_key'],
    'email' => parsed_response['email'], 'expires_at' => expires }
    redis.set authorization, @user.to_json
    else
    response.status = 401
    render json: {authorized: false} and return
    end
    end
    else
    response.status = 401
    render json: {authorized: false} and return
    end
    end
    end

    View full-size slide

  24. It’s a
    Standard

    View full-size slide

  25. Roll Your
    Own Is
    Less Secure

    View full-size slide

  26. JWT’s Are
    Roll Your
    Own

    View full-size slide

  27. Default
    Doorkeeper
    is Too

    View full-size slide

  28. Twitter @lgleasain
    Github lgleasain
    www.lancegleason.com
    www.polyglotprogrammincinc.com
    [email protected]

    View full-size slide