From b3846b1fb8bf78d400e2e98c0520dfe944b3b7c8 Mon Sep 17 00:00:00 2001 From: Corey Donohoe Date: Thu, 3 Jun 2010 10:05:44 -0700 Subject: [PATCH] break out the oauth2 stuff into a class so i can use it in the sinatra gem too --- Gemfile | 2 +- lib/warden-github.rb | 1 + lib/warden-github/proxy.rb | 33 +++++++++++++++++++++++++++++++++ lib/warden-github/strategy.rb | 31 +++++++++++++++++++------------ lib/warden-github/user.rb | 6 ++++-- spec/oauth_spec.rb | 3 ++- spec/proxy_spec.rb | 32 ++++++++++++++++++++++++++++++++ 7 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 lib/warden-github/proxy.rb create mode 100644 spec/proxy_spec.rb diff --git a/Gemfile b/Gemfile index 5a970b9..f8aa5a3 100644 --- a/Gemfile +++ b/Gemfile @@ -14,7 +14,7 @@ group :test do gem 'webrat', '~>0.7.0' gem 'bundler', '~>0.9.25' gem 'randexp', '>=0.1.4' - gem 'addressable', '~>2.1.2' + gem 'addressable', '~>2.1.2', :require => 'addressable/uri' gem 'rack-test', '~>0.5.3', :require => 'rack/test' end diff --git a/lib/warden-github.rb b/lib/warden-github.rb index ffbe072..647b5a6 100644 --- a/lib/warden-github.rb +++ b/lib/warden-github.rb @@ -9,5 +9,6 @@ class GithubMisconfiguredError < StandardError; end end require 'warden-github/user' +require 'warden-github/proxy' require 'warden-github/version' require 'warden-github/strategy' diff --git a/lib/warden-github/proxy.rb b/lib/warden-github/proxy.rb new file mode 100644 index 0000000..775dea5 --- /dev/null +++ b/lib/warden-github/proxy.rb @@ -0,0 +1,33 @@ +module Warden + module Github + module Oauth + class Proxy + def initialize(client_id, secret, callback_url) + @client_id, @secret, @callback_url = client_id, secret, callback_url + end + + def client + @client ||= OAuth2::Client.new(@client_id, @secret, + :site => 'https://github.com', + :authorize_path => '/login/oauth/authorize', + :access_token_path => '/login/oauth/access_token') + end + + def access_token_for(code) + web_server.get_access_token(code, :redirect_uri => @callback_url) + end + + def authorize_url + web_server.authorize_url( + :scope => 'email,offline_access', + :redirect_uri => @callback_url + ) + end + + def web_server + client.web_server + end + end + end + end +end diff --git a/lib/warden-github/strategy.rb b/lib/warden-github/strategy.rb index c97a711..86a1961 100644 --- a/lib/warden-github/strategy.rb +++ b/lib/warden-github/strategy.rb @@ -8,28 +8,35 @@ def params def authenticate! if params['code'] begin - access_token = oauth_client.web_server.get_access_token(params['code'], :redirect_uri => callback_url) + access_token = access_token_for(params['code']) user = JSON.parse(access_token.get('/api/v2/json/user/show')) success!(Warden::Github::Oauth::User.new(user['user'], access_token.token)) rescue OAuth2::HTTPError - %(

Outdated ?code=#{params[:code]}:

#{$!}

Retry

) + %(

Outdated ?code=#{params['code']}:

#{$!}

Retry

) end else - url = oauth_client.web_server.authorize_url( - :scope => 'email,offline_access', - :redirect_uri => callback_url - ) - throw(:halt, [ 302, {'Location' => url}, [ ]]) + throw(:halt, [ 302, {'Location' => authorize_url}, [ ]]) end end private + def oauth_client - OAuth2::Client.new(env['warden'].config[:github_client_id], - env['warden'].config[:github_secret], - :site => 'https://github.com', - :authorize_path => '/login/oauth/authorize', - :access_token_path => '/login/oauth/access_token') + oauth_proxy.client + end + + def authorize_url + oauth_proxy.authorize_url + end + + def access_token_for(code) + oauth_proxy.access_token_for(code) + end + + def oauth_proxy + @oauth_proxy ||= Warden::Github::Oauth::Proxy.new(env['warden'].config[:github_client_id], + env['warden'].config[:github_secret], + callback_url) end def callback_url diff --git a/lib/warden-github/user.rb b/lib/warden-github/user.rb index c4b41cb..c9831f7 100644 --- a/lib/warden-github/user.rb +++ b/lib/warden-github/user.rb @@ -2,8 +2,6 @@ module Warden module Github module Oauth class User < Struct.new(:attribs, :token) - extend Forwardable - def name attribs['name'] end @@ -11,6 +9,10 @@ def name def email attribs['email'] end + + def company + attribs['company'] + end end end end diff --git a/spec/oauth_spec.rb b/spec/oauth_spec.rb index 4eaf872..20cfd0e 100644 --- a/spec/oauth_spec.rb +++ b/spec/oauth_spec.rb @@ -5,8 +5,9 @@ response = get "/" uri = Addressable::URI.parse(response.headers["Location"]) - uri.should_not be_nil + uri.scheme.should eql('https') + uri.host.should eql('github.com') params = uri.query_values params['type'].should eql('web_server') diff --git a/spec/proxy_spec.rb b/spec/proxy_spec.rb new file mode 100644 index 0000000..0a88a6d --- /dev/null +++ b/spec/proxy_spec.rb @@ -0,0 +1,32 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "Warden::Github::Oauth::Proxy" do + before(:all) do + sha = Digest::SHA1.hexdigest(Time.now.to_s) + @proxy = Warden::Github::Oauth::Proxy.new(sha[0..19], sha[0..39], + 'http://example.org/auth/github/callback') + end + + it "returns an authorize url" do + uri = Addressable::URI.parse(@proxy.authorize_url) + + uri.scheme.should eql('https') + uri.host.should eql('github.com') + + params = uri.query_values + params['type'].should eql('web_server') + params['scope'].should eql('email,offline_access') + params['client_id'].should match(/\w{20}/) + params['redirect_uri'].should eql('http://example.org/auth/github/callback') + end + + it "has a client object" do + @proxy.client.should_not be_nil + end + + it "returns access tokens" do + pending "this hits the network" do + lambda { @proxy.access_token_for(/\w{20}/.gen) }.should_not raise_error + end + end +end