authlogic-connect 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.markdown +145 -0
- data/Rakefile +69 -0
- data/init.rb +1 -0
- data/lib/authlogic_connect.rb +71 -0
- data/lib/authlogic_connect/common.rb +9 -0
- data/lib/authlogic_connect/common/session.rb +27 -0
- data/lib/authlogic_connect/common/user.rb +40 -0
- data/lib/authlogic_connect/common/variables.rb +21 -0
- data/lib/authlogic_connect/oauth.rb +11 -0
- data/lib/authlogic_connect/oauth/helper.rb +16 -0
- data/lib/authlogic_connect/oauth/process.rb +82 -0
- data/lib/authlogic_connect/oauth/session.rb +72 -0
- data/lib/authlogic_connect/oauth/tokens/delicious_token.rb +12 -0
- data/lib/authlogic_connect/oauth/tokens/facebook_token.rb +19 -0
- data/lib/authlogic_connect/oauth/tokens/get_satisfaction_token.rb +14 -0
- data/lib/authlogic_connect/oauth/tokens/google_token.rb +38 -0
- data/lib/authlogic_connect/oauth/tokens/myspace_token.rb +14 -0
- data/lib/authlogic_connect/oauth/tokens/oauth_token.rb +48 -0
- data/lib/authlogic_connect/oauth/tokens/opensocial_token.rb +0 -0
- data/lib/authlogic_connect/oauth/tokens/photobucket_token.rb +13 -0
- data/lib/authlogic_connect/oauth/tokens/smug_mug_token.rb +14 -0
- data/lib/authlogic_connect/oauth/tokens/twitter_token.rb +11 -0
- data/lib/authlogic_connect/oauth/tokens/vimeo_token.rb +13 -0
- data/lib/authlogic_connect/oauth/tokens/yahoo_token.rb +20 -0
- data/lib/authlogic_connect/oauth/user.rb +81 -0
- data/lib/authlogic_connect/oauth/variables.rb +34 -0
- data/lib/authlogic_connect/openid.rb +8 -0
- data/lib/authlogic_connect/openid/session.rb +125 -0
- data/lib/authlogic_connect/openid/tokens/aol_token.rb +0 -0
- data/lib/authlogic_connect/openid/tokens/blogger_token.rb +0 -0
- data/lib/authlogic_connect/openid/tokens/flickr_token.rb +0 -0
- data/lib/authlogic_connect/openid/tokens/my_openid_token.rb +0 -0
- data/lib/authlogic_connect/openid/tokens/openid_token.rb +3 -0
- data/lib/authlogic_connect/openid/user.rb +93 -0
- data/lib/authlogic_connect/openid/variables.rb +5 -0
- data/lib/oauth_callback_filter.rb +12 -0
- data/lib/token.rb +37 -0
- data/rails/init.rb +17 -0
- metadata +175 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Lance Pollard (lancejpollard@gmail.com)
|
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.
|
data/README.markdown
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
# Authlogic Connect
|
2
|
+
|
3
|
+
Authlogic Connect is an extension of the Authlogic library to add extensive Oauth and OpenID support. With Authlogic Connect, it's very easy to allow users to login through any of the 30+ authentication providers out there. You shouldn't be reinventing the wheel anyways.
|
4
|
+
|
5
|
+
There are 3 ways you can allow your users to login with Authlogic Connect:
|
6
|
+
|
7
|
+
1. Clicking an Oauth Provider
|
8
|
+
2. Clicking an OpenID Provider and entering in their username
|
9
|
+
3. Manually typing in a full OpenID address
|
10
|
+
|
11
|
+
All of that is easier than creating a new account and password.
|
12
|
+
|
13
|
+
## Helpful links
|
14
|
+
|
15
|
+
* <b>Authlogic:</b> [http://github.com/binarylogic/authlogic](http://github.com/binarylogic/authlogic)
|
16
|
+
* <b>Authlogic Connect Example Project:</b> [http://github.com/viatropos/authlogic-connect-example](http://github.com/viatropos/authlogic-connect-example)
|
17
|
+
* <b>Live example with Twitter and Facebook using Rails 3:</b> [http://authlogic-connect.heroku.com](http://authlogic-connect.heroku.com)
|
18
|
+
|
19
|
+
## Supported Providers
|
20
|
+
|
21
|
+
Lists of all known providers here:
|
22
|
+
|
23
|
+
- [Oauth Providers](http://wiki.oauth.net/ServiceProviders)
|
24
|
+
- [OpenID Providers](http://en.wikipedia.org/wiki/List_of_OpenID_providers)
|
25
|
+
|
26
|
+
### Oauth
|
27
|
+
|
28
|
+
- Twitter
|
29
|
+
- Facebook
|
30
|
+
- Google
|
31
|
+
|
32
|
+
### OpenID
|
33
|
+
|
34
|
+
- MyOpenID
|
35
|
+
|
36
|
+
## Install and use
|
37
|
+
|
38
|
+
### 1. Install Authlogic and setup your application
|
39
|
+
|
40
|
+
sudo gem install authlogic
|
41
|
+
|
42
|
+
### 2. Install OAuth and Authlogic Connect
|
43
|
+
|
44
|
+
sudo gem install oauth
|
45
|
+
sudo gem install authlogic-connect
|
46
|
+
|
47
|
+
Now add the gem dependencies in your config:
|
48
|
+
|
49
|
+
config.gem "json"
|
50
|
+
config.gem "authlogic"
|
51
|
+
config.gem "oauth"
|
52
|
+
config.gem "oauth2"
|
53
|
+
config.gem "authlogic-connect", :lib => "authlogic_connect"
|
54
|
+
|
55
|
+
### 3. Add the Migrations
|
56
|
+
|
57
|
+
If you are starting from scratch (and you don't even have a User model yet), create the migrations using this command.
|
58
|
+
|
59
|
+
script/generate authlogic_connect_migration
|
60
|
+
|
61
|
+
Otherwise, add this migration
|
62
|
+
|
63
|
+
class AddAuthlogicConnectMigration < ActiveRecord::Migration
|
64
|
+
def self.up
|
65
|
+
add_column :users, :oauth_token, :string
|
66
|
+
add_column :users, :oauth_secret, :string
|
67
|
+
add_index :users, :oauth_token
|
68
|
+
|
69
|
+
change_column :users, :login, :string, :default => nil, :null => true
|
70
|
+
change_column :users, :crypted_password, :string, :default => nil, :null => true
|
71
|
+
change_column :users, :password_salt, :string, :default => nil, :null => true
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.down
|
75
|
+
remove_column :users, :oauth_token
|
76
|
+
remove_column :users, :oauth_secret
|
77
|
+
|
78
|
+
[:login, :crypted_password, :password_salt].each do |field|
|
79
|
+
User.all(:conditions => "#{field} is NULL").each { |user| user.update_attribute(field, "") if user.send(field).nil? }
|
80
|
+
change_column :users, field, :string, :default => "", :null => false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
### 4. Make sure you save your objects properly
|
86
|
+
|
87
|
+
Because of the redirects involved in Oauth and OpenID, you MUST pass a block to the `save` method in your UsersController and UserSessionsController:
|
88
|
+
|
89
|
+
@user_session.save do |result|
|
90
|
+
if result
|
91
|
+
flash[:notice] # "Login successful!"
|
92
|
+
redirect_back_or_default account_url
|
93
|
+
else
|
94
|
+
render :action => :new
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
You should save your `@user` objects this way as well, because you also want the user to authenticate with OAuth.
|
99
|
+
|
100
|
+
If we don't use the block, we will get a DoubleRender error. This lets us skip that entire block and send the user along their way without any problems.
|
101
|
+
|
102
|
+
### 5. Create Custom Tokens (if they don't already exist)
|
103
|
+
|
104
|
+
Here's an example of the FacebookToken for Oauth
|
105
|
+
|
106
|
+
class FacebookToken < OauthToken
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
### 6. Add login and register buttons to your views
|
111
|
+
|
112
|
+
<%# oauth_register_button :value => "Register with Twitter" %>
|
113
|
+
<%# oauth_login_button :value => "Login with Twitter" %>
|
114
|
+
|
115
|
+
That's it! The rest is taken care of for you.
|
116
|
+
|
117
|
+
## The Flow
|
118
|
+
|
119
|
+
- Controller calls `save`
|
120
|
+
- Save checks to see what type of authentication we're going to use
|
121
|
+
- methods called `authenticating_with_x?` sees if its service is in use
|
122
|
+
- called twice, once before, and once after, redirect
|
123
|
+
- it does this by checking if the session and parameters have certain variables defined.
|
124
|
+
- Save calls `save_with_x`, which either:
|
125
|
+
- performs the initial redirect, or
|
126
|
+
- on response from the service, retrieves attributes and saves the user
|
127
|
+
- If first round (hasn't yet redirected):
|
128
|
+
- Saves important data into the session
|
129
|
+
- Specifies callback url based on controller name and action
|
130
|
+
- Redirects to remote service
|
131
|
+
- User clicks "accept!"
|
132
|
+
- Redirects back to callback url
|
133
|
+
- If second round (redirect callback url):
|
134
|
+
- Still processing service (`authenticating_with_oauth?` for example)
|
135
|
+
- Instantiates new User, Session, or Token, or all 3 if they are brand new
|
136
|
+
- Validates User and Session
|
137
|
+
- You don't want to validate any password/email if you're using these services,
|
138
|
+
so they are all skipped
|
139
|
+
- Need to validate keys
|
140
|
+
- Save user
|
141
|
+
- Finish block, render page
|
142
|
+
|
143
|
+
## Tests
|
144
|
+
|
145
|
+
This has no tests! I had to build this in a weekend and am not fluent with Shoulda, which I'd like to use. One of these days when I can breathe.
|
data/Rakefile
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require "rake/rdoctask"
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
# http://docs.rubygems.org/read/chapter/20
|
6
|
+
spec = Gem::Specification.new do |s|
|
7
|
+
s.name = "authlogic-connect"
|
8
|
+
s.author = "Lance Pollard"
|
9
|
+
s.version = "0.0.1"
|
10
|
+
s.summary = "Authlogic Connect: Let your app use all of Oauth and OpenID"
|
11
|
+
s.homepage = "http://github.com/viatropos/authlogic-connect"
|
12
|
+
s.email = "lancejpollard@gmail.com"
|
13
|
+
s.description = "Let your app use all of Oauth and OpenID"
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.rubyforge_project = "authlogic-connect"
|
16
|
+
s.platform = Gem::Platform::RUBY
|
17
|
+
s.files = %w(README.markdown Rakefile init.rb MIT-LICENSE) + Dir["{lib,rails,test}/**/*"] - Dir["test/tmp"]
|
18
|
+
s.require_path = "lib"
|
19
|
+
s.add_dependency("activesupport", ">= 2.1.2")
|
20
|
+
s.add_dependency("activerecord", ">= 2.1.2")
|
21
|
+
s.add_dependency("authlogic")
|
22
|
+
s.add_dependency("oauth")
|
23
|
+
s.add_dependency("json")
|
24
|
+
s.add_dependency("oauth2") # facebook only
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Create .gemspec file (useful for github)"
|
28
|
+
task :gemspec do
|
29
|
+
File.open("pkg/#{spec.name}.gemspec", "w") do |f|
|
30
|
+
f.puts spec.to_ruby
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Build the gem into the current directory"
|
35
|
+
task :gem => :gemspec do
|
36
|
+
`gem build pkg/#{spec.name}.gemspec`
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Publish gem to rubygems"
|
40
|
+
task :publish => [:package] do
|
41
|
+
`gem push pkg/#{spec.name}-#{spec.version}.gem`
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Print a list of the files to be put into the gem"
|
45
|
+
task :manifest do
|
46
|
+
File.open("Manifest", "w") do |f|
|
47
|
+
spec.files.each do |file|
|
48
|
+
f.puts file
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
54
|
+
pkg.gem_spec = spec
|
55
|
+
pkg.package_dir = "pkg"
|
56
|
+
end
|
57
|
+
|
58
|
+
desc "Install the gem locally"
|
59
|
+
task :install => [:package] do
|
60
|
+
sh %{sudo gem install pkg/#{spec.name}-#{spec.version} --no-ri --no-rdoc}
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "Generate the rdoc"
|
64
|
+
Rake::RDocTask.new do |rdoc|
|
65
|
+
files = ["README.markdown", "lib/**/*.rb"]
|
66
|
+
rdoc.rdoc_files.add(files)
|
67
|
+
rdoc.main = "README.markdown"
|
68
|
+
rdoc.title = spec.summary
|
69
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
File.dirname(__FILE__) + "/rails/init.rb"
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'authlogic'
|
3
|
+
require 'oauth'
|
4
|
+
require 'oauth2'
|
5
|
+
|
6
|
+
class Hash
|
7
|
+
def recursively_symbolize_keys!
|
8
|
+
self.symbolize_keys!
|
9
|
+
self.values.each do |v|
|
10
|
+
if v.is_a? Hash
|
11
|
+
v.recursively_symbolize_keys!
|
12
|
+
elsif v.is_a? Array
|
13
|
+
v.recursively_symbolize_keys!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Array
|
21
|
+
def recursively_symbolize_keys!
|
22
|
+
self.each do |item|
|
23
|
+
if item.is_a? Hash
|
24
|
+
item.recursively_symbolize_keys!
|
25
|
+
elsif item.is_a? Array
|
26
|
+
item.recursively_symbolize_keys!
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module AuthlogicConnect
|
33
|
+
VERSION = "0.0.1"
|
34
|
+
|
35
|
+
class << self
|
36
|
+
|
37
|
+
attr_accessor :config
|
38
|
+
|
39
|
+
def config=(value)
|
40
|
+
value.recursively_symbolize_keys!
|
41
|
+
@config = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def key(path)
|
45
|
+
result = self.config
|
46
|
+
path.to_s.split(".").each { |node| result = result[node.to_sym] if result }
|
47
|
+
result
|
48
|
+
end
|
49
|
+
|
50
|
+
def credentials(service)
|
51
|
+
key("services.#{service.to_s}")
|
52
|
+
end
|
53
|
+
|
54
|
+
def include?(service)
|
55
|
+
!credentials(service).nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
def token(key)
|
59
|
+
throw Error unless AuthlogicConnect.include?(key) and !key.to_s.empty?
|
60
|
+
"#{key.to_s.camelcase}Token".constantize
|
61
|
+
end
|
62
|
+
|
63
|
+
def consumer(key)
|
64
|
+
token(key).consumer
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
require File.dirname(__FILE__) + "/authlogic_connect/openid"
|
70
|
+
require File.dirname(__FILE__) + "/authlogic_connect/oauth"
|
71
|
+
require File.dirname(__FILE__) + "/authlogic_connect/common"
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module AuthlogicConnect::Common
|
2
|
+
end
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + "/common/variables"
|
5
|
+
require File.dirname(__FILE__) + "/common/user"
|
6
|
+
require File.dirname(__FILE__) + "/common/session"
|
7
|
+
|
8
|
+
ActiveRecord::Base.send(:include, AuthlogicConnect::Common::User)
|
9
|
+
Authlogic::Session::Base.send(:include, AuthlogicConnect::Common::Session)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module AuthlogicConnect::Common
|
2
|
+
module Session
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
include Variables
|
7
|
+
include InstanceMethods
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
|
13
|
+
# core save method coordinating how to save the session
|
14
|
+
def save(&block)
|
15
|
+
block_destroyed = false
|
16
|
+
if authenticating_with_openid?
|
17
|
+
block_destroyed = save_with_openid(&block)
|
18
|
+
elsif authenticating_with_oauth?
|
19
|
+
block_destroyed = save_with_oauth(&block)
|
20
|
+
end
|
21
|
+
block = nil if block_destroyed
|
22
|
+
super(&block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module AuthlogicConnect::Common
|
2
|
+
module User
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
add_acts_as_authentic_module(Variables, :prepend)
|
7
|
+
add_acts_as_authentic_module(InstanceMethods, :append)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
|
13
|
+
# core save method coordinating how to save the user
|
14
|
+
def save(perform_validation = true, &block)
|
15
|
+
status = true
|
16
|
+
if authenticating_with_openid?
|
17
|
+
status = save_with_openid(perform_validation, &block)
|
18
|
+
elsif authenticating_with_oauth?
|
19
|
+
status = save_with_oauth(perform_validation, &block)
|
20
|
+
end
|
21
|
+
if status
|
22
|
+
result = super
|
23
|
+
yield(result) if block_given?
|
24
|
+
result
|
25
|
+
end
|
26
|
+
status
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate_password_with_oauth?
|
30
|
+
!using_openid? && super
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_password_with_openid?
|
34
|
+
!using_oauth? && super
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module AuthlogicConnect::Common
|
2
|
+
module Variables
|
3
|
+
|
4
|
+
def auth_controller
|
5
|
+
is_auth_session? ? controller : session_class.controller
|
6
|
+
end
|
7
|
+
|
8
|
+
def auth_session
|
9
|
+
auth_controller.session
|
10
|
+
end
|
11
|
+
|
12
|
+
def auth_params
|
13
|
+
auth_controller.params
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_auth_session?
|
17
|
+
self.is_a?(Authlogic::Session::Base)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module AuthlogicConnect::Oauth
|
2
|
+
end
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + "/oauth/process"
|
5
|
+
require File.dirname(__FILE__) + "/oauth/user"
|
6
|
+
require File.dirname(__FILE__) + "/oauth/session"
|
7
|
+
require File.dirname(__FILE__) + "/oauth/helper"
|
8
|
+
|
9
|
+
ActiveRecord::Base.send(:include, AuthlogicConnect::Oauth::User)
|
10
|
+
Authlogic::Session::Base.send(:include, AuthlogicConnect::Oauth::Session)
|
11
|
+
ActionController::Base.helper AuthlogicConnect::Oauth::Helper
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module AuthlogicConnect::Oauth
|
2
|
+
module Helper
|
3
|
+
def oauth_register_button(options = {})
|
4
|
+
oauth_button('register_with_oauth', options)
|
5
|
+
end
|
6
|
+
|
7
|
+
def oauth_login_button(options = {})
|
8
|
+
oauth_button('login_with_oauth', options)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def oauth_button(name, options = {})
|
13
|
+
"<input type='submit' value='#{options[:value]}' name='#{name}' id='user_submit' class='#{options[:class]}'/>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|