oauth_im 0.8.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -43
- data/app/controllers/concerns/oauth_im/authenticable.rb +9 -11
- data/app/controllers/oauth_im/client_controller.rb +3 -4
- data/app/services/oauth_im/client.rb +10 -69
- data/app/services/oauth_im/idp_client.rb +16 -0
- data/app/services/oauth_im/registration_client.rb +16 -0
- data/app/services/oauth_im/request_client.rb +76 -0
- data/app/services/oauth_im/user_client.rb +57 -0
- data/config/initializers/app_context.rb +1 -3
- data/lib/oauth_im/configuration.rb +1 -0
- data/lib/oauth_im/version.rb +1 -1
- data/lib/oauth_im.rb +11 -6
- metadata +22 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: caff412768b7a6411078d84704899ce468379841ca548fc9271ec5e44a0bbc26
|
4
|
+
data.tar.gz: ca77658308ba2d2a432a9ed6f8fa23a0b59bce783804bc9298e10cf53fa6a89b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
21
|
-
|
22
|
-
|
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
|
32
|
-
|
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 :
|
38
|
-
to: :oauth_client
|
37
|
+
delegate :user_jwt, to: :oauth_client
|
39
38
|
|
40
39
|
def oauth_client
|
41
|
-
@oauth_client ||= OauthIm::Client.
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
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
|
data/lib/oauth_im/version.rb
CHANGED
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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 ||
|
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.
|
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-
|
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
|