vidibus-user 0.0.10 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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'