Skip to content

Instantly share code, notes, and snippets.

@avand
Created January 13, 2010 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avand/276329 to your computer and use it in GitHub Desktop.
Save avand/276329 to your computer and use it in GitHub Desktop.
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
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
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
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
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