capcoauth 0.1.4 → 0.2.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.
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