vidibus-user 0.0.10 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Vidibus::User [![Build Status](https://travis-ci.org/vidibus/vidibus-user.png)](https://travis-ci.org/vidibus/vidibus-user) [![Code Climate](https://codeclimate.com/github/vidibus/vidibus-user.png)](https://codeclimate.com/github/vidibus/vidibus-user)
2
+
3
+ Provides single sign-on through OAuth2 authentication. It adds a simple user model to your application which can be extended easily.
4
+
5
+ This gem is part of [Vidibus](http://vidibus.org), an open source toolset for building distributed (video) applications.
6
+
7
+
8
+ ## Installation
9
+
10
+ Add `gem 'vidibus-service'` to your Gemfile. Then call `bundle install` on your console.
11
+
12
+
13
+ ## Obtaining user data
14
+
15
+ After authorization via OAuth2 this gem requests user data from the providing service. It expects `GET /oauth/user` to return JSON data. The dataset must at least include the user's UUID.
16
+
17
+ The [Vidibus::Oauth2Server](https://github.com/vidibus/vidibus-oauth2_server) gem will provide a controller for this task.
18
+
19
+
20
+ ## Dependencies
21
+
22
+ In order to perform authentication, this gem depends on services provided by the [Vidibus::Service](https://github.com/vidibus/vidibus-service) gem.
23
+
24
+
25
+ ## TODO
26
+
27
+ Explain usage and integration.
28
+
29
+
30
+ ## Copyright
31
+
32
+ Copyright (c) 2010-2013 Andre Pankratz. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,35 +1,17 @@
1
- require "rubygems"
2
- require "rake"
3
- require "rake/rdoctask"
4
- require "rspec"
5
- require "rspec/core/rake_task"
1
+ $:.unshift File.expand_path('../lib/', __FILE__)
6
2
 
7
- begin
8
- require "jeweler"
9
- Jeweler::Tasks.new do |gem|
10
- gem.name = "vidibus-user"
11
- gem.summary = %Q{Single sign-on for Vidibus applications.}
12
- gem.description = %Q{Provides single sign-on and a local user model.}
13
- gem.email = "andre@vidibus.com"
14
- gem.homepage = "http://github.com/vidibus/vidibus-user"
15
- gem.authors = ["Andre Pankratz"]
16
- end
17
- Jeweler::GemcutterTasks.new
18
- rescue LoadError
19
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
- end
3
+ require 'bundler'
4
+ require 'rdoc/task'
5
+ require 'rspec'
6
+ require 'rspec/core/rake_task'
7
+ require 'vidibus/user/version'
21
8
 
22
- Rspec::Core::RakeTask.new(:rcov) do |t|
23
- t.pattern = "spec/**/*_spec.rb"
24
- t.rcov = true
25
- t.rcov_opts = ["--exclude", "^spec,/gems/"]
26
- end
9
+ Bundler::GemHelper.install_tasks
27
10
 
28
11
  Rake::RDocTask.new do |rdoc|
29
- version = File.exist?("VERSION") ? File.read("VERSION") : ""
30
- rdoc.rdoc_dir = "rdoc"
31
- rdoc.title = "vidibus-user #{version}"
32
- rdoc.rdoc_files.include("README*")
33
- rdoc.rdoc_files.include("lib/**/*.rb")
34
- rdoc.options << "--charset=utf-8"
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = "vidibus-user #{Vidibus::User::VERSION}"
14
+ rdoc.rdoc_files.include('README*')
15
+ rdoc.rdoc_files.include('lib/**/*.rb')
16
+ rdoc.options << '--charset=utf-8'
35
17
  end
data/config/routes.rb CHANGED
@@ -1,5 +1,5 @@
1
- require "user/callback_app"
1
+ require 'vidibus/user/callback_app'
2
2
 
3
3
  Rails.application.routes.draw do
4
- match "/authenticate_user" => Vidibus::User::CallbackApp
4
+ get '/authenticate_user' => Vidibus::User::CallbackApp
5
5
  end
@@ -5,14 +5,14 @@ module Vidibus
5
5
  self.new.call(env)
6
6
  end
7
7
 
8
- # This is just a rack endpoint for Connector authentication. It will be called
9
- # by the Connector after requesting an authentication code.
8
+ # This is a rack endpoint user authentication. It will be called
9
+ # by the consumer after requesting an authentication code.
10
10
  def call(env)
11
- env["warden"].authenticate!(:scope => :user)
11
+ env['warden'].authenticate!(:scope => :user)
12
12
 
13
13
  # Redirect to return path after signin
14
- return_to = env["rack.session"][:user_return_to] || "/"
15
- [302, {"Content-Type" => "text/html", "Location" => return_to}, ["Login successful."]]
14
+ return_to = env['rack.session'][:user_return_to] || '/'
15
+ [302, {'Content-Type' => 'text/html', 'Location' => return_to}, ['Login successful.']]
16
16
  end
17
17
  end
18
18
  end
@@ -0,0 +1,7 @@
1
+ module Vidibus
2
+ module User
3
+ class Error < StandardError; end
4
+ class ServiceError < Error; end
5
+ class SingleSignOnError < Error; end
6
+ end
7
+ end
@@ -1,52 +1,34 @@
1
+ require 'vidibus/user/extensions/helper'
2
+
1
3
  module Vidibus
2
4
  module User
3
5
  module Extensions
4
-
5
- # Contains extensions of ApplicationController.
6
6
  module Controller
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- helper_method :warden, :signed_in?, :user_signed_in?, :current_user, :user_session
11
- end
12
-
13
- protected
14
-
15
- # Accessor for the warden proxy instance.
16
- def warden
17
- request.env["warden"]
18
- end
19
-
20
- # Performs login on Connector service.
21
- def authenticate_user!
22
- return if user_signed_in?
23
- store_location
24
- warden.authenticate!(:scope => :user)
25
- end
7
+ include Helper
26
8
 
27
- # Returns session of currently signed in user.
28
- def user_session
29
- current_user and warden.session(:user)
9
+ # Authenticates user from single sign on cookie.
10
+ # Nothing happens if authentication fails.
11
+ def single_sign_on
12
+ return if authenticated?
13
+ warden.authenticate(:single_sign_on)
30
14
  end
31
15
 
32
- # Returns user currently logged in.
33
- def current_user
34
- warden.user(:user)
16
+ # Authenticates user either from single sign on cookie
17
+ # or from email and password params.
18
+ # Calls failure app if authentication fails.
19
+ def authenticate!
20
+ return if authenticated?
21
+ warden.authenticate!
35
22
  end
23
+ alias :signin! :authenticate!
24
+ alias :authenticate_user! :authenticate!
36
25
 
37
- # Returns true if user is logged in.
38
- def user_signed_in?
39
- warden.authenticated?(:user)
40
- end
41
- alias_method :signed_in?, :user_signed_in?
42
-
43
- private
44
-
45
- # Stores current location in session to perform redirect after signin in session
46
- def store_location
47
- Rails.logger.error 'store_location: '+request.fullpath
48
- session[:user_return_to] = request.fullpath
26
+ # Performs logout.
27
+ def logout
28
+ return unless authenticated?
29
+ warden.logout
49
30
  end
31
+ alias :signout :logout
50
32
  end
51
33
  end
52
34
  end
@@ -0,0 +1,29 @@
1
+ module Vidibus
2
+ module User
3
+ module Extensions
4
+ module Helper
5
+
6
+ # Accessor for the warden proxy instance.
7
+ def warden
8
+ request.env['warden']
9
+ end
10
+
11
+ # Returns the user that is currently logged in.
12
+ def current_user
13
+ warden.user
14
+ end
15
+
16
+ # Returns the session of the currently signed-in user.
17
+ def user_session
18
+ warden.session if current_user
19
+ end
20
+
21
+ # Returns true if user is logged in.
22
+ def authenticated?
23
+ warden.authenticated?
24
+ end
25
+ alias :signed_in? :authenticated?
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,5 +1,16 @@
1
- require "user/extensions/controller"
1
+ require 'vidibus/user/extensions/controller'
2
+ require 'vidibus/user/extensions/helper'
2
3
 
3
- ActiveSupport.on_load(:action_controller) do
4
- include Vidibus::User::Extensions::Controller
4
+ if defined?(ActiveSupport)
5
+ ActiveSupport.on_load(:action_controller) do
6
+ include Vidibus::User::Extensions::Controller
7
+ end
8
+
9
+ ActiveSupport.on_load(:application_helper) do
10
+ include Vidibus::User::Extensions::Helper
11
+ end
12
+
13
+ ActiveSupport.on_load(:action_view) do
14
+ include Vidibus::User::Extensions::Helper
15
+ end
5
16
  end
@@ -1,10 +1,12 @@
1
+ require 'vidibus-uuid'
2
+
1
3
  module Vidibus
2
4
  module User
3
5
  module Mongoid
4
6
  extend ActiveSupport::Concern
5
7
  included do
6
- field :uuid
7
- field :email
8
+ field :uuid, type: String
9
+ field :email, type: String
8
10
  validates :uuid, :uuid => true
9
11
  end
10
12
  end
@@ -0,0 +1,19 @@
1
+ if defined?(::Rails::Engine)
2
+ module Vidibus
3
+ module User
4
+ class Engine < ::Rails::Engine
5
+
6
+ # Add warden to rack stack and use vidibus strategy.
7
+ config.app_middleware.use ::Warden::Manager do |manager|
8
+ manager.default_strategies :single_sign_on
9
+ manager.default_scope = :user
10
+ manager.failure_app = Vidibus::User.failure_app
11
+ end
12
+
13
+ config.after_initialize do
14
+ Vidibus::User.logger = Rails.logger
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Vidibus
2
+ module User
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ # Warden callback that validates the SSO session.
2
+ Warden::Manager.after_set_user do |user, auth, opts|
3
+ # TODO
4
+ end
@@ -0,0 +1,5 @@
1
+ # Warden callback that sends a request to the central user registration
2
+ # for single sign-out
3
+ Warden::Manager.before_logout do |user, auth, opts|
4
+ # TODO
5
+ end
@@ -0,0 +1,2 @@
1
+ require 'vidibus/user/warden/callbacks/after_set_user'
2
+ require 'vidibus/user/warden/callbacks/before_logout'
@@ -0,0 +1,30 @@
1
+ module Vidibus
2
+ module User
3
+ module Warden
4
+ class FailureApp
5
+ include Warden::Helper
6
+
7
+ def self.call(env)
8
+ self.new.call(env)
9
+ end
10
+
11
+ # This is a rack endpoint user authentication. It will be called
12
+ # by the consumer after requesting an authentication code.
13
+ def call(env)
14
+ @env = env
15
+ body = "Please authenticate at #{host}#{Vidibus::User.login_path}"
16
+ header = {
17
+ 'Content-Type' => 'text/html',
18
+ 'Location' => Vidibus::User.login_path,
19
+ 'Content-Length' => body.length.to_s
20
+ }
21
+ [302, header, [body]]
22
+ end
23
+
24
+ def env
25
+ @env
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,55 @@
1
+ module Vidibus
2
+ module User
3
+ module Warden
4
+ module Helper
5
+
6
+ # Sets credentials for Connector login in session.
7
+ # The client_secret will be validated through Vidibus' OauthServer
8
+ # when issuing an OAuth token. To protect the service's secret, a
9
+ # custom signature will be sent instead.
10
+ def credentials
11
+ @credentials ||= begin
12
+ service = ::Service.discover(:user, realm)
13
+ unless service
14
+ raise(ServiceError, 'No user service is available.')
15
+ end
16
+ {
17
+ :client_id => "#{this.uuid}-#{realm}",
18
+ :client_secret => Vidibus::Secure.sign(this.uuid, service.secret),
19
+ :service_url => service.url
20
+ }
21
+ end
22
+ end
23
+
24
+ # Returns this service
25
+ def this
26
+ @this ||= ::Service.this
27
+ end
28
+
29
+ # Returns the current realm
30
+ def realm
31
+ @realm ||= params['realm'] || env[:realm]
32
+ end
33
+
34
+ # Returns OAuth client
35
+ def client
36
+ @client ||= OAuth2::Client.new(credentials[:client_id], credentials[:client_secret], :site => credentials[:service_url])
37
+ end
38
+
39
+ # Returns current host.
40
+ def host
41
+ "#{protocol}#{env['HTTP_HOST']}"
42
+ end
43
+
44
+ # Returns protocol depending on SERVER_PORT.
45
+ def protocol
46
+ env['SERVER_PORT'] == 443 ? 'https://' : 'http://'
47
+ end
48
+
49
+ def logger
50
+ Vidibus::User.logger
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ Warden::Manager.serialize_into_session do |user|
2
+ user.id
3
+ end
4
+
5
+ Warden::Manager.serialize_from_session do |id|
6
+ ::User.find(id)
7
+ end
@@ -0,0 +1,77 @@
1
+ require 'oauth2'
2
+
3
+ # Warden strategy to authenticate user from a
4
+ # single sign-on cookie.
5
+ ::Warden::Strategies.add(:single_sign_on) do
6
+ include Vidibus::User::Warden::Helper
7
+
8
+ USER_DATA_PATH = '/oauth/user'
9
+
10
+ # Run this strategy only if a realm is present.
11
+ def valid?
12
+ !!realm
13
+ end
14
+
15
+ def user
16
+ @user
17
+ end
18
+
19
+ def authenticate!
20
+ return if fetch_code
21
+ fetch_access_token
22
+ fetch_user_data
23
+ user ? success!(user) : fail!
24
+ end
25
+
26
+ private
27
+
28
+ def args
29
+ {:redirect_url => "#{host}/authenticate_user?realm=#{realm}"}
30
+ end
31
+
32
+ def code
33
+ params['code']
34
+ end
35
+
36
+ def access_token
37
+ @access_token ||= begin
38
+ client.auth_code.get_token(code, args)
39
+ end
40
+ end
41
+
42
+ def fetch_code
43
+ return if code
44
+ failsafe do
45
+ redirect!(client.auth_code.authorize_url(args))
46
+ end
47
+ end
48
+
49
+ def fetch_access_token
50
+ failsafe do
51
+ access_token
52
+ end
53
+ end
54
+
55
+ def fetch_user_data
56
+ begin
57
+ response = access_token.get(USER_DATA_PATH)
58
+ user_data = JSON.parse(response.body)
59
+ query = {:uuid => user_data['uuid']}
60
+ user = User.where(query).first || User.create!(query)
61
+ user.update_attributes!(user_data)
62
+ @user = user
63
+ rescue OAuth2::Error => e
64
+ logger.error("Vidibus::User: Failed to fetch user data from #{credentials[:service_url]}/#{USER_DATA_PATH}: #{e.message}")
65
+ rescue => e
66
+ logger.error("Vidibus::User: #{e.message}")
67
+ end
68
+ end
69
+
70
+ def failsafe(&block)
71
+ begin
72
+ block.call
73
+ rescue OAuth2::Error => e
74
+ raise(Vidibus::User::SingleSignOnError, e.response.body)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1 @@
1
+ require 'vidibus/user/warden/strategies/single_sign_on'
@@ -0,0 +1,5 @@
1
+ require 'vidibus/user/warden/serialize'
2
+ require 'vidibus/user/warden/helper'
3
+ require 'vidibus/user/warden/strategies'
4
+ require 'vidibus/user/warden/callbacks'
5
+ require 'vidibus/user/warden/failure_app'
data/lib/vidibus/user.rb CHANGED
@@ -1,3 +1,20 @@
1
- require "user/extensions"
2
- require "user/warden_strategy"
3
- require "user/mongoid"
1
+ require 'vidibus/user/errors'
2
+ require 'vidibus/user/mongoid'
3
+ require 'vidibus/user/warden'
4
+ require 'vidibus/user/extensions'
5
+ require 'vidibus/user/railstie'
6
+
7
+ module Vidibus
8
+ module User
9
+ extend self
10
+
11
+ attr_accessor :login_path
12
+ @login_path = '/login'
13
+
14
+ attr_accessor :logger
15
+ @logger = Logger.new(STDOUT)
16
+
17
+ attr_accessor :failure_app
18
+ @failure_app = Vidibus::User::Warden::FailureApp
19
+ end
20
+ end
data/lib/vidibus-user.rb CHANGED
@@ -1,20 +1,3 @@
1
- require "rails"
2
-
3
- $:.unshift(File.join(File.dirname(__FILE__), "vidibus"))
4
- require "user"
5
-
6
- module Vidibus
7
- module User
8
- class Error < StandardError; end
9
- class NoRealmError < Error; end
10
-
11
- class Engine < ::Rails::Engine
12
-
13
- # Add warden to rack stack and use connector strategy.
14
- config.app_middleware.use Warden::Manager do |manager|
15
- manager.default_strategies :connector
16
- manager.default_scope = :user
17
- end
18
- end
19
- end
20
- end
1
+ require 'warden'
2
+ require 'vidibus-service'
3
+ require 'vidibus/user'