svenfuchs-devise_oauth2_authenticatable 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 bhbryant
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,145 @@
1
+ = devise_oauth2_authenticatable
2
+
3
+ == This fork works with Devise 1.1 + Rails 3
4
+
5
+
6
+ ==Quick tutorial for Devise 1.1 + Rails 3 + devise_oauth2_authenticatable
7
+
8
+ Set up your Facebook app at http://developers.facebook.com/setup/
9
+
10
+ Create the Rails app:
11
+ rails new YOUR_APP
12
+ cd YOUR_APP
13
+
14
+ Add the following lines to your Gemfile:
15
+ gem "oauth2"
16
+ gem "devise", :git => "git://github.com/plataformatec/devise.git"
17
+ gem "devise_oauth2_authenticatable", :git => "git://github.com/jerryluk/devise_oauth2_authenticatable.git"
18
+
19
+ Run the following commands:
20
+ bundle install
21
+ rails g devise:install
22
+ rails g devise User
23
+ rails g devise:oauth2_authenticatable APP_ID SECRET
24
+
25
+ Your DeviseCreateUsers migration should look like this:
26
+ class DeviseCreateUsers < ActiveRecord::Migration
27
+ def self.up
28
+ create_table(:users) do |t|
29
+ t.database_authenticatable
30
+ t.rememberable
31
+ t.trackable
32
+ t.oauth2_authenticatable
33
+ t.string :email
34
+
35
+ t.timestamps
36
+ end
37
+
38
+ add_index :users, :oauth2_uid, :unique => true
39
+ end
40
+
41
+ def self.down
42
+ drop_table :users
43
+ end
44
+ end
45
+
46
+ Make sure user.rb has the following line:
47
+ devise :oauth2_authenticatable, ...
48
+
49
+ Add this to your application_controller.rb:
50
+ before_filter :authenticate_user!
51
+
52
+ Add the sign in/sign out links to your applications.html.erb:
53
+ <% if user_signed_in? %>
54
+ <%= link_to "Sign out", destroy_user_session_path %>
55
+ <% else %>
56
+ <%= link_to_oauth2 "Sign In with Facebook" %>
57
+ <% end %>
58
+
59
+ The usual stuffs:
60
+ rm public/index.html
61
+ rake db:create
62
+ rake db:migrate
63
+ rails s
64
+
65
+ Navigate your browser to http://localhost:3000, there are many things to fix but you are mostly there!
66
+
67
+ ==
68
+ This is the basic framework for an OAuth2 gem for Devise.
69
+
70
+ It currently works with FacebookGraph, to get started begin by registering a new application at
71
+
72
+ http://developers.facebook.com/setup/
73
+
74
+
75
+ A generator is provided for creating your oauth yml file
76
+
77
+ rails g devise:oauth2_authenticatable
78
+
79
+ Ex:
80
+
81
+ rails g devise:oauth2_authenticatable APP_ID SECRET 'email,offline_access,publish_stream'
82
+
83
+
84
+ for more details
85
+
86
+ http://developers.facebook.com/docs/authentication/
87
+
88
+
89
+
90
+ It's based on the devise facebook gem provided by grimen
91
+
92
+ http://github.com/grimen/devise_facebook_connectable
93
+
94
+
95
+
96
+ And uses the example provided in OAuth2 library provided by mbleigh
97
+
98
+ http://github.com/intridea/oauth2
99
+
100
+
101
+ DB Migration :
102
+
103
+ add_column :users, :oauth2_uid, :integer, :limit => 8 # BIGINT unsigned / 64-bit int
104
+ add_column :users, :oauth2_token, :string, :limit => 149 # [128][1][20] chars
105
+ add_index :users, :oauth2_uid, :unique => true
106
+
107
+
108
+
109
+ Note:
110
+
111
+ A little souce of confusion when working with Facebook Graph
112
+
113
+ The api key and secret key are no the same a Facebook Connect/the old API.
114
+
115
+ The client id should be your application id and the client_key, should be your API key (not secret key)
116
+
117
+
118
+ == TODO
119
+
120
+ Write tests :
121
+ Currently no tests have been written. My bad.
122
+
123
+ Add Javascript / token based auth :
124
+ Facebook graph offes a complete authorization solution using javascript and a returned authentication token. Adding optional support for this would complete the Facebook Graph authentication interface.
125
+
126
+ Generalize for OAuth2:
127
+ Add support for other OAuth2 services. Wrote this specifically for facebook graph, althought configuration arugments should be generalized to support other interfaces.
128
+
129
+
130
+
131
+ Description goes here.
132
+
133
+ == Note on Patches/Pull Requests
134
+
135
+ * Fork the project.
136
+ * Make your feature addition or bug fix.
137
+ * Add tests for it. This is important so I don't break it in a
138
+ future version unintentionally.
139
+ * Commit, do not mess with rakefile, version, or history.
140
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
141
+ * Send me a pull request. Bonus points for topic branches.
142
+
143
+ == Copyright
144
+
145
+ Copyright (c) 2010 bhbryant. See LICENSE for details.
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "devise_oauth2_authenticatable"
8
+ gem.summary = %Q{Implements OAuth2 for Devise }
9
+ gem.description = %Q{Implements OAuth2 for Devise, specifically integrating with facebook Graph}
10
+ gem.email = "benjamin@bryantmarkowsky.com"
11
+ gem.homepage = "http://github.com/bhbryant/devise_oauth2_authenticatable"
12
+ gem.authors = ["bhbryant"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+
15
+ gem.add_dependency'devise', '>= 1.0.0'
16
+ gem.add_dependency "oauth2"
17
+ gem.add_dependency "json"
18
+
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'spec/rake/spectask'
27
+ Spec::Rake::SpecTask.new(:spec) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :spec => :check_dependencies
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "devise_oauth2_authenticatable #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,74 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{svenfuchs-devise_oauth2_authenticatable}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["bhbryant"]
12
+ s.date = %q{2010-06-13}
13
+ s.description = %q{Implements OAuth2 for Devise}
14
+ s.email = %q{benjamin@bryantmarkowsky.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "devise_oauth2_authenticatable.gemspec",
27
+ "lib/devise_oauth2_authenticatable.rb",
28
+ "lib/devise_oauth2_authenticatable/locales/en.yml",
29
+ "lib/devise_oauth2_authenticatable/rails.rb",
30
+ "lib/devise_oauth2_authenticatable/model.rb",
31
+ "lib/devise_oauth2_authenticatable/routes.rb",
32
+ "lib/devise_oauth2_authenticatable/schema.rb",
33
+ "lib/devise_oauth2_authenticatable/strategy.rb",
34
+ "lib/devise_oauth2_authenticatable/view_helpers.rb",
35
+ "lib/generators/devise/oauth2_authenticatable/oauth2_authenticatable_generator.rb",
36
+ "lib/generators/devise/oauth2_authenticatable/templates/oauth2.yml",
37
+ "lib/generators/devise/oauth2_authenticatable/USAGE",
38
+ "spec/devise_oauth2_authenticatable_spec.rb",
39
+ "spec/spec.opts",
40
+ "spec/spec_helper.rb"
41
+ ]
42
+ s.homepage = %q{http://github.com/bhbryant/devise_oauth2_authenticatable}
43
+ s.rdoc_options = ["--charset=UTF-8"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.6}
46
+ s.summary = %q{Implements OAuth2 for Devise}
47
+ s.test_files = [
48
+ "spec/devise_oauth2_authenticatable_spec.rb",
49
+ "spec/spec_helper.rb"
50
+ ]
51
+
52
+ if s.respond_to? :specification_version then
53
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
54
+ s.specification_version = 3
55
+
56
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
57
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
58
+ s.add_runtime_dependency(%q<devise>, [">= 1.0.0"])
59
+ s.add_runtime_dependency(%q<oauth2>, [">= 0"])
60
+ s.add_runtime_dependency(%q<json>, [">= 0"])
61
+ else
62
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
63
+ s.add_dependency(%q<devise>, [">= 1.0.0"])
64
+ s.add_dependency(%q<oauth2>, [">= 0"])
65
+ s.add_dependency(%q<json>, [">= 0"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
69
+ s.add_dependency(%q<devise>, [">= 1.0.0"])
70
+ s.add_dependency(%q<oauth2>, [">= 0"])
71
+ s.add_dependency(%q<json>, [">= 0"])
72
+ end
73
+ end
74
+
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+ require 'devise'
3
+ require 'oauth2'
4
+
5
+ require 'devise_oauth2_authenticatable/model'
6
+ require 'devise_oauth2_authenticatable/strategy'
7
+ require 'devise_oauth2_authenticatable/schema'
8
+ require 'devise_oauth2_authenticatable/routes'
9
+ #require 'devise_oauth2_authenticatable/controller_filters'
10
+ require 'devise_oauth2_authenticatable/view_helpers'
11
+ require 'devise_oauth2_authenticatable/rails'
12
+
13
+ module Devise
14
+ # Specifies the name of the database column name used for storing
15
+ # the oauth UID. Useful if this info should be saved in a
16
+ # generic column if different authentication solutions are used.
17
+ mattr_accessor :oauth2_uid_field
18
+ @@oauth2_uid_field = :oauth2_uid
19
+
20
+ # Specifies the name of the database column name used for storing
21
+ # the user Facebook session key. Useful if this info should be saved in a
22
+ # generic column if different authentication solutions are used.
23
+ mattr_accessor :oauth2_token_field
24
+ @@oauth2_token_field = :oauth2_token
25
+
26
+ # Specifies if account should be created if no account exists for
27
+ # a specified Facebook UID or not.
28
+ mattr_accessor :oauth2_auto_create_account
29
+ @@oauth2_auto_create_account = true
30
+
31
+ def self.oauth2_client
32
+ @@oauth2_client ||= OAuth2::Client.new(
33
+ OAUTH2_CONFIG['client_id'],
34
+ OAUTH2_CONFIG['client_secret'],
35
+ :site => OAUTH2_CONFIG['authorization_server'],
36
+ :authorize_path => OAUTH2_CONFIG['authorize_path'],
37
+ :access_token_path => OAUTH2_CONFIG['access_token_path'])
38
+ end
39
+
40
+
41
+ def self.session_sign_in_url(request, mapping)
42
+ url = URI.parse(request.url)
43
+ # url.path = "#{mapping.parsed_path}/#{mapping.path_names[:sign_in]}"
44
+ url.path = "/#{mapping.path}/#{mapping.path_names[:oauth2]}"
45
+ url.query = nil
46
+ url.to_s
47
+ end
48
+
49
+ def self.requested_scope
50
+ @@requested_scope ||= OAUTH2_CONFIG['requested_scope']
51
+ end
52
+
53
+ end
54
+
55
+ # Load core I18n locales: en
56
+ #
57
+ I18n.load_path.unshift File.join(File.dirname(__FILE__), *%w[devise_oauth2_authenticatable locales en.yml])
58
+
59
+ # Add +:facebook_connectable+ strategies to defaults.
60
+ #
61
+ Devise.add_module(:oauth2_authenticatable,
62
+ :strategy => true,
63
+ :controller => :sessions,
64
+ :route => :oauth2,
65
+ :model => 'devise_oauth2_authenticatable/model')
@@ -0,0 +1,9 @@
1
+ en:
2
+ devise:
3
+ sessions:
4
+ oauth2_invalid: "Could not login. Invalid account."
5
+ oauth2_timeout: "OAuth2 session expired., please sign in again to continue."
6
+ oauth2_authenticity_token: "Something went wrong. For security reasons, please sign in again." # Revise this message =)
7
+ oauth2_actions:
8
+ sign_in: "Sign in" # NOTE: Not used for the default Facebook Connect button.
9
+ sign_out: "Sign out"
@@ -0,0 +1,196 @@
1
+ # encoding: utf-8
2
+ require 'devise/models'
3
+
4
+
5
+ module Devise #:nodoc:
6
+ # module OAuth2Authenticatable #:nodoc:
7
+ module Models #:nodoc:
8
+
9
+ # OAuth2 Connectable Module, responsible for validating authenticity of a
10
+ # user and storing credentials while signing in using their OAuth2 account.
11
+ #
12
+ # == Configuration:
13
+ #
14
+ # You can overwrite configuration values by setting in globally in Devise (+Devise.setup+),
15
+ # using devise method, or overwriting the respective instance method.
16
+ #
17
+ # +oauth2_uid_field+ - Defines the name of the OAuth2 user UID database attribute/column.
18
+ #
19
+ # +oauth2_token_field+ - Defines the name of the OAuth2 session key database attribute/column.
20
+ #
21
+ # +oauth2_auto_create_account+ - Speifies if account should automatically be created upon connect
22
+ # if not already exists.
23
+ #
24
+ # == Examples:
25
+ #
26
+ # User.oauth2_connect(:uid => '123456789') # returns authenticated user or nil
27
+ # User.find(1).oauth2_connected? # returns true/false
28
+ #
29
+ module Oauth2Authenticatable
30
+
31
+ def self.included(base) #:nodoc:
32
+ base.class_eval do
33
+ extend ClassMethods
34
+ end
35
+ end
36
+
37
+ # Store OAuth2 Connect account/session credentials.
38
+ #
39
+ def store_oauth2_credentials!(attributes = {})
40
+ self.send(:"#{self.class.oauth2_uid_field}=", attributes[:uid])
41
+ self.send(:"#{self.class.oauth2_token_field}=", attributes[:token])
42
+
43
+ # Confirm without e-mail - if confirmable module is loaded.
44
+ self.skip_confirmation! if self.respond_to?(:skip_confirmation!)
45
+
46
+ # Only populate +email+ field if it's available (e.g. if +authenticable+ module is used).
47
+ self.email = attributes[:email] || '' if self.respond_to?(:email)
48
+
49
+ # Lazy hack: These database fields are required if +authenticable+/+confirmable+
50
+ # module(s) is used. Could be avoided with :null => true for authenticatable
51
+ # migration, but keeping this to avoid unnecessary problems.
52
+ self.password_salt = '' if self.respond_to?(:password_salt)
53
+ self.encrypted_password = '' if self.respond_to?(:encrypted_password)
54
+ end
55
+
56
+ # Checks if OAuth2 Connected.
57
+ #
58
+ def oauth2_connected?
59
+ self.send(:"#{self.class.oauth2_uid_field}").present?
60
+ end
61
+ alias :is_oauth2_connected? :oauth2_connected?
62
+
63
+ # Hook that gets called *before* connect (only at creation). Useful for
64
+ # specifiying additional user info (etc.) from OAuth2.
65
+ #
66
+ # Default: Do nothing.
67
+ #
68
+ # == Examples:
69
+ #
70
+ # # Overridden in OAuth2 Connect:able model, e.g. "User".
71
+ # #
72
+ # def before_oauth2_auto_create(oauth2_user_attributes)
73
+
74
+ # self.profile.first_name = oauth2_user_attributes.first_name
75
+
76
+ #
77
+ # end
78
+ #
79
+ # == For more info:
80
+ #
81
+ # * http://oauth2er.pjkh.com/user/populate
82
+ #
83
+ def on_before_oauth2_auto_create(oauth2_user_attributes)
84
+
85
+ if self.respond_to?(:before_oauth2_auto_create)
86
+ self.send(:before_oauth2_auto_create, oauth2_user_attributes) rescue nil
87
+ end
88
+ end
89
+
90
+ # Hook that gets called *after* a connection (each time). Useful for
91
+ # fetching additional user info (etc.) from OAuth2.
92
+ #
93
+ # Default: Do nothing.
94
+ #
95
+ # == Example:
96
+ #
97
+ # # Overridden in OAuth2 Connect:able model, e.g. "User".
98
+ # #
99
+ # def after_oauth2_connect(oauth2_user_attributes)
100
+ # # See "on_before_oauth2_connect" example.
101
+ # end
102
+ #
103
+ def on_after_oauth2_connect(oauth2_user_attributes)
104
+
105
+ if self.respond_to?(:after_oauth2_connect)
106
+ self.send(:after_oauth2_connect, oauth2_user_attributes) rescue nil
107
+ end
108
+ end
109
+
110
+ # Optional: Store session key.
111
+ #
112
+ def store_session(using_token)
113
+ if self.token != using_token
114
+ self.update_attribute(self.send(:"#{self.class.oauth2_token_field}"), using_token)
115
+ end
116
+ end
117
+
118
+ protected
119
+
120
+ # Passwords are always required if it's a new rechord and no oauth_id exists, or if the password
121
+ # or confirmation are being set somewhere.
122
+ def password_required?
123
+
124
+ ( new_record? && self.send(:"#{self.class.oauth2_uid_field}").nil? ) || !password.nil? || !password_confirmation.nil?
125
+ end
126
+
127
+ module ClassMethods
128
+
129
+ # Configuration params accessible within +Devise.setup+ procedure (in initalizer).
130
+ #
131
+ # == Example:
132
+ #
133
+ # Devise.setup do |config|
134
+ # config.oauth2_uid_field = :oauth2_uid
135
+ # config.oauth2_token_field = :oauth2_token
136
+ # config.oauth2_auto_create_account = true
137
+ # end
138
+ #
139
+ ::Devise::Models.config(self,
140
+ :oauth2_uid_field,
141
+ :oauth2_token_field,
142
+ :oauth2_auto_create_account
143
+ )
144
+
145
+ # Alias don't work for some reason, so...a more Ruby-ish alias
146
+ # for +oauth2_auto_create_account+.
147
+ #
148
+ def oauth2_auto_create_account?
149
+ self.oauth2_auto_create_account
150
+ end
151
+
152
+ # Authenticate a user based on OAuth2 UID.
153
+ #
154
+ def authenticate_with_oauth2(oauth2_id, oauth2_token)
155
+
156
+ # find user and update access token
157
+ returning(self.find_for_oauth2(oauth2_id)) do |user|
158
+ user.update_attributes(:"#{self.oauth2_token_field}" => oauth2_token) unless user.nil?
159
+ end
160
+
161
+ end
162
+
163
+ protected
164
+
165
+
166
+
167
+ # Find first record based on conditions given (OAuth2 UID).
168
+ # Overwrite to add customized conditions, create a join, or maybe use a
169
+ # namedscope to filter records while authenticating.
170
+ #
171
+ # == Example:
172
+ #
173
+ # def self.find_for_oauth2(uid, conditions = {})
174
+ # conditions[:active] = true
175
+ # self.find_by_oauth2_uid(uid, :conditions => conditions)
176
+ # end
177
+ #
178
+ def find_for_oauth2(uid, conditions = {})
179
+ self.send(:"find_by_#{self.oauth2_uid_field}",uid, :conditions => conditions)
180
+ end
181
+
182
+
183
+
184
+ # Contains the logic used in authentication. Overwritten by other devise modules.
185
+ # In the OAuth2 Connect case; nothing fancy required.
186
+ #
187
+ def valid_for_oauth2(resource, attributes)
188
+ true
189
+ end
190
+
191
+ end
192
+
193
+ end
194
+ end
195
+ # end
196
+ end
@@ -0,0 +1,24 @@
1
+ module Devise
2
+ class Engine
3
+ config.after_initialize do
4
+ begin
5
+ config_file = Rails.root.join('config', 'oauth2.yml')
6
+ unless File.exists?(config_file)
7
+ config_file = Rails.root.join('config', 'oauth2_config.yml')
8
+ if File.exists?(config_file)
9
+ puts "Deprecated OAuth2 config file config/oauth2_config.yml. Please use config/oauth.yml instead."
10
+ end
11
+ end
12
+
13
+ Devise::OAUTH2_CONFIG = YAML.load_file(config_file)[Rails.env]
14
+
15
+ unless Devise::OAUTH2_CONFIG['user_attributes_path']
16
+ puts "Your config/oauth2.yml does not seem to contain a user_attributes_path setting. Assuming '/me' for FacebookConnect."
17
+ Devise::OAUTH2_CONFIG['user_attributes_path'] = '/me'
18
+ end
19
+ rescue
20
+ puts "Can't load oauth2.yml. You can generate with rails g devise:oauth2_authenticatable"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ ActionDispatch::Routing::Mapper.class_eval do
2
+ protected
3
+
4
+ def devise_oauth2(mapping, controllers)
5
+ get mapping.path_names[:oauth2], :to => "#{controllers[:sessions]}#create", :as => :"oauth2_#{mapping.name}_session"
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ require 'devise/schema'
3
+
4
+ module Devise #:nodoc:
5
+ module Oauth2Authenticatable #:nodoc:
6
+
7
+ module Schema
8
+
9
+ # Database migration schema for Facebook Connect.
10
+ #
11
+ def oauth2_authenticatable
12
+ apply_devise_schema ::Devise.oauth2_uid_field, Integer, :limit => 8 # BIGINT unsigned / 64-bit int
13
+ apply_devise_schema ::Devise.oauth2_token_field, String, :limit => 149 # [128][1][20] chars
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+
20
+ Devise::Schema.module_eval do
21
+ include ::Devise::Oauth2Authenticatable::Schema
22
+ end
@@ -0,0 +1,100 @@
1
+ # encoding: utf-8
2
+ require 'devise/strategies/base'
3
+
4
+
5
+ module Devise #:nodoc:
6
+ module Oauth2Authenticatable #:nodoc:
7
+ module Strategies #:nodoc:
8
+
9
+ # Default strategy for signing in a user using Facebook Connect (a Facebook account).
10
+ # Redirects to sign_in page if it's not authenticated
11
+ #
12
+ class Oauth2Authenticatable < ::Devise::Strategies::Base
13
+
14
+
15
+
16
+ # Without a oauth session authentication cannot proceed.
17
+ #
18
+ def valid?
19
+
20
+ valid_controller? && valid_params? && mapping.to.respond_to?('authenticate_with_oauth2')
21
+
22
+ end
23
+
24
+ # Authenticate user with OAuth2
25
+ #
26
+ def authenticate!
27
+ klass = mapping.to
28
+ begin
29
+
30
+
31
+ # Verify User Auth code and get access token from auth server: will error on failue
32
+ access_token = Devise::oauth2_client.web_server.get_access_token(
33
+ params[:code], :redirect_uri => Devise::session_sign_in_url(request,mapping)
34
+ )
35
+
36
+ # retrieve user attributes
37
+
38
+ # Get user details from OAuth2 Service
39
+ oauth2_user_attributes = JSON.parse(access_token.get(OAUTH2_CONFIG['user_attributes_path']))
40
+
41
+ user = klass.authenticate_with_oauth2(oauth2_user_attributes['id'], access_token.token)
42
+
43
+
44
+
45
+ if user.present?
46
+ user.on_after_oauth2_connect(oauth2_user_attributes)
47
+ success!(user)
48
+ else
49
+ if klass.oauth2_auto_create_account?
50
+
51
+
52
+
53
+ user = returning(klass.new) do |u|
54
+ u.store_oauth2_credentials!(
55
+ :token => access_token.token,
56
+ :uid => oauth2_user_attributes['id']
57
+ )
58
+ u.on_before_oauth2_auto_create(oauth2_user_attributes)
59
+ end
60
+
61
+ begin
62
+
63
+
64
+ user.save(true)
65
+ user.on_after_oauth2_connect(oauth2_user_attributes)
66
+
67
+
68
+ success!(user)
69
+ rescue
70
+ fail!(:oauth2_invalid)
71
+ end
72
+ else
73
+ fail!(:oauth2_invalid)
74
+ end
75
+ end
76
+
77
+ rescue => e
78
+ fail!(e.message)
79
+ end
80
+ end
81
+
82
+
83
+
84
+
85
+ protected
86
+ def valid_controller?
87
+ # params[:controller] == 'sessions'
88
+ mapping.controllers[:sessions] == params[:controller]
89
+ end
90
+
91
+ def valid_params?
92
+ params[:code].present?
93
+ end
94
+
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ Warden::Strategies.add(:oauth2_authenticatable, Devise::Oauth2Authenticatable::Strategies::Oauth2Authenticatable)
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ require 'devise/mapping'
3
+
4
+ module Devise #:nodoc:
5
+ module Oauth2Authenticatable #:nodoc:
6
+
7
+ # OAuth2 view helpers to easily add the link to the OAuth2 connection popup and also the necessary JS code.
8
+ #
9
+ module Helpers
10
+
11
+ # Creates the link to
12
+ def link_to_oauth2(link_text, options={})
13
+
14
+
15
+ session_sign_in_url = Devise::session_sign_in_url(request,::Devise.mappings[:user])
16
+
17
+ link_to link_text, Devise::oauth2_client.web_server.authorize_url(
18
+ :redirect_uri => session_sign_in_url,
19
+ :scope => Devise::requested_scope
20
+ ), options
21
+ end
22
+
23
+
24
+
25
+ end
26
+ end
27
+ end
28
+
29
+ ::ActionView::Base.send :include, Devise::Oauth2Authenticatable::Helpers
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Generates a OAuth2 config file for your application. All the parameters are optional.
3
+
4
+ Example:
5
+ rails g devise:oauth2_authenticatable APP_ID SECRET 'email,offline_access,publish_stream'
6
+
7
+ This will create:
8
+ config/oauth2_config.yml
@@ -0,0 +1,17 @@
1
+ module Devise
2
+ class Oauth2AuthenticatableGenerator < Rails::Generators::Base
3
+ source_root File.expand_path('../templates', __FILE__)
4
+ argument :client_id, :type => :string, :default => "YOUR_APP_API_ID"
5
+ argument :client_key, :type => :string, :default => "YOUR_APP_SECRET_KEY"
6
+ argument :requested_scope, :type => :string, :default => "email,offline_access,publish_stream"
7
+ argument :auth_server, :type => :string, :default => "https://graph.facebook.com"
8
+ argument :authorize_path, :type => :string, :default => "/oauth/authorize"
9
+ argument :access_token_path, :type => :string, :default => "/oauth/access_token"
10
+ argument :user_attributes_path, :type => :string, :default => "/me"
11
+ desc "Generates a OAuth2 config file for your application. All the parameters are optional."
12
+
13
+ def generate_oauth2_config
14
+ template 'oauth2_config.yml', File.join(*%w[config oauth2.yml])
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ defaults: &defaults
2
+ # Required.
3
+ client_id: <%= client_id %>
4
+ client_secret: <%= client_key %>
5
+ authorization_server: <%= auth_server %>
6
+ requested_scope: <%= requested_scope %>
7
+ authorize_path: <%= authorize_path %>
8
+ access_token_path: <%= access_token_path %>
9
+ user_attributes_path: <%= user_attributes_path %>
10
+
11
+ development:
12
+ <<: *defaults
13
+
14
+ test: &test
15
+ <<: *defaults
16
+
17
+ production: &production
18
+ <<: *defaults
19
+
20
+ # staging:
21
+ # <<: *production
22
+ #
23
+ # cucumber:
24
+ # <<: *test
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "DeviseOauth2Authenticatable" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'devise_oauth2_authenticatable'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: svenfuchs-devise_oauth2_authenticatable
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - bhbryant
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-13 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 13
30
+ segments:
31
+ - 1
32
+ - 2
33
+ - 9
34
+ version: 1.2.9
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: devise
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 23
46
+ segments:
47
+ - 1
48
+ - 0
49
+ - 0
50
+ version: 1.0.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: oauth2
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ type: :runtime
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: json
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ type: :runtime
80
+ version_requirements: *id004
81
+ description: Implements OAuth2 for Devise
82
+ email: benjamin@bryantmarkowsky.com
83
+ executables: []
84
+
85
+ extensions: []
86
+
87
+ extra_rdoc_files:
88
+ - LICENSE
89
+ - README.rdoc
90
+ files:
91
+ - .document
92
+ - .gitignore
93
+ - LICENSE
94
+ - README.rdoc
95
+ - Rakefile
96
+ - VERSION
97
+ - devise_oauth2_authenticatable.gemspec
98
+ - lib/devise_oauth2_authenticatable.rb
99
+ - lib/devise_oauth2_authenticatable/locales/en.yml
100
+ - lib/devise_oauth2_authenticatable/rails.rb
101
+ - lib/devise_oauth2_authenticatable/model.rb
102
+ - lib/devise_oauth2_authenticatable/routes.rb
103
+ - lib/devise_oauth2_authenticatable/schema.rb
104
+ - lib/devise_oauth2_authenticatable/strategy.rb
105
+ - lib/devise_oauth2_authenticatable/view_helpers.rb
106
+ - lib/generators/devise/oauth2_authenticatable/oauth2_authenticatable_generator.rb
107
+ - lib/generators/devise/oauth2_authenticatable/templates/oauth2.yml
108
+ - lib/generators/devise/oauth2_authenticatable/USAGE
109
+ - spec/devise_oauth2_authenticatable_spec.rb
110
+ - spec/spec.opts
111
+ - spec/spec_helper.rb
112
+ has_rdoc: true
113
+ homepage: http://github.com/bhbryant/devise_oauth2_authenticatable
114
+ licenses: []
115
+
116
+ post_install_message:
117
+ rdoc_options:
118
+ - --charset=UTF-8
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 3
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ hash: 3
136
+ segments:
137
+ - 0
138
+ version: "0"
139
+ requirements: []
140
+
141
+ rubyforge_project:
142
+ rubygems_version: 1.3.7
143
+ signing_key:
144
+ specification_version: 3
145
+ summary: Implements OAuth2 for Devise
146
+ test_files:
147
+ - spec/devise_oauth2_authenticatable_spec.rb
148
+ - spec/spec_helper.rb