Skip to content

Instantly share code, notes, and snippets.

@shime
Last active December 23, 2015 20:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shime/6691184 to your computer and use it in GitHub Desktop.
Save shime/6691184 to your computer and use it in GitHub Desktop.
DCI implementation of OAuth with Github in Sinatra
require "sinatra"
get "/oauth/github" do
OAuthingWithGithub.start(self)
end
get "/oauth/github/callback" do
OAuthingWithGithub.finish(self)
end
# in contexts/oauthing_with_github.rb
class OAuthingWithGithub < AppContext
def self.start(app)
new(app).start
end
def self.finish(app)
new(app).finish
end
def start
unless session[:github_access_token]
redirect OAuth::Github.authorize_url(config["github_key"],
config["github_secret"], nil)
end
redirect "/"
end
def finish
token = OAuth::Github.token(config["github_key"],
config["github_secret"],
params[:code])
session[:github_access_token] = token
user = User.new
user.extend(Roles::GitHubber)
user.find_or_create_from_github(token)
redirect "/"
end
def config
app.send(:env_from_config)
end
private :config
module Roles
module GitHubber
def find_or_create_from_github(token)
user = User.first_or_initialize(email: fetch_email(token))
user.github_access_token = token
user.save!
end
private
def fetch_email(token)
OAuth::Github::Client.get_email(token)
end
end
end
end
# in contexts/app_context.rb
class AppContext
attr_reader :app
def initialize(app)
@app = app
end
private
def session
app.session
end
def params
app.params
end
def current_user
app.current_user
end
def redirect(*attrs)
app.redirect(*attrs)
end
end
# in oauth.rb
#
# a wrapper for OAuth client
require "oauth2"
require "httparty"
require "json"
module OAuth
module Github
def self.github_client(client_id, client_secret)
OAuth2::Client.new(client_id, client_secret,
:authorize_url => 'https://github.com/login/oauth/authorize',
:token_url => 'https://github.com/login/oauth/access_token')
end
def self.authorize_url(client_id, client_secret, scope = "repo,gist")
self.github_client(client_id, client_secret).auth_code.authorize_url(:scope => scope)
end
def self.token(client_id, client_secret, code)
self.github_client(client_id, client_secret).auth_code.get_token(code).token
end
module Client
def self.get_email(token)
response = HTTParty.get("https://api.github.com/user", :query => {:access_token => token})
body = JSON.parse(response.body)
body["email"]
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment