svenfuchs-devise_oauth2_authenticatable 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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