authorio 0.8.4 → 0.8.5

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
  SHA256:
3
- metadata.gz: 78659edadab6ff85d24828c318525bac7b62b4a76b9905e0a1d819ec266f9d46
4
- data.tar.gz: 817fe77d1c1fd89e68df07a594725997d598e0f0027210d083762da50cb447fd
3
+ metadata.gz: e4cd85ad8ec9b0e70f4d276f7c600d5cc3ebab5b04f0f0313da9f6151e78d680
4
+ data.tar.gz: 7ec85565cc8fb4ea711836ab8069f7062929d13af6f1520809095bdee7c859b9
5
5
  SHA512:
6
- metadata.gz: 8205bfe7bc6798f560da3f56b19f26822653d6f6fb8baac925be38a713f871e1faf90f0492ea25187124cd98db928a7d875da47b53faf14afe1efc6418498dbd
7
- data.tar.gz: 3c772c7777f016316911f36573f5d2982ca27a40edb18dcac16782fb380021971feaeea4271adebe411101b39a9bb544d3f27f88dec93d72aae6f0e5adc483fd
6
+ metadata.gz: 845bc518d44332a7e71eabd020da0f450979dcf35ec35539850ee40b931c270c7c89f6205fa021b27b78b86c07fbcd1b36354c49c79c28d6e5d2b8ea501aad00
7
+ data.tar.gz: ca1f67ba7804bd630ce55713cfd1c3f2b542f04781583ec165073c1ad0eea829bef439d362af9e302e530da8ccc650736b00039b1151e7559b1cb8b8cdcc64b2
@@ -50,7 +50,7 @@ div.authorio-auth {
50
50
  margin: 0.1em;
51
51
  }
52
52
 
