Skip to content
Browse files

new readme

  • Loading branch information...
1 parent b962107 commit 6209d2a3427f1ef13758fa81ed569269c809a175 Holden Thomas committed Nov 19, 2009
View
22 README.rdoc
@@ -1,36 +1,46 @@
= Authlogic OpenID-Selector Example
-This is an example of how to use Authlogic in combination with the Javascript OpenID-Selector in a Rails app.
+This is an example of how to use Authlogic in combination with the Javascript OpenID-Selector and Facebook authentication thrown in a Rails app.
-Live Example can be found here: http://openid-example.joontos.ch
+Live Example can be found here: http://big-glow-mama.heroku.com
<b>Please check the following pages to find more information about the applications used to build this example:</b>
* Original Authlogic Example App: http://authlogicexample.binarylogic.com
* Authlogic: http://github.com/binarylogic/authlogic
* Authlogic OpenID: http://github.com/binarylogic/authlogic_openid
+* Auto_register version that works http://github.com/gaizka/authlogic_openid
* Javascript OpenID-Selector (based on JQuery): http://code.google.com/p/openid-selector/
+* Facebook integration http://github.com/kalasjocke/authlogic_facebook_connect
+* Inspiration http://github.com/vazqujav/authlogic_openid_selector_example
+
== What does this example app contain?
1. OpenID User registration using Javascript OpenID-Selector.
2. Automatically log users in upon successful OpenID registration, saving his OpenID identifier and (if returned) his email address.
+2b. Auto Registration of users, no registration required for first time Facebook/Google/Yahoo etc.
3. A my account area where the user can view / delete his account.
4. Login/Logout functionality.
5. Automatically store information on the users and their session in the databases. Such as login count, IP address, when they logged in last, and when their last activity occurred.
6. Count how many users are logged in / out in your system.
== Status
-* Fetching email using sreg and ax works now
+* Fetching email using sreg and ax works
* Flickr OpenID doesn't seem to work at all...
+* Facebook works... though logging out and trying to then use an Open ID provider a bit buggy
+* Auto registration works but does not currently capture the email as it does during normal registration? http://stackoverflow.com/questions/1748629/authlogic-autoregister-feature-using-my-options
+
+
== Todo
-* Port Javascript OpenID-Selector to the Prototype JS library.
-* Implement Facebook login into this app (waiting for Authlogic Facebook module :-)).
* Use this application to build a Rails plugin...feel free to help me on this one!
+* Fix auto registration for correct capturing of emails and get rid of registration altogether
+* Replace Open ID registration with simple old school registration for users who don't want to use OpenID at all or facebook, etc.
+* Twitter addition? (OAuth)
== Misc.
-This is my first Github and Git project, so please be patient and give me feedback if anything isn't working as you would expect. :-)
+Some fine tuning is needed.
View
14 app/models/user.rb
@@ -1,14 +1,22 @@
class User < ActiveRecord::Base
+
+ is_gravtastic :email
+
acts_as_authentic do |c|
c.validate_login_field = false
# optional, but if a user registers by openid, he should at least share his email-address with the app
c.validate_email_field = false
# fetch email by ax
c.openid_required_fields = [:email,"http://axschema.org/contact/email"]
#c.openid_required_fields = [:language, "http://axschema.org/pref/language"]
- #c.required_fields = ["http://axschema.org/contact/email"]
- # fetch email by sreg
- #c.optional_fields = ["email"]
+ end
+
+ def before_connect(facebook_session)
+ self.name = facebook_session.user.name
+ self.birthday = facebook_session.user.birthday_date
+ self.about = facebook_session.user.about_me
+ self.locale = facebook_session.user.locale
+ #self.website = facebook_session.user.website
end
private
View
19 app/views/layouts/application.html.erb
@@ -1,18 +1,26 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title><%= controller.controller_name %>: <%= controller.action_name %></title>
- <%= stylesheet_link_tag 'scaffold' %>
+ <%= stylesheet_link_tag 'application', 'scaffold' %>
<%= stylesheet_link_tag 'openid' %>
+ <%= javascript_include_tag :defaults %>
+
<script src="/javascripts/jquery-1.2.6.min.js" type="text/javascript"></script>
+ <script>
+ jQuery.noConflict();
+ </script>
<script src="/javascripts/openid-jquery.js" type="text/javascript"></script>
+
+
+
</head>
<body>
-<span style="float: right; text-align: right;"><%= link_to "Source Code", "http://github.com/vazqujav/authlogic_openid_selector_example" %></span>
+<span style="float: right; text-align: right;"><%= link_to "Source Code", "http://github.com/holden/authlogic_openid_selector_example" %></span>
<h1>Authlogic OpenID-Selector Example App</h1>
<%= pluralize User.logged_in.count, "user" %> currently logged in (<%= pluralize User.all.size, "user" %> registered)<br /> <!-- This based on last_request_at, if they were active < 10 minutes they are logged in -->
<br />
@@ -21,7 +29,7 @@
<% if !current_user %>
<b>Make a choice:</b> <br />
- <%= link_to "Register", new_account_path %> |
+ <%= link_to "<strike>Register</strike>", new_account_path %> |
<%= link_to "Log In", new_user_session_path %>
<% else %>
<%= link_to "My Account", account_path %> |
@@ -31,6 +39,9 @@
<p style="color: green"><%= flash[:notice] %></p>
+<%= fb_connect_javascript_tag %>
+<%= init_fb_connect "XFBML" %>
+
<%= yield %>
<p>
View
6 app/views/user_sessions/new.html.erb
@@ -1,5 +1,5 @@
<script type="text/javascript">
- $(document).ready(function() {
+ jQuery(document).ready(function() {
openid.init('user_session[openid_identifier]');
});
</script>
@@ -18,4 +18,6 @@
<%= submit_tag "Sign-In" %>
</div>
<% end %>
-<% end %>
+<% end %>
+
+<%= authlogic_facebook_login_button %>
View
2 app/views/users/_form.erb
@@ -1,5 +1,5 @@
<script type="text/javascript">
- $(document).ready(function() {
+ jQuery(document).ready(function() {
openid.init('user[openid_identifier]');
});
</script>
View
7 app/views/users/show.html.erb
@@ -1,7 +1,14 @@
+<% if @user.facebook_uid %>
+ <%= fb_profile_pic @user.facebook_uid, :size => :square, :class => 'profile_pic' %>
+<% else %>
+ <%= image_tag @user.gravatar_url %>
+<% end %>
+
<% if @user.openid_identifier.blank? %>
<p>
<b>Login:</b>
<%=h @user.login %>
+ <%=h @user.facebook_uid %>
</p>
<% else %>
<p>
View
3 config/environment.rb
@@ -26,6 +26,9 @@
# config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
# config.gem "aws-s3", :lib => "aws/s3"
config.gem "authlogic"
+ config.gem "facebooker"
+ config.gem 'gravtastic', :version => '>= 2.1.0'
+
#config.gem "authlogic-oid", :lib => "authlogic_openid"
# Only load the plugins named here, in the order given. By default, all plugins
View
49 config/facebooker.yml
@@ -0,0 +1,49 @@
+# The api key, secret key, and canvas page name are required to get started
+# Tunnel configuration is only needed if you are going to use the facebooker:tunnel Rake tasks
+# Your callback url in Facebook should be set to http://public_host:public_port
+# If you're building a Facebook connect site,
+# change the value of set_asset_host_to_callback_url to false
+# To develop for the new profile design, add the following key..
+# api: new
+# remove the key or set it to anything else to use the old facebook design.
+# This should only be necessary until the final version of the new profile is released.
+
+development:
+ api_key: 054f2060bd08b3d45936501ff38544db
+ secret_key: c8cef61589f3cceda946ed1b6fcbc17e
+ canvas_page_name:
+ callback_url: http://localhost:3000/
+ pretty_errors: true
+ set_asset_host_to_callback_url: true
+ tunnel:
+ public_host_username:
+ public_host:
+ public_port: 4007
+ local_port: 3000
+
+test:
+ api_key:
+ secret_key:
+ canvas_page_name:
+ callback_url:
+ set_asset_host_to_callback_url: true
+ tunnel:
+ public_host_username:
+ public_host:
+ public_port: 4007
+ local_port: 3000
+ server_alive_interval: 0
+
+production:
+ api_key: 054f2060bd08b3d45936501ff38544db
+ secret_key: c8cef61589f3cceda946ed1b6fcbc17e
+ canvas_page_name:
+ callback_url: http://localhost:3000/
+ pretty_errors: true
+ set_asset_host_to_callback_url: true
+ tunnel:
+ public_host_username:
+ public_host:
+ public_port: 4007
+ local_port: 3000
+ server_alive_interval: 0
View
4 db/migrate/20081103171327_create_users.rb
@@ -6,8 +6,8 @@ def self.up
t.string :crypted_password
t.string :password_salt
t.string :email
- t.string :openid_identifier, :null => false
- t.string :persistence_token, :null => false
+ t.string :openid_identifier, :null => true
+ t.string :persistence_token, :null => true
t.integer :login_count, :default => 0, :null => false
t.datetime :last_request_at
t.datetime :last_login_at
View
21 db/migrate/20091118070358_add_facebook_column.rb
@@ -0,0 +1,21 @@
+class AddFacebookColumn < ActiveRecord::Migration
+ def self.up
+ add_column :users, :name, :string
+ add_column :users, :facebook_username, :string
+ add_column :users, :facebook_uid, :integer, :limit => 8
+ add_column :users, :birthday, :string
+ add_column :users, :locale, :string
+ add_column :users, :website, :string
+ add_column :users, :about, :text
+ end
+
+ def self.down
+ remove_column :users, :website
+ remove_column :users, :about
+ remove_column :users, :locale
+ remove_column :users, :birthday
+ remove_column :users, :facebook_username
+ remove_column :users, :facebook_uid
+ remove_column :users, :name
+ end
+end
View
1 public/javascripts/application.js
@@ -1,2 +1,3 @@
// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults
+
View
28 public/javascripts/openid-jquery.js
@@ -95,7 +95,7 @@ var providers_small = {
url: 'http://openid.orange.fr/'
}
};
-var providers = $.extend({}, providers_large, providers_small);
+var providers = jQuery.extend({}, providers_large, providers_small);
var openid = {
@@ -110,12 +110,12 @@ var openid = {
init: function(input_id) {
- var openid_btns = $('#openid_btns');
+ var openid_btns = jQuery('#openid_btns');
this.input_id = input_id;
- $('#openid_choice').show();
- $('#openid_input_area').empty();
+ jQuery('#openid_choice').show();
+ jQuery('#openid_input_area').empty();
// add box for each provider
for (id in providers_large) {
@@ -131,7 +131,7 @@ var openid = {
}
}
- $('#openid_form').submit(this.submit);
+ jQuery('#openid_form').submit(this.submit);
var box_id = this.readCookie();
if (box_id) {
@@ -167,7 +167,7 @@ var openid = {
this.setOpenIdUrl(provider['url']);
if (! onload) {
- $('#openid_form').submit();
+ jQuery('#openid_form').submit();
}
}
},
@@ -176,29 +176,29 @@ var openid = {
var url = openid.provider_url;
if (url) {
- url = url.replace('{username}', $('#openid_username').val());
+ url = url.replace('{username}', jQuery('#openid_username').val());
openid.setOpenIdUrl(url);
}
return true;
},
setOpenIdUrl: function (url) {
- var hidden = $('#'+this.input_id);
+ var hidden = jQuery('#'+this.input_id);
if (hidden.length > 0) {
hidden.value = url;
} else {
- $('#openid_form').append('<input type="hidden" id="' + this.input_id + '" name="' + this.input_id + '" value="'+url+'"/>');
+ jQuery('#openid_form').append('<input type="hidden" id="' + this.input_id + '" name="' + this.input_id + '" value="'+url+'"/>');
}
},
highlight: function (box_id) {
// remove previous highlight.
- var highlight = $('#openid_highlight');
+ var highlight = jQuery('#openid_highlight');
if (highlight) {
- highlight.replaceWith($('#openid_highlight a')[0]);
+ highlight.replaceWith(jQuery('#openid_highlight a')[0]);
}
// add new highlight.
- $('.'+box_id).wrap('<div id="openid_highlight"></div>');
+ jQuery('.'+box_id).wrap('<div id="openid_highlight"></div>');
},
setCookie: function (value) {
@@ -220,7 +220,7 @@ var openid = {
},
useInputBox: function (provider) {
- var input_area = $('#openid_input_area');
+ var input_area = jQuery('#openid_input_area');
var html = '';
var id = 'openid_username';
@@ -242,6 +242,6 @@ var openid = {
input_area.empty();
input_area.append(html);
- $('#'+id).focus();
+ jQuery('#'+id).focus();
}
};
View
10 public/xd_receiver.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head>
+ <title>Cross-Domain Receiver Page</title>
+</head>
+<body>
+ <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.debug.js" type="text/javascript"></script>
+</body>
+</html>
View
10 public/xd_receiver_ssl.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head>
+ <title>Cross-Domain Receiver Page</title>
+</head>
+<body>
+ <script src="https://www.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script>
+</body>
+</html>
View
79 vendor/plugins/authlogic_facebook_connect/README.rdoc
@@ -0,0 +1,79 @@
+== Install and use
+
+=== 1. Install the facebooker gem and make Rails use it
+
+ $ sudo gem install facebooker
+
+Make sure that you have setup you config/facebooker.yml to match your facebook application, make you application depended on the facebooker gem
+
+ config.gem "facebooker"
+
+and run the xd_receiver generator to create the cross domain scripting bridge to make it possible for your application to communicate with facebook
+
+ $ script/generate xd_receiver
+
+For more information on the facebooker gem checkout it's readme http://github.com/mmangino/facebooker/tree/master
+
+=== 2. Install the Authlogic Facebook Connect plugin
+
+ $ script/plugin install git://github.com/kalasjocke/authlogic_facebook_connect.git
+
+This plugin should soon be packed inside a gem.
+
+=== 3. Make some changes to your database
+
+ class AddFacebookConnectFieldsToUser < ActiveRecord::Migration
+ def self.up
+ add_column :users, :name, :string
+ add_column :users, :facebook_uid, :integer, :limit => 8
+ end
+
+ def self.down
+ remove_column :users, :facebook_uid
+ remove_column :users, :name
+ end
+ end
+
+=== 4. Make your layout look something like this
+
+The important parts are the facebook html namespace, facebook javascript include and the facebook helper calls to init the facebooker gem.
+
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
+ <head>
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+ <title>Your awsome facebook connected app</title>
+
+ <%= stylesheet_link_tag 'application' %>
+ <%= javascript_include_tag :defaults %>
+
+ <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php" type="text/javascript"></script>
+ </head>
+ <body>
+
+ <p style="color: green"><%= flash[:notice] %></p>
+
+ <%= fb_connect_javascript_tag %>
+ <%= init_fb_connect "XFBML" %>
+
+ <%= yield %>
+
+ </body>
+ </html>
+
+=== 5. Add the Facebook Connect button to your login form
+
+ <%= authlogic_facebook_login_button %>
+
+=== Notes
+
+If you want to save some user data when connecting to facebook you can use the before_connect hook in your user model.
+
+ def before_connect(facebook_session)
+ self.name = facebook_session.user.name
+ end
+
+For more information about what you can get form the facebook_session checkout the Facebooker gem rdoc.
+
View
1 vendor/plugins/authlogic_facebook_connect/init.rb
@@ -0,0 +1 @@
+require 'authlogic_facebook_connect'
View
10 vendor/plugins/authlogic_facebook_connect/lib/authlogic_facebook_connect.rb
@@ -0,0 +1,10 @@
+# require "authlogic_facebook_connect/version"
+require "authlogic_facebook_connect/acts_as_authentic"
+require "authlogic_facebook_connect/session"
+require "authlogic_facebook_connect/helper"
+
+if ActiveRecord::Base.respond_to?(:add_acts_as_authentic_module)
+ ActiveRecord::Base.send(:include, AuthlogicFacebookConnect::ActsAsAuthentic)
+ Authlogic::Session::Base.send(:include, AuthlogicFacebookConnect::Session)
+ ActionController::Base.helper AuthlogicFacebookConnect::Helper
+end
View
20 ...or/plugins/authlogic_facebook_connect/lib/authlogic_facebook_connect/acts_as_authentic.rb
@@ -0,0 +1,20 @@
+module AuthlogicFacebookConnect
+ module ActsAsAuthentic
+ def self.included(klass)
+ klass.class_eval do
+ extend Config
+ add_acts_as_authentic_module(Methods, :prepend)
+ end
+ end
+
+ module Config
+ end
+
+ module Methods
+ def self.included(klass)
+ klass.class_eval do
+ end
+ end
+ end
+ end
+end
View
29 vendor/plugins/authlogic_facebook_connect/lib/authlogic_facebook_connect/helper.rb
@@ -0,0 +1,29 @@
+module AuthlogicFacebookConnect
+ module Helper
+ def authlogic_facebook_login_button(options = {})
+ # TODO: Make this with correct helpers istead of this uggly hack.
+
+ options[:controller] ||= "user_session"
+ options[:js] ||= :prototype
+
+ case options[:js]
+ when :prototype
+ js_selector = "$('connect_to_facebook_form')"
+ when :jquery
+ js_selector = "jQuery('#connect_to_facebook_form')"
+ end
+
+ output = "<form id='connect_to_facebook_form' method='post' action='/#{options[:controller]}'>\n"
+ output << "<input type='hidden' name='authenticity_token' value='#{form_authenticity_token}'/>\n"
+ output << "</form>\n"
+ output << "<script type='text/javascript' charset='utf-8'>\n"
+ output << " function connect_to_facebook() {\n"
+ output << " #{js_selector}.submit();\n"
+ output << " }\n"
+ output << "</script>\n"
+ options.delete(:controller)
+ output << fb_login_button("connect_to_facebook()", options)
+ output
+ end
+ end
+end
View
105 vendor/plugins/authlogic_facebook_connect/lib/authlogic_facebook_connect/session.rb
@@ -0,0 +1,105 @@
+module AuthlogicFacebookConnect
+ module Session
+ def self.included(klass)
+ klass.class_eval do
+ extend Config
+ include Methods
+ end
+ end
+
+ module Config
+ # Should the user be saved with our without validations?
+ #
+ # The default behavior is to save the user without validations and then
+ # in an application specific interface ask for the additional user
+ # details to make the user valid as facebook just provides a facebook id.
+ #
+ # This is useful if you do want to turn on user validations, maybe if you
+ # just have facebook connect as an additional authentication solution and
+ # you already have valid users.
+ #
+ # * <tt>Default:</tt> true
+ # * <tt>Accepts:</tt> Boolean
+ def facebook_valid_user(value = nil)
+ rw_config(:facebook_valid_user, value, false)
+ end
+ alias_method :facebook_valid_user=, :facebook_valid_user
+
+ # What user field should be used for the facebook UID?
+ #
+ # This is useful if you want to use a single field for multiple types of
+ # alternate user IDs, e.g. one that handles both OpenID identifiers and
+ # facebook ids.
+ #
+ # * <tt>Default:</tt> :facebook_uid
+ # * <tt>Accepts:</tt> Symbol
+ def facebook_uid_field(value = nil)
+ rw_config(:facebook_uid_field, value, :facebook_uid)
+ end
+ alias_method :facebook_uid_field=, :facebook_uid_field
+ end
+
+ module Methods
+ def self.included(klass)
+ klass.class_eval do
+ validate :validate_by_facebook_connect, :if => :authenticating_with_facebook_connect?
+ end
+
+ def credentials=(value)
+ # TODO: Is there a nicer way to tell Authlogic that we don't have any credentials than this?
+ values = [:facebook_connect]
+ super
+ end
+ end
+
+ def validate_by_facebook_connect
+ facebook_session = controller.facebook_session
+
+ self.attempted_record =
+ klass.find(:first, :conditions => { facebook_uid_field => facebook_session.user.uid })
+
+ unless self.attempted_record
+ begin
+ # Get the user from facebook and create a local user.
+ #
+ # We assign it after the call to new in case the attribute is protected.
+ new_user = klass.new
+ new_user.send(:"#{facebook_uid_field}=", facebook_session.user.uid)
+
+ new_user.before_connect(facebook_session) if new_user.respond_to?(:before_connect)
+
+ self.attempted_record = new_user
+
+ if facebook_valid_user
+ errors.add_to_base(
+ I18n.t('error_messages.facebook_user_creation_failed',
+ :default => 'There was a problem creating a new user ' +
+ 'for your Facebook account')) unless self.attempted_record.valid?
+
+ self.attempted_record = nil
+ else
+ self.attempted_record.save_with_validation(false)
+ end
+ rescue Facebooker::Session::SessionExpired
+ errors.add_to_base(I18n.t('error_messages.facebooker_session_expired',
+ :default => "Your Facebook Connect session has expired, please reconnect."))
+ end
+ end
+ end
+
+ def authenticating_with_facebook_connect?
+ controller.set_facebook_session
+ attempted_record.nil? && errors.empty? && controller.facebook_session
+ end
+
+ private
+ def facebook_valid_user
+ self.class.facebook_valid_user
+ end
+
+ def facebook_uid_field
+ self.class.facebook_uid_field
+ end
+ end
+ end
+end
View
0 vendor/plugins/authlogic_facebook_connect/lib/authlogic_facebook_connect/version.rb
No changes.

0 comments on commit 6209d2a

Please sign in to comment.
Something went wrong with that request. Please try again.