#353 OAuth with Doorkeeper pro
Doorkeeper makes it easy to create an OAuth 2 provider. This episode also shows how to setup OmniAuth as an OAuth client and use the oauth2 gem to communicate with an API.
- Download:
- source codeProject Files in Zip (153 KB)
- mp4Full Size H.264 Video (45 MB)
- m4vSmaller H.264 Video (22 MB)
- webmFull Size VP8 Video (26.9 MB)
- ogvFull Size Theora Video (46.9 MB)
Resources
terminal
rails g doorkeeper:install rake db:migrate gem install oauth2 irb -r oauth2
irb
callback = "http://localhost:3001/auth/todo/callback" app_id = "70b18783971c5405907241c1b45616a26c704dd6406cf1c6743ab61c4615eb00" secret = "1dbd541132ca2bdeb9fe83b41d24490b2be445c30fd1856e5914f6d343c4a71b" client = OAuth2::Client.new(app_id, secret, site: "http://localhost:3000/") client.auth_code.authorize_url(redirect_uri: callback) access = client.auth_code.get_token('b77df49142317a6a42ea12412d2065c949c9e01ca3c9d72a478f34f153a88678', redirect_uri: callback) access.get("/api/tasks").parsed access.post("/api/tasks", params: {task: {name: "test oauth"}}) access.get("/api/user").parsed
config/application.rb
config.active_record.whitelist_attributes = false
Gemfile
gem 'doorkeeper'
config/initializers/doorkeeper.rb
Doorkeeper.configure do resource_owner_authenticator do |routes| User.find_by_id(session[:user_id]) || redirect_to(routes.login_url(return_to: request.fullpath)) end admin_authenticator do |routes| session[:user_id] == 1 || redirect_to(routes.login_url(return_to: request.fullpath)) end end
controllers/api/v1/base_controller.rb
module Api module V1 class BaseController < ApplicationController private def current_user if doorkeeper_token @current_user ||= User.find(doorkeeper_token.resource_owner_id) end end end end end
controllers/api/v1/tasks_controller.rb
module Api module V1 class TasksController < BaseController doorkeeper_for :all respond_to :json def index respond_with current_user.tasks end def create respond_with current_user.tasks.create(params[:task]) end end end end
controllers/api/v1/users_controller.rb
module Api module V1 class UsersController < BaseController doorkeeper_for :all respond_to :json def show respond_with current_user.as_json(except: :password_digest) end end end end
OmniAuth Client
Gemfile
gem 'omniauth-oauth2'
lib/omniauth/strategies/todo.rb
module OmniAuth module Strategies class Todo < OmniAuth::Strategies::OAuth2 option :name, :todo option :client_options, { site: "http://localhost:3000", authorize_path: "/oauth/authorize" } uid do raw_info["id"] end info do {name: raw_info["name"]} end def raw_info @raw_info ||= access_token.get('/api/user').parsed end end end end
config/initializers/omniauth.rb
require File.expand_path('lib/omniauth/strategies/todo', Rails.root) Rails.application.config.middleware.use OmniAuth::Builder do provider :todo, ENV["OAUTH_ID"], ENV["OAUTH_SECRET"] end
application_controller.rb
rescue_from OAuth2::Error do |exception| if exception.response.status == 401 session[:user_id] = nil session[:access_token] = nil redirect_to root_url, alert: "Access token expired, try signing in again." end end private def oauth_client @oauth_client ||= OAuth2::Client.new(ENV["OAUTH_ID"], ENV["OAUTH_SECRET"], site: "http://localhost:3000") end def access_token if session[:access_token] @access_token ||= OAuth2::AccessToken.new(oauth_client, session[:access_token]) end end
tasks_controller.rb
def index @tasks = access_token.get("/api/tasks").parsed if access_token end def create access_token.post("/api/tasks", params: {task: {name: params[:name]}}) redirect_to root_url end