53
- .authorio-auth .auth-btn-row .auth-btn:last-child {
53
+ .authorio-auth .auth-btn-row .btn-success {
54
54
  float: right;
55
55
  }
56
56
 
@@ -2,9 +2,6 @@
2
2
 
3
3
  module Authorio
4
4
  class AuthController < AuthorioController
5
- require 'uri'
6
- require 'digest'
7
-
8
5
  # These API-only endpoints are protected by code challenge and do not need CSRF protextion
9
6
  protect_from_forgery with: :exception, except: %i[send_profile issue_token]
10
7
 
@@ -31,22 +28,19 @@ module Authorio
31
28
  def authorize_user
32
29
  redirect_to session[:client_id] and return if params[:commit] == 'Cancel'
33
30
 
34
- user = authenticate_user_from_session_or_password
35
- write_session_cookie(user) if auth_user_params[:remember_me]
36
- redirect_to_client(user)
31
+ @user = authenticate_user_from_session_or_password
32
+ write_session_cookie(@user) if auth_user_params[:remember_me]
33
+ create_auth_request
34
+ redirect_to_client
37
35
  end
38
36
 
39
37
  def send_profile
40
- @request = validate_request Request.find_by! code: params[:code]
41
- rescue Exceptions::InvalidGrant, ActiveRecord::RecordNotFound => e
42
- render oauth_error 'invalid_grant', e.message
38
+ @auth_request = find_auth_request or (render validation_failed and return)
43
39
  end
44
40
 
45
41
  def issue_token
46
- @request = validate_request Request.find_by! code: params[:code]
47
- @token = Token.create_from_request(@request)
48
- rescue Exceptions::InvalidGrant, ActiveRecord::RecordNotFound => e
49
- render oauth_error 'invalid_grant', e.message
42
+ @auth_request = find_auth_request or (render validation_failed and return)
43
+ @token = Token.create_from_request(@auth_request)
50
44
  end
51
45
 
52
46
  def verify_token
@@ -61,14 +55,10 @@ module Authorio
61
55
 
62
56
  def auth_interface_params
63
57
  @auth_interface_params ||= begin
64
- required = %w[client_id redirect_uri state code_challenge]
65
- permitted = %w[me scope code_challenge_method response_type action controller]
66
- missing = required - params.keys
67
- raise ::ActionController::ParameterMissing, missing unless missing.empty?
68
-
69
- unpermitted = params.keys - required - permitted
70
- raise ::ActionController::UnpermittedParameters, unpermitted unless unpermitted.empty?
71
-
58
+ required = %w[client_id redirect_uri state]
59
+ permitted = %w[me scope code_challenge_method response_type code_challenge dummy]
60
+ params.require(required)
61
+ params.permit(permitted + required)
72
62
  params.permit!
73
63
  end
74
64
  end
@@ -86,27 +76,26 @@ module Authorio
86
76
  oauth_error('invalid_token', 'The access token has expired', :unauthorized)
87
77
  end
88
78
 
89
- def code_challenge_failed?
90
- # For now, if original request did not have code challenge, then we pass by default
91
- return unless session[:code_challenge]
92
-
93
- sha256 = Digest::SHA256.hexdigest params[:code_verifier]
94
- Base64.urlsafe_encode64(sha256) != session[:code_challenge]
79
+ def validation_failed
80
+ oauth_error('invalid_grant', 'validation failed')
95
81
  end
96
82
 
97
- def validate_request(request)
98
- raise Exceptions::InvalidGrant, 'validation failed' if request.invalid?(params) || code_challenge_failed?
83
+ def find_auth_request
84
+ auth_request = Request.find_by code: params[:code]
85
+ auth_request&.validate_oauth params
86
+ end
99
87
 
100
- request
88
+ def create_auth_request
89
+ @auth_req = Request.create(client: session[:client_id],
90
+ redirect_uri: session[:redirect_uri],
91
+ code_challenge: (session[:code_challenge] if session.key? :code_challenge),
92
+ scope: (scope_params[:scope].join(' ') if params.key? :scope),
93
+ authorio_user: @user)
101
94
  end
102
95
 
103
- def redirect_to_client(user)
104
- auth_req = Request.create(client: session[:client_id],
105
- redirect_uri: session[:redirect_uri],
106
- scope: (scope_params[:scope].join(' ') if params.key? :scope),
107
- authorio_user: user)
108
- redirect_params = { code: auth_req.code, state: session[:state] }
109
- redirect_to "#{auth_req.redirect_uri}?#{redirect_params.to_query}"
96
+ def redirect_to_client
97
+ redirect_params = { code: @auth_req.code, state: session[:state] }
98
+ redirect_to "#{@auth_req.redirect_uri}?#{redirect_params.to_query}"
110
99
  end
111
100
 
112
101
  def authenticate_user_from_session_or_password
@@ -16,10 +16,20 @@ module Authorio
16
16
  self.client = value
17
17
  end
18
18
 
19
- def invalid?(params)
20
- redirect_uri != params[:redirect_uri] ||
21
- client != params[:client_id] ||
22
- created_at < Time.now - 10.minutes
19
+ def validate_oauth(params)
20
+ redirect_uri == params[:redirect_uri] &&
21
+ client == params[:client_id] &&
22
+ created_at > 10.minutes.ago &&
23
+ code_challenge_matches(params[:code_verifier]) &&
24
+ self
25
+ end
26
+
27
+ def code_challenge_matches(verifier)
28
+ # For now, if original request did not have code challenge, then we pass by default
29
+ return true if code_challenge.blank?
30
+
31
+ sha256 = Digest::SHA256.digest verifier
32
+ Base64.urlsafe_encode64(sha256).sub(/=*$/, '') == code_challenge
23
33
  end
24
34
 
25
35
  def self.user_scope_description(scope)
@@ -38,8 +48,7 @@ module Authorio
38
48
 
39
49
  USER_SCOPE_DESCRIPTION = {
40
50
  profile: 'View basic profile information',
41
- email: 'View your email address',
42
- offline_access: 'Keep you logged in permanently (until revoked)'
51
+ email: 'View your email address'
43
52
  }.freeze
44
53
  end
45
54
  end
@@ -4,4 +4,4 @@ json.access_token @token.auth_token
4
4
  json.expires_in Authorio.configuration.token_expiration
5
5
  json.token_type 'Bearer'
6
6
  json.scope @token.scope
7
- json.partial! 'authorio/users/profile', request: @request
7
+ json.partial! 'authorio/users/profile', request: @auth_request
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- json.me profile_url(request.authorio_user)
4
- if request.scope&.include? 'profile'
3
+ json.me profile_url(@auth_request.authorio_user)
4
+ if @auth_request.scope&.include? 'profile'
5
5
  json.profile do
6
- json.name(request.authorio_user.full_name)
7
- json.call(request.authorio_user, :url, :photo)
8
- json.email(request.authorio_user.email) if request.scope.include?('email')
6
+ json.name(@auth_request.authorio_user.full_name)
7
+ json.call(@auth_request.authorio_user, :url, :photo)
8
+ json.email(@auth_request.authorio_user.email) if @auth_request.scope.include?('email')
9
9
  end
10
10
  end
@@ -33,9 +33,9 @@
33
33
  <% end %>
34
34
  <% end -%>
35
35
  <div class='auth-btn-row'>
36
+ <%= form.submit("Sign in", class: 'btn btn-success auth-btn') %>
36
37
  <% if cancel %>
37
38
  <%= form.submit("Cancel", class: 'btn btn-default auth-btn') %>
38
39
  <% end %>
39
- <%= form.submit("Sign in", class: 'btn btn-success auth-btn') %>
40
40
  </div>
41
41
  <% end %>
@@ -0,0 +1,5 @@
1
+ class AddCodeChallengeToRequests < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :authorio_requests, :code_challenge, :string
4
+ end
5
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Authorio
4
- VERSION = '0.8.4'
4
+ VERSION = '0.8.5'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authorio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.4
4
+ version: 0.8.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Meckler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-25 00:00:00.000000000 Z
11
+ date: 2021-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -157,6 +157,7 @@ files:
157
157
  - db/migrate/20210726164625_create_authorio_sessions.rb
158
158
  - db/migrate/20210801184120_add_profile_to_users.rb
159
159
  - db/migrate/20210817010101_change_path_to_username_in_users.rb
160
+ - db/migrate/20210831155106_add_code_challenge_to_requests.rb
160
161
  - lib/authorio.rb
161
162
  - lib/authorio/configuration.rb
162
163
  - lib/authorio/engine.rb
@@ -187,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
188
  - !ruby/object:Gem::Version
188
189
  version: '0'
189
190
  requirements: []
190
- rubygems_version: 3.2.11
191
+ rubygems_version: 3.1.6
191
192
  signing_key:
192
193
  specification_version: 4
193
194
  summary: Indieauth Authentication endpoint for Rails