capcoauth 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a84d574dab09d66611c3a8d525d0480cb5aeabf
4
- data.tar.gz: aab1b067b415ffad7199f4a3174e84e7c2fec81f
3
+ metadata.gz: 413293494a485db6a7d32e5f7ebb599b0a140dd1
4
+ data.tar.gz: f37a26cb400e3c5092b2958799551e13ee433af0
5
5
  SHA512:
6
- metadata.gz: aa9cf3ee808b75df538536d81040544faa5251d6450fcd1c95416d8d731276361fa9b10fa73448562da5df13e4b6caeecb1d1ef51dc0da00c3661cd18c7195da
7
- data.tar.gz: e220ad1bbefff4ba8f399b75c1acb6a6045fedce7eb46d5f575049a17bc5118dab6a2836b6ac11fbd823dc17733270b3b731536f10987ffa1eb24242556a319c
6
+ metadata.gz: a6401723ff07e5dc867d4fbbac9a2142c5bba2139d34b0c5969ff1737cb83f5d90fa261103e689eb289b23dce44ba0b046a488f1845496d1554d277ec1878162
7
+ data.tar.gz: 2d591b42756602ac29116859f224a0780408ddefaf303f53ce3b41d5340504d61fbc49a84242bcb32c655f2b9f5f39830749ca4bf43f5d62753f677e5452e606
data/README.md CHANGED
@@ -79,6 +79,15 @@ whatever TTL value you set in your initializer. This saves time by preventing e
79
79
  CapcOAuth for approval. This can be increased or decreased at your discretion, but should be kept to a relatively low
80
80
  value.
81
81
 
82
+ ## API-only applications
83
+
84
+ Simply remove `use_capcoauth` from `routes.rb`, or don't add it if you created your own initializer.
85
+
86
+ By default, this gem assumes you're using a normal Rails application, and thus adds `use_capcoauth` to your `routes.rb`
87
+ file. When `use_capcoauth` is used, it signals the gem to allow redirects and session variables whenever an HTML
88
+ request type is detected. For API-only applications, it will only parse the `access_token` query param and
89
+ `Authorization` headers.
90
+
82
91
  ## Bugs? Feature requests? Pull requests?
83
92
 
84
93
  Email me or submit via issue/pull request.
@@ -3,10 +3,11 @@ require 'httparty'
3
3
  module Capcoauth
4
4
  class CallbackController < Capcoauth::ApplicationController
5
5
  def show
6
+
6
7
  # Abort if code not found
7
8
  return redirect_to root_url, alert: 'Authorization was canceled' unless params[:code].present?
8
9
 
