oauth_im 0.8.2 → 0.9.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
  SHA256:
3
- metadata.gz: 7c32ade2f9c543728b3946076d1f8cad2566f06f4959c20b7c67613b6c296240
4
- data.tar.gz: ad6148ef5c4bed447ee4468ef03825a5802b9df3f3a0dd096bda20f4024b803a
3
+ metadata.gz: caff412768b7a6411078d84704899ce468379841ca548fc9271ec5e44a0bbc26
4
+ data.tar.gz: ca77658308ba2d2a432a9ed6f8fa23a0b59bce783804bc9298e10cf53fa6a89b
5
5
  SHA512:
6
- metadata.gz: 4824f3121b1ee2e24c0f706041c0295335a9efd35317442c5e1c857836224b88713ee61d1d1ae0694d01acd8559ef363ad44047393bb2b00128af96a97b60603
7
- data.tar.gz: 656cbad5b4111347e5b0f277fcb99d9ac794fc8defccc1d49cb0637d1971d21f900315ab731f6d3eec16b9606f4b2de2902028d8a6bb8ddc13630a74aa261b78
6
+ metadata.gz: 6efbc2ea50fc30a26166b86c9abc9bb927c82faa70f6a693101b8761d4e10c8e071ca2cc14e726e0e1c3cecd08ae71cb2e2734de67278e383b84ece88401878a
7
+ data.tar.gz: afc164c6542ca85cd3206451cead14ebe4fca9293d0d819cd544ed7347ba7ed8eacf4dd9a85045b69a046a44871380871b934aeaeb34e42c14baf24879863c38
data/README.md CHANGED
@@ -17,49 +17,9 @@ $ bundle
17
17
  ```
18
18
 
19
19
  ## Configuration
20
- Once the gem is installed, add an initializer. Here is an example:
21
-
22
- ```ruby
23
- # config/initializers/oauth_im.rb
24
- module OauthIm
25
- configure do |config|
26
- #####################################
27
- # these routes are local to the app #
28
- #####################################
29
- config.authorize_url = ENV.fetch 'FUSION_AUTH_AUTHORIZE_URL', DEFAULT_AUTHORIZE_URL
30
- config.callback_route = ENV.fetch 'FUSION_CALLBACK_ROUTE', DEFAULT_CALLBACK_ROUTE
31
- config.token_url = ENV.fetch 'FUSION_AUTH_TOKEN_URL', DEFAULT_TOKEN_URL
32
-
33
- ##############################################
34
- # identity provider url (e.g., fusion auth): #
35
- ##############################################
36
- config.idp_url = ENV.fetch 'FUSION_AUTH_IDP_URL', DEFAULT_IDP_URL
37
-
38
- ################################################
39
- # Issuer domain: find on FA tenant General tab #
40
- ################################################
41
- config.iss_domain = ENV.fetch 'FUSION_AUTH_ISS_DOMAIN', DEFAULT_ISS_DOMAIN
42
-
43
- ####################################
44
- # find on FA application OAuth tab #
45
- ####################################
46
- config.client_id = ENV['FUSION_AUTH_CLIENT_ID']
47
- config.client_secret = ENV['FUSION_AUTH_CLIENT_SECRET']
48
-
49
- ####################################################################################
50
- # 1. Find signing key name on the app details pane. (See RSA v. HMAC screenshots.) #
51
- # 2. Look up the key (by name) under Key Master tab under Settings: #
52
- # https://illustrativemath-dev.fusionauth.io/admin/key/ #
53
- # 3. The key should be either HMAC or RSA. #
54
- # - If HMAC, view the Secret under Details. You will need to click to reveal. #
55
- # - If RSA, copy the PEM encoded public key as-is. #
56
- # Note: You don't need both keys --- TokenDecoder will use the one available. #
57
- ####################################################################################
58
- config.hmac = ENV['FUSION_AUTH_HMAC']
59
- config.rsa_public = ENV['FUSION_AUTH_RSA_PUBLIC]
60
- end
61
- end
62
- ```
20
+ Once the gem is installed, add an initializer. The [iiab
21
+ app](https://github.com/illustrativemathematics/iiab/blob/master/config/initializers/oauth_im.rb)
22
+ provides an example.
63
23
 
64
24
  ### Environment
65
25
 
@@ -179,6 +139,14 @@ After many false starts, this repo includes two (seemingly functional) github wo
179
139
 
180
140
  ## Version History
181
141
 
142
+ ### 0.8.3
143
+ * Consolidate all OAuth (FusionAuth) functionality
144
+ * the register app can now include this gem for OAuth to create users
145
+ * IIAB can include this gem to authenticate users
146
+ * IIAB can include this gem to determine user privileges
147
+ * Relax Rails version constraint in Gemfile
148
+ * necessary in order for register app to use gem
149
+
182
150
  ### 0.8.2
183
151
  * README
184
152
 
@@ -11,25 +11,23 @@ module OauthIm
11
11
 
12
12
  private
13
13
 
14
+ delegate :email, :email_verified?,
15
+ :user_privileges,
16
+ to: :user_client,
17
+ allow_nil: true
18
+
14
19
  def authenticated?
15
20
  AppContext.authenticated_for_specs? ||
16
21
  (AppContext.provide_authentication? && logged_in?)
17
22
  end
18
23
 
19
- def email
20
- @email ||= jwt_token['email']
21
- end
22
-
23
24
  def user_jwt
24
- @user_jwt ||= session[:user_jwt] || {}
25
- end
26
-
27
- def jwt_token
28
- @jwt_token ||= user_jwt['value']&.first || {}
25
+ @user_jwt ||= session[:user_jwt]
29
26
  end
30
27
 
31
- def email_verified?
32
- jwt_token.present? && jwt_token['email_verified'].present?
28
+ def user_client
29
+ @user_client ||= OauthIm::Client.for(user_jwt: user_jwt) if
30
+ user_jwt.present?
33
31
  end
34
32
 
35
33
  def current_user
@@ -15,7 +15,7 @@ module OauthIm
15
15
 
16
16
  def logout
17
17
  reset_session
18
- redirect_to logout_url
18
+ redirect_to oauth_client.logout_url
19
19
  end
20
20
 
21
21
  def local_login
@@ -34,11 +34,10 @@ module OauthIm
34
34
 
35
35
  private
36
36
 
37
- delegate :logout_url, :user_jwt,
38
- to: :oauth_client
37
+ delegate :user_jwt, to: :oauth_client
39
38
 
40
39
  def oauth_client
41
- @oauth_client ||= OauthIm::Client.new request: request
40
+ @oauth_client ||= OauthIm::Client.for request: request
42
41
  end
43
42
 
44
43
  def local_login_userinfo
@@ -2,75 +2,16 @@
2
2
 
3
3
  module OauthIm
4
4
  class Client
5
- attr_reader :request
6
-
7
- def initialize(request:)
8
- @request = request
9
- end
10
-
11
- def login_url
12
- @login_url ||= auth_code.authorize_url
13
- end
14
-
15
- def logout_url
16
- @logout_url ||= "#{idp_url}/oauth2/logout" \
17
- "?post_logout_redirect_uri=#{return_to_url}" \
18
- "&client_id=#{client_id}"
19
- end
20
-
21
- def user_jwt
22
- @user_jwt ||= { value: decoded_token, httponly: httponly? }
23
- end
24
-
25
- private
26
-
27
- delegate :host_with_port, :params, to: :request
28
- delegate :configuration, to: OauthIm
29
- delegate :authorize_url, :token_url, :idp_url, :client_id, :client_secret,
30
- to: :configuration
31
- delegate :auth_code, to: :oauth_client
32
-
33
- def httponly?
34
- true
35
- end
36
-
37
- def return_to_url
38
- @return_to_url ||= params.fetch :return_to
39
- end
40
-
41
- def redirect_url
42
- @redirect_url ||=
43
- Engine.routes.url_helpers.callback_url callback_url_params
44
- end
45
-
46
- def callback_url_params
47
- @callback_url_params ||= { host: host_with_port,
48
- protocol: protocol }.freeze
49
- end
50
-
51
- def protocol
52
- @protocol ||= Rails.env.production? ? :https : :http
53
- end
54
-
55
- def decoded_token
56
- @decoded_token ||= TokenDecoder.new(access_token, oauth_client.id).decode
57
- end
58
-
59
- def access_token
60
- @access_token ||= response_hash[:access_token]
61
- end
62
-
63
- def oauth_client
64
- @oauth_client ||= ::OAuth2::Client.new client_id,
65
- client_secret,
66
- authorize_url: authorize_url,
67
- site: idp_url,
68
- token_url: token_url,
69
- redirect_uri: redirect_url
70
- end
71
-
72
- def response_hash
73
- @response_hash ||= auth_code.get_token(params[:code]).to_hash
5
+ def self.for(request: nil, user_jwt: nil, secure_id: nil)
6
+ if request.present?
7
+ RequestClient.new request: request
8
+ elsif user_jwt.present?
9
+ UserClient.new user_jwt: user_jwt
10
+ elsif secure_id.present?
11
+ RegistrationClient.new secure_id: secure_id
12
+ else
13
+ raise ArgumentError
14
+ end
74
15
  end
75
16
  end
76
17
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fusionauth/fusionauth_client'
4
+
5
+ module OauthIm
6
+ class IdpClient
7
+ private
8
+
9
+ delegate :configuration, to: OauthIm
10
+ delegate :api_key, :idp_url, to: :configuration
11
+
12
+ def client
13
+ @client ||= ::FusionAuth::FusionAuthClient.new api_key, idp_url
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OauthIm
4
+ class RegistrationClient < IdpClient
5
+ attr_reader :secure_id
6
+
7
+ def initialize(secure_id:)
8
+ @secure_id = secure_id
9
+ super()
10
+ end
11
+
12
+ def register(submission_params:)
13
+ client.register secure_id, submission_params
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OauthIm
4
+ class RequestClient
5
+ attr_reader :request
6
+
7
+ def initialize(request:)
8
+ @request = request
9
+ end
10
+
11
+ def login_url
12
+ @login_url ||= auth_code.authorize_url
13
+ end
14
+
15
+ def logout_url
16
+ @logout_url ||= "#{idp_url}/oauth2/logout" \
17
+ "?post_logout_redirect_uri=#{return_to_url}" \
18
+ "&client_id=#{client_id}"
19
+ end
20
+
21
+ def user_jwt
22
+ @user_jwt ||= { value: decoded_token, httponly: httponly? }
23
+ end
24
+
25
+ private
26
+
27
+ delegate :host_with_port, :params, to: :request
28
+ delegate :configuration, to: OauthIm
29
+ delegate :authorize_url, :token_url, :idp_url, :client_id, :client_secret,
30
+ to: :configuration
31
+ delegate :auth_code, to: :oauth_client
32
+
33
+ def httponly?
34
+ true
35
+ end
36
+
37
+ def return_to_url
38
+ @return_to_url ||= params.fetch :return_to
39
+ end
40
+
41
+ def redirect_url
42
+ @redirect_url ||=
43
+ Engine.routes.url_helpers.callback_url callback_url_params
44
+ end
45
+
46
+ def callback_url_params
47
+ @callback_url_params ||= { host: host_with_port,
48
+ protocol: protocol }.freeze
49
+ end
50
+
51
+ def protocol
52
+ @protocol ||= Rails.env.production? ? :https : :http
53
+ end
54
+
55
+ def decoded_token
56
+ @decoded_token ||= TokenDecoder.new(access_token, oauth_client.id).decode
57
+ end
58
+
59
+ def access_token
60
+ @access_token ||= response_hash[:access_token]
61
+ end
62
+
63
+ def oauth_client
64
+ @oauth_client ||= ::OAuth2::Client.new client_id,
65
+ client_secret,
66
+ authorize_url: authorize_url,
67
+ site: idp_url,
68
+ token_url: token_url,
69
+ redirect_uri: redirect_url
70
+ end
71
+
72
+ def response_hash
73
+ @response_hash ||= auth_code.get_token(params[:code]).to_hash
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fusionauth/fusionauth_client'
4
+
5
+ module OauthIm
6
+ class UserClient < IdpClient
7
+ attr_reader :user_jwt
8
+
9
+ def initialize(user_jwt:)
10
+ @user_jwt = user_jwt&.with_indifferent_access
11
+ super()
12
+ end
13
+
14
+ def email
15
+ @email ||= jwt_token[:email]
16
+ end
17
+
18
+ def email_verified?
19
+ email.present?
20
+ end
21
+
22
+ def user_privileges
23
+ @user_privileges ||= data[:privileges] || []
24
+ end
25
+
26
+ private
27
+
28
+ def user_data
29
+ @user_data ||= user[:registrations]&.first || {}
30
+ end
31
+
32
+ def data
33
+ @data ||= user_data[:data] || {}
34
+ end
35
+
36
+ def success_response
37
+ @success_response ||= client_response&.success_response || {}
38
+ end
39
+
40
+ def user
41
+ @user ||= success_response[:user] || {}
42
+ end
43
+
44
+ # https://www.rubydoc.info/gems/fusionauth_client/1.32.1/FusionAuth/FusionAuthClient#retrieve_user-instance_method
45
+ def client_response
46
+ @client_response ||= client.retrieve_user user_id
47
+ end
48
+
49
+ def jwt_token
50
+ @jwt_token ||= user_jwt[:value]&.first&.with_indifferent_access || {}
51
+ end
52
+
53
+ def user_id
54
+ @user_id ||= jwt_token[:sub]
55
+ end
56
+ end
57
+ end
@@ -17,15 +17,13 @@ module AppContext
17
17
  @authenticated_for_specs if Rails.env.test? && provide_authentication?
18
18
  end
19
19
 
20
- def self.authenticate_for_specs(spec_user: nil, privileged: false)
20
+ def self.authenticate_for_specs(spec_user: nil)
21
21
  return unless provide_authentication?
22
22
  raise 'Use only in test environment!!' unless Rails.env.test?
23
23
 
24
24
  @authenticated_for_specs = true
25
25
  @spec_user = spec_user
26
- @privileged = privileged
27
26
  yield
28
- @privileged = false
29
27
  @spec_user = nil
30
28
  @authenticated_for_specs = false
31
29
  end
@@ -7,6 +7,7 @@
7
7
  module OauthIm
8
8
  CONFIGURABLE_FIELDS =
9
9
  %i[
10
+ api_key
10
11
  authorize_url
11
12
  callback_route
12
13
  token_url
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OauthIm
4
- VERSION = '0.8.2'
4
+ VERSION = '0.9.0'
5
5
  end
data/lib/oauth_im.rb CHANGED
@@ -9,11 +9,16 @@ require 'oauth_im/engine'
9
9
  require 'oauth_im/configuration'
10
10
 
11
11
  module OauthIm
12
- DEFAULT_AUTHORIZE_URL = '/oauth2/authorize'
13
- DEFAULT_CALLBACK_ROUTE = 'callback'
14
- DEFAULT_TOKEN_URL = '/oauth2/token'
15
- DEFAULT_IDP_URL = 'https://illustrativemath-dev.fusionauth.io'
16
- DEFAULT_ISS_DOMAIN = 'illustrativemathematics.org'
12
+ DEFAULT_AUTH_AUTHORIZE_URL = '/oauth2/authorize'
13
+ DEFAULT_AUTH_CALLBACK_ROUTE = 'callback'
14
+ DEFAULT_AUTH_TOKEN_URL = '/oauth2/token'
15
+ DEFAULT_AUTH_IDP_URL = 'https://illustrativemath-dev.fusionauth.io'
16
+ DEFAULT_AUTH_ISS_DOMAIN = 'illustrativemathematics.org'
17
+ DEFAULT_AUTH_API_KEY = nil
18
+ DEFAULT_AUTH_CLIENT_ID = nil
19
+ DEFAULT_AUTH_CLIENT_SECRET = nil
20
+ DEFAULT_AUTH_HMAC = nil
21
+ DEFAULT_AUTH_RSA_PUBLIC = nil
17
22
 
18
23
  class << self
19
24
  attr_reader :configuration
@@ -29,6 +34,6 @@ module OauthIm
29
34
  end
30
35
 
31
36
  def self.callback_route
32
- configuration&.callback_route || DEFAULT_CALLBACK_ROUTE
37
+ configuration&.callback_route || DEFAULT_AUTH_CALLBACK_ROUTE
33
38
  end
34
39
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oauth_im
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Connally
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-08 00:00:00.000000000 Z
11
+ date: 2022-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fusionauth_client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.32.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.32.1
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: jwt
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -42,14 +56,14 @@ dependencies:
42
56
  name: rails
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - "~>"
59
+ - - ">="
46
60
  - !ruby/object:Gem::Version
47
61
  version: 5.pre.2.pre.stable
48
62
  type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - "~>"
66
+ - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: 5.pre.2.pre.stable
55
69
  - !ruby/object:Gem::Dependency
@@ -126,7 +140,11 @@ files:
126
140
  - app/controllers/oauth_im/client_controller.rb
127
141
  - app/helpers/oauth_im/application_helper.rb
128
142
  - app/services/oauth_im/client.rb
143
+ - app/services/oauth_im/idp_client.rb
144
+ - app/services/oauth_im/registration_client.rb
145
+ - app/services/oauth_im/request_client.rb
129
146
  - app/services/oauth_im/token_decoder.rb
147
+ - app/services/oauth_im/user_client.rb
130
148
  - app/views/layouts/oauth_im/application.html.erb
131
149
  - config/initializers/app_context.rb
132
150
  - config/routes.rb