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 'RocketAMF', '~> 0.2.1'
|
||||
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'
|
||||
|
||||
|
|
12
Gemfile.lock
12
Gemfile.lock
|
@ -87,6 +87,9 @@ GEM
|
|||
mime-types
|
||||
treetop (>= 1.4.5)
|
||||
mime-types (1.16)
|
||||
msgpack (0.4.3)
|
||||
openneo-auth-signatory (0.0.4)
|
||||
ruby-hmac
|
||||
polyglot (0.3.1)
|
||||
rack (1.2.1)
|
||||
rack-fiber_pool (0.9.0)
|
||||
|
@ -102,6 +105,8 @@ GEM
|
|||
activesupport (= 3.0.0)
|
||||
bundler (~> 1.0.0)
|
||||
railties (= 3.0.0)
|
||||
rails_warden (0.5.2)
|
||||
warden
|
||||
railties (3.0.0)
|
||||
actionpack (= 3.0.0)
|
||||
activesupport (= 3.0.0)
|
||||
|
@ -121,10 +126,13 @@ GEM
|
|||
rspec-expectations (= 2.0.0.beta.22)
|
||||
rspec-rails (2.0.0.beta.22)
|
||||
rspec (= 2.0.0.beta.22)
|
||||
ruby-hmac (0.4.0)
|
||||
thor (0.14.2)
|
||||
treetop (1.4.8)
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.23)
|
||||
warden (1.0.1)
|
||||
rack (>= 1.0.0)
|
||||
will_paginate (3.0.pre2)
|
||||
yui-compressor (0.9.1)
|
||||
|
||||
|
@ -142,9 +150,13 @@ DEPENDENCIES
|
|||
factory_girl_rails (~> 1.0)
|
||||
haml (~> 3.0.18)
|
||||
jammit (~> 0.5.3)
|
||||
msgpack (~> 0.4.3)
|
||||
mysqlplus!
|
||||
openneo-auth-signatory (~> 0.0.4)
|
||||
rack-fiber_pool
|
||||
rails (= 3.0.0)
|
||||
rails_warden (~> 0.5.2)
|
||||
rdiscount (~> 1.6.5)
|
||||
rspec-rails (~> 2.0.0.beta.22)
|
||||
warden (~> 1.0.1)
|
||||
will_paginate (~> 3.0.pre2)
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
class ApplicationController < ActionController::Base
|
||||
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
|
||||
|
|
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"
|
||||
%body{:class => params[:action]}
|
||||
#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
|
||||
= link_to items_path do
|
||||
= image_tag 'http://images.neopets.com/items/mall_floatingneggfaerie.gif'
|
||||
|
|
|
@ -21,3 +21,8 @@ OpenneoImpressItems::Application.configure do
|
|||
end
|
||||
|
||||
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'
|
||||
|
||||
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|
|
||||
root :to => 'items#index'
|
||||
match '/' => 'items#index', :as => :items
|
||||
match '/index.js' => 'items#index', :format => :js
|
||||
match '/items.json' => 'items#index', :format => :json
|
||||
|
@ -18,5 +19,9 @@ OpenneoImpressItems::Application.routes.draw do |map|
|
|||
resources :pet_attributes, :only => [:index]
|
||||
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
|
||||
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