9
- response = HTTParty.post('https://capcoauth.capco.com/oauth/token', {
10
+ response = ::HTTParty.post("#{Capcoauth.configuration.capcoauth_url}/oauth/token", {
10
11
  body: {
11
12
  client_id: Capcoauth.configuration.client_id,
12
13
  client_secret: Capcoauth.configuration.client_secret,
@@ -3,12 +3,20 @@ require 'uri'
3
3
  module Capcoauth
4
4
  class LoginController < Capcoauth::ApplicationController
5
5
  def show
6
- if capcoauth_token
7
- redirect_to session[:previous_url].blank? ? root_url : session.delete(:previous_url), notice: 'You are already logged in'
8
- return
6
+
7
+ # If set in session
8
+ if session[:capcoauth_access_token]
9
+
10
+ # Attempt to verify
11
+ begin
12
+ capcoauth_token.verify
13
+ redirect_to session.delete(:previous_url) || root_url, notice: 'You are already logged in'
14
+ return
15
+ rescue; end
9
16
  end
10
17
 
11
- redirect_to "https://capcoauth.capco.com/oauth/authorize?client_id=#{Capcoauth.configuration.client_id}&redirect_uri=#{URI.encode(oauth_callback_url)}&response_type=code"
18
+ # Otherwise, redirect
19
+ redirect_to "#{Capcoauth.configuration.capcoauth_url}/oauth/authorize?client_id=#{Capcoauth.configuration.client_id}&redirect_uri=#{URI.encode(oauth_callback_url)}&response_type=code"
12
20
  end
13
21
  end
14
22
  end
@@ -1,10 +1,10 @@
1
1
  module Capcoauth
2
2
  class LogoutController < Capcoauth::ApplicationController
3
-
4
3
  def show
5
4
  session.delete(:capcoauth_user_id)
6
- if token = session.delete(:capcoauth_access_token)
7
- OAuth::TTLCache.delete(token)
5
+ token = session.delete(:capcoauth_access_token)
6
+ if token
7
+ OAuth::TTLCache.remove(token)
8
8
  redirect_to root_url, notice: 'You have been logged out'
9
9
  else
10
10
  redirect_to root_url
data/capcoauth.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
  # s.test_files = `git ls-files -- spec/*`.split("\n")
17
17
  s.require_paths = ['lib']
18
18
 
19
- s.add_dependency 'railties', '~> 4.2'
19
+ s.add_dependency 'railties', ['>= 4.2', '< 6.0']
20
20
  s.add_dependency 'httparty', '~> 0.13'
21
21
 
22
22
  s.add_development_dependency 'rake', '~> 10.5'
@@ -16,6 +16,8 @@ module Capcoauth
16
16
  class Config
17
17
  attr_reader :client_id
18
18
  attr_reader :client_secret
19
+ attr_reader :logger
20
+ attr_accessor :using_routes
19
21
 
20
22
  class Builder
21
23
  def initialize(&block)
@@ -34,6 +36,10 @@ module Capcoauth
34
36
  def client_secret(client_secret)
35
37
  @config.instance_variable_set('@client_secret', client_secret)
36
38
  end
39
+
40
+ def logger(logger)
41
+ @config.instance_variable_set('@logger', logger)
42
+ end
37
43
  end
38
44
 
39
45
  module Option
@@ -67,5 +73,6 @@ module Capcoauth
67
73
  extend Option
68
74
 
69
75
  option :token_verify_ttl, default: 10
76
+ option :capcoauth_url, default: 'https://capcoauth.capco.com'
70
77
  end
71
78
  end
@@ -3,10 +3,8 @@ module Capcoauth
3
3
  module Controller
4
4
  extend ActiveSupport::Concern
5
5
 
6
- private
7
-
8
6
  def capcoauth_token
9
- @token ||= OAuth::AccessToken.new(session[:capcoauth_access_token]).verify
7
+ @capcoauth_token ||= OAuth::AccessToken.new(session[:capcoauth_access_token])
10
8
  end
11
9
 
12
10
  def oauth_callback_url
@@ -1,27 +1,50 @@
1
+ require 'httparty'
2
+
1
3
  module Capcoauth
2
4
  module OAuth
3
5
  class TokenVerifier
6
+
7
+ class UnauthorizedError < StandardError; end
8
+ class OtherError < StandardError; end
9
+
4
10
  def self.verify(access_token)
5
- return nil if access_token.blank? or access_token.token.blank?
11
+ raise UnauthorizedError if access_token.blank? or access_token.token.blank?
6
12
  return access_token if TTLCache.valid?(access_token.token)
7
13
 
8
14
  # Call Capcoauth
9
- response = HTTParty.get('https://capcoauth.capco.com/oauth/token/info', {
15
+ response = ::HTTParty.get("#{Capcoauth.configuration.capcoauth_url}/oauth/token/info", {
10
16
  headers: {
11
- 'Authorization' => "Bearer #{access_token.token}"
17
+ :'Authorization' => "Bearer #{access_token.token}"
12
18
  }
13
19
  })
14
20
 
15
21
  # Set the user_id from the token response
16
22
  if response.code == 200
17
- TTLCache.update(access_token.token)
18
23
  access_token.user_id = response.parsed_response['resource_owner_id']
19
- access_token
20
- else
24
+ if response.parsed_response.fetch('application', {}).fetch('uid', nil) === Capcoauth.configuration.client_id
25
+ logger.info("CapcOAuth: The access token for user ##{access_token.user_id} was verified successfully") unless logger.nil?
26
+ TTLCache.update(access_token.token)
27
+ access_token
28
+ else
29
+ logger.info("CapcOAuth: The access token for user ##{access_token.user_id} was valid, but for a different OAuth client ID") unless logger.nil?
30
+ raise UnauthorizedError
31
+ end
32
+ elsif response.code == 401
21
33
  TTLCache.remove(access_token.token)
22
- nil
34
+ logger.info("CapcOAuth: The access token was invalid, expired, or revoked") unless logger.nil?
35
+ raise UnauthorizedError
36
+ else
37
+ logger.info("CapcOAuth: Received unknown response") unless logger.nil?
38
+ logger.info(JSON.pretty_generate(response)) unless logger.nil?
39
+ raise OtherError
23
40
  end
24
41
  end
42
+
43
+ private
44
+
45
+ def self.logger
46
+ Capcoauth.configuration.logger
47
+ end
25
48
  end
26
49
  end
27
50
  end
@@ -4,25 +4,74 @@ module Capcoauth
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  def verify_authorized!
7
- if capcoauth_token
7
+ return if request.method_symbol == :options
8
+ capcoauth_token.verify
9
+
10
+ # Browser client
11
+ if handle_sessions?
8
12
  session.delete(:previous_url)
9
- else
13
+ end
14
+
15
+ @current_user_id ||= capcoauth_token.user_id
16
+ rescue OAuth::TokenVerifier::UnauthorizedError
17
+ if handle_sessions?
18
+ session[:previous_url] = request.url
10
19
  session.delete(:capcoauth_access_token)
11
20
  session.delete(:capcoauth_user_id)
12
- session[:previous_url] = request.url
13
- redirect_to :auth_login
14
21
  end
22
+ handle_unauthorized
23
+ rescue OAuth::TokenVerifier::OtherError
24
+ if handle_sessions?
25
+ session.delete(:capcoauth_access_token)
26
+ session.delete(:capcoauth_user_id)
27
+ end
28
+ handle_internal_server_error
15
29
  end
16
30
 
17
31
  def current_user
18
- User.find session[:capcoauth_user_id] if session[:capcoauth_user_id]
32
+ @user ||= User.find_by_id verify_authorized!
19
33
  end
20
34
 
35
+ protected
36
+
37
+ def handle_unauthorized
38
+ if handle_sessions?
39
+ redirect_to :auth_login
40
+ else
41
+ render plain: 'Unauthorized', status: :unauthorized
42
+ end
43
+ end
44
+
45
+ def handle_internal_server_error
46
+ render plain: 'Internal server error', status: :internal_server_error
47
+ end
48
+
21
49
  private
22
50
 
23
- def capcoauth_token
24
- @_capcoauth_token ||= OAuth::AccessToken.new(session[:capcoauth_access_token]).verify
25
- end
51
+ def capcoauth_token
52
+ @_capcoauth_token ||= OAuth::AccessToken.new(token_from_request)
53
+ end
54
+
55
+ def token_from_request
56
+ token_from_param || token_from_session || token_from_headers
57
+ end
58
+
59
+ def token_from_param
60
+ params[:access_token]
61
+ end
62
+
63
+ def token_from_session
64
+ session[:capcoauth_access_token]
65
+ end
66
+
67
+ def token_from_headers
68
+ header_parts = (request.headers['AUTHORIZATION'] || '').split(' ')
69
+ (header_parts.length == 2 and header_parts[0].downcase == 'bearer') ? header_parts[1] : header_parts[0]
70
+ end
71
+
72
+ def handle_sessions?
73
+ request.format.html? and Capcoauth.configuration.using_routes
74
+ end
26
75
  end
27
76
  end
28
77
  end
@@ -7,6 +7,7 @@ module Capcoauth
7
7
  module Helper
8
8
  def use_capcoauth(options = {}, &block)
9
9
  Capcoauth::Rails::Routes.new(self, &block).generate_routes!(options)
10
+ Capcoauth.configuration.using_routes = true
10
11
  end
11
12
  end
12
13
 
@@ -1,3 +1,3 @@
1
1
  module Capcoauth
2
- VERSION = '0.1.4'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -1,11 +1,21 @@
1
1
  Capcoauth.configure do |config|
2
+
3
+ raise 'CapcOAuth Client ID not found' if ENV['CAPCOAUTH_CLIENT_ID'].nil?
4
+ raise 'CapcOAuth Client secret not found' if ENV['CAPCOAUTH_CLIENT_SECRET'].nil?
5
+
2
6
  # CapcOAuth Client ID
3
- config.client_id 'YOUR APPLICATION CLIENT ID'
7
+ config.client_id ENV['CAPCOAUTH_CLIENT_ID']
4
8
 
5
9
  # CapcOAuth Client Secret
6
- config.client_secret 'YOUR APPLICATION CLIENT SECRET'
10
+ config.client_secret ENV['CAPCOAUTH_CLIENT_SECRET']
7
11
 
8
12
  # Configures how often to check CapcOAuth for access token validity, in seconds. If this value is too high,
9
13
  # application will continue to serve requests to users even after the token is revoked
10
14
  # config.token_verify_ttl 10
15
+
16
+ # Configure CapcOAuth service URL
17
+ # config.capcoauth_url ENV['CAPCOAUTH_URL']
18
+
19
+ # Configure the logger to use for OAuth events
20
+ config.logger Rails.logger
11
21
  end
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capcoauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Robertson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-07 00:00:00.000000000 Z
11
+ date: 2016-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '4.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '6.0'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '4.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '6.0'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: httparty
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -79,7 +85,6 @@ files:
79
85
  - README.md
80
86
  - Rakefile
81
87
  - app/controllers/capcoauth/application_controller.rb
82
- - app/controllers/capcoauth/application_metal_controller.rb
83
88
  - app/controllers/capcoauth/callback_controller.rb
84
89
  - app/controllers/capcoauth/login_controller.rb
85
90
  - app/controllers/capcoauth/logout_controller.rb
@@ -119,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
124
  version: '0'
120
125
  requirements: []
121
126
  rubyforge_project:
122
- rubygems_version: 2.4.8
127
+ rubygems_version: 2.5.1
123
128
  signing_key:
124
129
  specification_version: 4
125
130
  summary: Integration with Capcoauth authentication service
@@ -1,15 +0,0 @@
1
- module Capcoauth
2
- class ApplicationMetalController < ActionController::Metal
3
- MODULES = [
4
- ActionController::Instrumentation,
5
- AbstractController::Rendering,
6
- ActionController::Rendering,
7
- ActionController::Renderers::All,
8
- Helpers::Controller
9
- ]
10
-
11
- MODULES.each do |mod|
12
- include mod
13
- end
14
- end
15
- end