forked from OpenNeo/impress
auth works - yaaay
This commit is contained in:
parent
e0ee659f86
commit
895c6e721e
18 changed files with 268 additions and 0 deletions
5
Gemfile
5
Gemfile
|
@ -8,6 +8,11 @@ gem 'haml', '~> 3.0.18'
|
||||||
gem 'rdiscount', '~> 1.6.5'
|
gem 'rdiscount', '~> 1.6.5'
|
||||||
gem 'RocketAMF', '~> 0.2.1'
|
gem 'RocketAMF', '~> 0.2.1'
|
||||||
gem 'will_paginate', '~> 3.0.pre2'
|
gem 'will_paginate', '~> 3.0.pre2'
|
||||||
|
gem 'warden', '~> 1.0.1'
|
||||||
|
gem 'rails_warden', '~> 0.5.2'
|
||||||
|
|
||||||
|
gem 'msgpack', '~> 0.4.3'
|
||||||
|
gem 'openneo-auth-signatory', '~> 0.0.4'
|
||||||
|
|
||||||
gem 'jammit', '~> 0.5.3'
|
gem 'jammit', '~> 0.5.3'
|
||||||
|
|
||||||
|
|
12
Gemfile.lock
12
Gemfile.lock
|
@ -87,6 +87,9 @@ GEM
|
||||||
mime-types
|
mime-types
|
||||||
treetop (>= 1.4.5)
|
treetop (>= 1.4.5)
|
||||||
mime-types (1.16)
|
mime-types (1.16)
|
||||||
|
msgpack (0.4.3)
|
||||||
|
openneo-auth-signatory (0.0.4)
|
||||||
|
ruby-hmac
|
||||||
polyglot (0.3.1)
|
polyglot (0.3.1)
|
||||||
rack (1.2.1)
|
rack (1.2.1)
|
||||||
rack-fiber_pool (0.9.0)
|
rack-fiber_pool (0.9.0)
|
||||||
|
@ -102,6 +105,8 @@ GEM
|
||||||
activesupport (= 3.0.0)
|
activesupport (= 3.0.0)
|
||||||
bundler (~> 1.0.0)
|
bundler (~> 1.0.0)
|
||||||
railties (= 3.0.0)
|
railties (= 3.0.0)
|
||||||
|
rails_warden (0.5.2)
|
||||||
|
warden
|
||||||
railties (3.0.0)
|
railties (3.0.0)
|
||||||
actionpack (= 3.0.0)
|
actionpack (= 3.0.0)
|
||||||
activesupport (= 3.0.0)
|
activesupport (= 3.0.0)
|
||||||
|
@ -121,10 +126,13 @@ GEM
|
||||||
rspec-expectations (= 2.0.0.beta.22)
|
rspec-expectations (= 2.0.0.beta.22)
|
||||||
rspec-rails (2.0.0.beta.22)
|
rspec-rails (2.0.0.beta.22)
|
||||||
rspec (= 2.0.0.beta.22)
|
rspec (= 2.0.0.beta.22)
|
||||||
|
ruby-hmac (0.4.0)
|
||||||
thor (0.14.2)
|
thor (0.14.2)
|
||||||
treetop (1.4.8)
|
treetop (1.4.8)
|
||||||
polyglot (>= 0.3.1)
|
polyglot (>= 0.3.1)
|
||||||
tzinfo (0.3.23)
|
tzinfo (0.3.23)
|
||||||
|
warden (1.0.1)
|
||||||
|
rack (>= 1.0.0)
|
||||||
will_paginate (3.0.pre2)
|
will_paginate (3.0.pre2)
|
||||||
yui-compressor (0.9.1)
|
yui-compressor (0.9.1)
|
||||||
|
|
||||||
|
@ -142,9 +150,13 @@ DEPENDENCIES
|
||||||
factory_girl_rails (~> 1.0)
|
factory_girl_rails (~> 1.0)
|
||||||
haml (~> 3.0.18)
|
haml (~> 3.0.18)
|
||||||
jammit (~> 0.5.3)
|
jammit (~> 0.5.3)
|
||||||
|
msgpack (~> 0.4.3)
|
||||||
mysqlplus!
|
mysqlplus!
|
||||||
|
openneo-auth-signatory (~> 0.0.4)
|
||||||
rack-fiber_pool
|
rack-fiber_pool
|
||||||
rails (= 3.0.0)
|
rails (= 3.0.0)
|
||||||
|
rails_warden (~> 0.5.2)
|
||||||
rdiscount (~> 1.6.5)
|
rdiscount (~> 1.6.5)
|
||||||
rspec-rails (~> 2.0.0.beta.22)
|
rspec-rails (~> 2.0.0.beta.22)
|
||||||
|
warden (~> 1.0.1)
|
||||||
will_paginate (~> 3.0.pre2)
|
will_paginate (~> 3.0.pre2)
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
protect_from_forgery
|
protect_from_forgery
|
||||||
|
|
||||||
|
helper_method :current_user, :user_signed_in?
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def current_user
|
||||||
|
@current_user ||= warden.authenticate
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_signed_in?
|
||||||
|
current_user ? true : false
|
||||||
|
end
|
||||||
|
|
||||||
|
def warden
|
||||||
|
env['warden']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
32
app/controllers/sessions_controller.rb
Normal file
32
app/controllers/sessions_controller.rb
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
class SessionsController < ApplicationController
|
||||||
|
rescue_from Openneo::Auth::Session::InvalidSignature, :with => :invalid_signature
|
||||||
|
rescue_from Openneo::Auth::Session::MissingParam, :with => :missing_param
|
||||||
|
|
||||||
|
skip_before_filter :verify_authenticity_token, :only => [:create]
|
||||||
|
|
||||||
|
def new
|
||||||
|
redirect_to Openneo::Auth.remote_auth_url(params, session)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
session = Openneo::Auth::Session.from_params(params)
|
||||||
|
session.save!
|
||||||
|
render :text => 'Success'
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
warden.logout
|
||||||
|
redirect_to root_path
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def invalid_signature(exception)
|
||||||
|
render :text => "Signature did not match. Check secret.",
|
||||||
|
:status => :unprocessable_entity
|
||||||
|
end
|
||||||
|
|
||||||
|
def missing_param(exception)
|
||||||
|
render :text => exception.message, :status => :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
15
app/models/user.rb
Normal file
15
app/models/user.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class User < ActiveRecord::Base
|
||||||
|
DefaultAuthServerId = 1
|
||||||
|
|
||||||
|
def self.find_or_create_from_remote_auth_data(user_data)
|
||||||
|
user = find_or_initialize_by_remote_id_and_auth_server_id(
|
||||||
|
user_data['id'],
|
||||||
|
DefaultAuthServerId
|
||||||
|
)
|
||||||
|
if user.new_record?
|
||||||
|
user.name = user_data['name']
|
||||||
|
user.save
|
||||||
|
end
|
||||||
|
user
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,6 +7,13 @@
|
||||||
= javascript_include_tag "http://#{RemoteImpressHost}/assets/js/analytics.js"
|
= javascript_include_tag "http://#{RemoteImpressHost}/assets/js/analytics.js"
|
||||||
%body{:class => params[:action]}
|
%body{:class => params[:action]}
|
||||||
#container
|
#container
|
||||||
|
- if user_signed_in?
|
||||||
|
You are logged in as
|
||||||
|
= current_user.name
|
||||||
|
== (#{current_user.id})
|
||||||
|
= link_to 'Log out', logout_path
|
||||||
|
- else
|
||||||
|
= link_to 'Log in', login_path
|
||||||
%h1
|
%h1
|
||||||
= link_to items_path do
|
= link_to items_path do
|
||||||
= image_tag 'http://images.neopets.com/items/mall_floatingneggfaerie.gif'
|
= image_tag 'http://images.neopets.com/items/mall_floatingneggfaerie.gif'
|
||||||
|
|
|
@ -21,3 +21,8 @@ OpenneoImpressItems::Application.configure do
|
||||||
end
|
end
|
||||||
|
|
||||||
RemoteImpressHost = 'beta.impress.openneo.net'
|
RemoteImpressHost = 'beta.impress.openneo.net'
|
||||||
|
OPENNEO_AUTH_CONFIG = {
|
||||||
|
:app => 'beta.items.impress',
|
||||||
|
:auth_server => 'openneo-id',
|
||||||
|
:secret => 'zaheh2draswAb8eneca$3an?2ADAsTuwra8h7BujUBr_w--p2-a@e?u!taQux3tr'
|
||||||
|
}
|
||||||
|
|
|
@ -25,3 +25,9 @@ end
|
||||||
RemoteImpressHost = 'beta.impress.openneo.net'
|
RemoteImpressHost = 'beta.impress.openneo.net'
|
||||||
|
|
||||||
USE_FIBER_POOL = true
|
USE_FIBER_POOL = true
|
||||||
|
|
||||||
|
OPENNEO_AUTH_CONFIG = {
|
||||||
|
:app => 'beta.items.impress',
|
||||||
|
:auth_server => 'beta.id.openneo.net',
|
||||||
|
:secret => 'zaheh2draswAb8eneca$3an?2ADAsTuwra8h7BujUBr_w--p2-a@e?u!taQux3tr'
|
||||||
|
}
|
||||||
|
|
16
config/initializers/warden.rb
Normal file
16
config/initializers/warden.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
Rails.configuration.middleware.use RailsWarden::Manager do |manager|
|
||||||
|
manager.default_strategies :openneo_auth_token, :openneo_auth_redirect
|
||||||
|
manager.failure_app = SessionsController.action(:failure)
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'openneo-auth'
|
||||||
|
|
||||||
|
Openneo::Auth.configure do |config|
|
||||||
|
OPENNEO_AUTH_CONFIG.each do |key, value|
|
||||||
|
config.send("#{key}=", value)
|
||||||
|
end
|
||||||
|
|
||||||
|
config.user_finder do |user_data|
|
||||||
|
User.find_or_create_from_remote_auth_data(user_data)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,5 @@
|
||||||
OpenneoImpressItems::Application.routes.draw do |map|
|
OpenneoImpressItems::Application.routes.draw do |map|
|
||||||
|
root :to => 'items#index'
|
||||||
match '/' => 'items#index', :as => :items
|
match '/' => 'items#index', :as => :items
|
||||||
match '/index.js' => 'items#index', :format => :js
|
match '/index.js' => 'items#index', :format => :js
|
||||||
match '/items.json' => 'items#index', :format => :json
|
match '/items.json' => 'items#index', :format => :json
|
||||||
|
@ -18,5 +19,9 @@ OpenneoImpressItems::Application.routes.draw do |map|
|
||||||
resources :pet_attributes, :only => [:index]
|
resources :pet_attributes, :only => [:index]
|
||||||
resources :pets, :only => [:show]
|
resources :pets, :only => [:show]
|
||||||
|
|
||||||
|
match '/login' => 'sessions#new', :as => :login
|
||||||
|
match '/logout' => 'sessions#destroy', :as => :logout
|
||||||
|
match '/users/authorize' => 'sessions#create'
|
||||||
|
|
||||||
match '/wardrobe' => 'outfits#edit', :as => :wardrobe
|
match '/wardrobe' => 'outfits#edit', :as => :wardrobe
|
||||||
end
|
end
|
||||||
|
|
47
lib/openneo-auth.rb
Normal file
47
lib/openneo-auth.rb
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
require 'openneo-auth/session'
|
||||||
|
require 'openneo-auth/strategy'
|
||||||
|
|
||||||
|
Warden::Strategies.add :openneo_auth_token, Openneo::Auth::Strategy
|
||||||
|
|
||||||
|
module Openneo
|
||||||
|
module Auth
|
||||||
|
class Config
|
||||||
|
attr_accessor :app, :auth_server, :secret
|
||||||
|
|
||||||
|
def find_user(data)
|
||||||
|
raise "Must set a user finder for Openneo Auth to find a user" unless @user_finder
|
||||||
|
@user_finder.call(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_finder(&block)
|
||||||
|
@user_finder = block
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def config
|
||||||
|
@@config ||= Config.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def configure(&block)
|
||||||
|
block.call(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
def remote_auth_url(params, session)
|
||||||
|
raise "Must set config.app to this app's subdomain" unless config.app
|
||||||
|
raise "Must set config.auth_server to remote server's hostname" unless config.auth_server
|
||||||
|
query = {
|
||||||
|
:app => config.app,
|
||||||
|
:session_id => session[:session_id],
|
||||||
|
:path => params[:return_to] || '/'
|
||||||
|
}.to_query
|
||||||
|
uri = URI::HTTP.build({
|
||||||
|
:host => config.auth_server,
|
||||||
|
:path => '/',
|
||||||
|
:query => query
|
||||||
|
})
|
||||||
|
uri.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
84
lib/openneo-auth/session.rb
Normal file
84
lib/openneo-auth/session.rb
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
require 'active_support/core_ext/hash'
|
||||||
|
require 'msgpack'
|
||||||
|
require 'openneo-auth-signatory'
|
||||||
|
|
||||||
|
module Openneo
|
||||||
|
module Auth
|
||||||
|
class Session
|
||||||
|
REMOTE_MSG_KEYS = %w(session_id source user)
|
||||||
|
TMP_STORAGE_DIR = Rails.root.join('tmp', 'openneo-auth-sessions')
|
||||||
|
|
||||||
|
attr_writer :id
|
||||||
|
|
||||||
|
def save!
|
||||||
|
FileUtils.mkdir_p TMP_STORAGE_DIR
|
||||||
|
File.open(tmp_storage_path, 'w') do |file|
|
||||||
|
file.write MessagePack.pack(@message).force_encoding('utf-8')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy!
|
||||||
|
File.delete(tmp_storage_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_message!
|
||||||
|
raise NotFound, "Session #{id} not found" unless File.exists?(tmp_storage_path)
|
||||||
|
@message = File.open(tmp_storage_path, 'r') do |file|
|
||||||
|
MessagePack.unpack file.read
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def params=(params)
|
||||||
|
unless Auth.config.secret
|
||||||
|
raise "Must set config.secret to the remote auth server's secret"
|
||||||
|
end
|
||||||
|
given_signature = params['signature']
|
||||||
|
signatory = Auth::Signatory.new(Auth.config.secret.force_encoding('utf-8'))
|
||||||
|
REMOTE_MSG_KEYS.each do |key|
|
||||||
|
unless params.include?(key)
|
||||||
|
raise MissingParam, "Missing required param #{key.inspect}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@message = params.slice(*REMOTE_MSG_KEYS)
|
||||||
|
correct_signature = signatory.sign(@message)
|
||||||
|
unless given_signature == correct_signature
|
||||||
|
raise InvalidSignature, "Signature (#{given_signature}) " +
|
||||||
|
"did not match message #{@message.inspect} (#{correct_signature})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def user
|
||||||
|
Auth.config.find_user(@message['user'])
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.from_params(params)
|
||||||
|
session = new
|
||||||
|
session.params = params
|
||||||
|
session
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find(id)
|
||||||
|
session = new
|
||||||
|
session.id = id
|
||||||
|
session.load_message!
|
||||||
|
session
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def id
|
||||||
|
@id ||= @message[:session_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
def tmp_storage_path
|
||||||
|
name = "#{id}.mpac"
|
||||||
|
File.join TMP_STORAGE_DIR, name
|
||||||
|
end
|
||||||
|
|
||||||
|
class InvalidSession < ArgumentError;end
|
||||||
|
class InvalidSignature < InvalidSession;end
|
||||||
|
class MissingParam < InvalidSession;end
|
||||||
|
class NotFound < StandardError;end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
18
lib/openneo-auth/strategy.rb
Normal file
18
lib/openneo-auth/strategy.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
require 'warden'
|
||||||
|
|
||||||
|
module Openneo
|
||||||
|
module Auth
|
||||||
|
class Strategy < Warden::Strategies::Base
|
||||||
|
def authenticate!
|
||||||
|
begin
|
||||||
|
auth_session = Session.find session[:session_id]
|
||||||
|
rescue Session::NotFound => e
|
||||||
|
fail! e.message
|
||||||
|
else
|
||||||
|
auth_session.destroy!
|
||||||
|
success! auth_session.user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
BIN
vendor/cache/msgpack-0.4.3.gem
vendored
Normal file
BIN
vendor/cache/msgpack-0.4.3.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/openneo-auth-signatory-0.0.4.gem
vendored
Normal file
BIN
vendor/cache/openneo-auth-signatory-0.0.4.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/rails_warden-0.5.2.gem
vendored
Normal file
BIN
vendor/cache/rails_warden-0.5.2.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/ruby-hmac-0.4.0.gem
vendored
Normal file
BIN
vendor/cache/ruby-hmac-0.4.0.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/warden-1.0.1.gem
vendored
Normal file
BIN
vendor/cache/warden-1.0.1.gem
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue