authlogic-connect 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +145 -0
  3. data/Rakefile +69 -0
  4. data/init.rb +1 -0
  5. data/lib/authlogic_connect.rb +71 -0
  6. data/lib/authlogic_connect/common.rb +9 -0
  7. data/lib/authlogic_connect/common/session.rb +27 -0
  8. data/lib/authlogic_connect/common/user.rb +40 -0
  9. data/lib/authlogic_connect/common/variables.rb +21 -0
  10. data/lib/authlogic_connect/oauth.rb +11 -0
  11. data/lib/authlogic_connect/oauth/helper.rb +16 -0
  12. data/lib/authlogic_connect/oauth/process.rb +82 -0
  13. data/lib/authlogic_connect/oauth/session.rb +72 -0
  14. data/lib/authlogic_connect/oauth/tokens/delicious_token.rb +12 -0
  15. data/lib/authlogic_connect/oauth/tokens/facebook_token.rb +19 -0
  16. data/lib/authlogic_connect/oauth/tokens/get_satisfaction_token.rb +14 -0
  17. data/lib/authlogic_connect/oauth/tokens/google_token.rb +38 -0
  18. data/lib/authlogic_connect/oauth/tokens/myspace_token.rb +14 -0
  19. data/lib/authlogic_connect/oauth/tokens/oauth_token.rb +48 -0
  20. data/lib/authlogic_connect/oauth/tokens/opensocial_token.rb +0 -0
  21. data/lib/authlogic_connect/oauth/tokens/photobucket_token.rb +13 -0
  22. data/lib/authlogic_connect/oauth/tokens/smug_mug_token.rb +14 -0
  23. data/lib/authlogic_connect/oauth/tokens/twitter_token.rb +11 -0
  24. data/lib/authlogic_connect/oauth/tokens/vimeo_token.rb +13 -0
  25. data/lib/authlogic_connect/oauth/tokens/yahoo_token.rb +20 -0
  26. data/lib/authlogic_connect/oauth/user.rb +81 -0
  27. data/lib/authlogic_connect/oauth/variables.rb +34 -0
  28. data/lib/authlogic_connect/openid.rb +8 -0
  29. data/lib/authlogic_connect/openid/session.rb +125 -0
  30. data/lib/authlogic_connect/openid/tokens/aol_token.rb +0 -0
  31. data/lib/authlogic_connect/openid/tokens/blogger_token.rb +0 -0
  32. data/lib/authlogic_connect/openid/tokens/flickr_token.rb +0 -0
  33. data/lib/authlogic_connect/openid/tokens/my_openid_token.rb +0 -0
  34. data/lib/authlogic_connect/openid/tokens/openid_token.rb +3 -0
  35. data/lib/authlogic_connect/openid/user.rb +93 -0
  36. data/lib/authlogic_connect/openid/variables.rb +5 -0
  37. data/lib/oauth_callback_filter.rb +12 -0
  38. data/lib/token.rb +37 -0
  39. data/rails/init.rb +17 -0
  40. 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