Created
January 13, 2010 16:29
-
-
Save avand/276329 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ApplicationController < ActionController::Base | |
protected | |
def persist_user(user) | |
session[:user_id] = user.id | |
end | |
def forget_user | |
session[:user_id] = nil | |
end | |
def current_user | |
return nil unless session[:user_id] | |
@current_user ||= User.find_by_id(session[:user_id]) # find_by_id so as not to raise | |
end | |
def require_authentication | |
redirect_to(login_path) and return false unless current_user | |
end | |
def require_no_authentication | |
redirect_to(root_path) and return false if current_user | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "digest/sha2" | |
module CryptographyHelper | |
module Random | |
def self.friendly_token | |
# use base64url as defined by RFC4648 | |
ActiveSupport::SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n") | |
end | |
end | |
class Sha512 | |
class << self | |
# Turns your raw password into a Sha512 hash. | |
def encrypt(*tokens) | |
digest = tokens.flatten.join | |
20.times { digest = Digest::SHA512.hexdigest(digest) } | |
digest | |
end | |
# Does the crypted password match the tokens? Uses the same tokens that were used to encrypt. | |
def matches?(crypted, *tokens) | |
encrypt(*tokens) == crypted | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SiteController < ApplicationController | |
before_filter :require_no_authentication, :only => :login | |
before_filter :require_authentication, :only => :logout | |
def login | |
if params[:email] && params[:password] | |
@user = User.find_by_email(params[:email]) | |
if @user.nil? | |
# Bad email | |
elsif @user.password_matches?(params[:password]) | |
# Everything's good! | |
persist_user(@user) | |
redirect_to #wherever | |
else | |
# Wrong password | |
params[:password] = '' | |
end | |
end | |
end | |
def logout | |
forget_user | |
redirect_to #wherever | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'oauth/consumer' | |
require 'json' | |
class TwitterController < ApplicationController | |
before_filter :require_no_authentication | |
TWITTER_AUTH_KEY = '...' | |
TWITTER_AUTH_SECRET = '...' | |
TWITTER_AUTH_URL = 'http://twitter.com' | |
def oauth | |
@oauth_consumer = OAuth::Consumer.new(TWITTER_AUTH_KEY, TWITTER_AUTH_SECRET, { :site => TWITTER_AUTH_URL }) | |
@request_token = @oauth_consumer.get_request_token({ | |
:oauth_callback => twitter_callback_url(:user_action => params[:user_action]) | |
}) | |
session[:request_token] = @request_token.token | |
session[:request_token_secret] = @request_token.secret | |
redirect_to @request_token.authorize_url # Send to twitter.com to authorize | |
end | |
def callback | |
@oauth_consumer = OAuth::Consumer.new(TWITTER_AUTH_KEY, TWITTER_AUTH_SECRET, { :site => TWITTER_AUTH_URL }) | |
@request_token = OAuth::RequestToken.new(@oauth_consumer, session[:request_token], session[:request_token_secret]) | |
session[:request_token] = nil | |
session[:request_token_secret] = nil | |
@access_token = @request_token.get_access_token(:oauth_verifier => params[:oauth_verifier]) | |
response = @access_token.get('/account/verify_credentials.json') | |
twitter_user_info = case response | |
when Net::HTTPSuccess | |
JSON.parse(response.body) # user attribtues are in here | |
else | |
raise # Twitter response wasn't a success, handle it. | |
end | |
twitter_attributes = { | |
:id => twitter_user_info['id'], | |
:name => twitter_user_info['name'], | |
:handle => twitter_user_info['screen_name'], | |
:token => @access_token.token, | |
:secret => @access_token.secret | |
} | |
if params[:user_action] == 'login' | |
@user = User.find_by_twitter_id(twitter_attributes[:id]) | |
if @user.present? | |
# A) User already exists with that Twitter ID, log them in | |
else | |
# B) User does not exist with Twitter ID, link them | |
end | |
else | |
# C) Create the user with the Twitter attributes provided (remember they might already exists), and log them in | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ActiveRecord::Base | |
attr_accessor :password | |
before_validation :set_crypted_password_and_password_salt | |
def self.authenticate_by_email(email, password) | |
user = User.find_by_email(email) or return nil | |
user.password_matches?(password) ? user : nil | |
end | |
def password_matches?(password) | |
CryptographyHelper::Sha512.matches?(self.crypted_password, password, self.password_salt) | |
end | |
def reset_perishable_token! | |
self.perishable_token = CryptographyHelper::Random.friendly_token | |
self.save | |
end | |
protected | |
def set_crypted_password_and_password_salt | |
if @password | |
self.password_salt = CryptographyHelper::Random.friendly_token | |
self.crypted_password = CryptographyHelper::Sha512.encrypt(@password, password_salt) | |
@password = nil | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment