devise_auth0 1.0.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 +7 -0
- data/CHANGELOG.md +30 -0
- data/LICENSE.md +22 -0
- data/app/controllers/devise/auth0_callbacks_controller.rb +23 -0
- data/lib/devise/auth0/client.rb +17 -0
- data/lib/devise/auth0/controllers/helpers.rb +43 -0
- data/lib/devise/auth0/exceptions.rb +23 -0
- data/lib/devise/auth0/helpers.rb +25 -0
- data/lib/devise/auth0/rails/routes.rb +37 -0
- data/lib/devise/auth0/rails.rb +50 -0
- data/lib/devise/auth0/token.rb +126 -0
- data/lib/devise/auth0/version.rb +13 -0
- data/lib/devise/auth0.rb +62 -0
- data/lib/devise/hooks/auth0.rb +7 -0
- data/lib/devise/models/auth0.rb +210 -0
- data/lib/devise/strategies/auth0.rb +43 -0
- data/lib/devise_auth0.rb +3 -0
- metadata +484 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c18b3f8598776472a2f76cf1b1dfa63b00f53cf0490a8088d663a4f54ecbef5b
|
4
|
+
data.tar.gz: 04a20bad11da869d3b9724f68d66a4b2382e3c26c98d481f9425c1589a756330
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8efc4197e1280051359ba69c9ddb8ed62fc70617eeaf65ddb518256ad6e1f11711cfee3651154cd4f9930e3401cc3ad29c68d8e0ad512df80a8e32e3b0c0d72d
|
7
|
+
data.tar.gz: b373a943d168c14277870c54eff0227077a5c8cfc6c14aaaab60de05a5782068aaf9efc3e5a769ccd87e840db54509385552f01cc53c8ac8c0dcfd352aab786b
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 1.0.0 (2023-09-08)
|
4
|
+
|
5
|
+
|
6
|
+
### Tests
|
7
|
+
|
8
|
+
* Fixes rspec-rails issues on rails edge ([ea4a050](https://github.com/itsmechlark/devise-auth0/commit/ea4a050528196936960d38b29edfb36a6e6cfcf1))
|
9
|
+
|
10
|
+
|
11
|
+
### Miscellaneous
|
12
|
+
|
13
|
+
* Bump changelog-enforcer to v3 ([5ffcab8](https://github.com/itsmechlark/devise-auth0/commit/5ffcab87952644b40cf73f45bce8cb2bd82ab534))
|
14
|
+
* Bump rubocop-shopify to v2.14 ([9102709](https://github.com/itsmechlark/devise-auth0/commit/91027094bbc243ef05fb10bfe2b9da91189ca8a4))
|
15
|
+
* Change Rubocop code scanning name ([ccae036](https://github.com/itsmechlark/devise-auth0/commit/ccae036e25f8f5d3d9fe0341e81d6b5b53af2df9))
|
16
|
+
* CI/CD workflow ([b82655d](https://github.com/itsmechlark/devise-auth0/commit/b82655d9a7af844f1a62d558e65799ef796951fc))
|
17
|
+
* Code scanning ([a2f9d1b](https://github.com/itsmechlark/devise-auth0/commit/a2f9d1b98994be941abfdba41346976cb717ba5a))
|
18
|
+
* Configure version file on release config ([53b3b5b](https://github.com/itsmechlark/devise-auth0/commit/53b3b5b4b88bc52bddee7bcee4cba1e889d21eda))
|
19
|
+
* Fixes Code Scanning permissions ([765f698](https://github.com/itsmechlark/devise-auth0/commit/765f698abe70f30a16b84549bb6256c22379d0fd))
|
20
|
+
* Fixes release please config ([fb8aba4](https://github.com/itsmechlark/devise-auth0/commit/fb8aba487088409c783c7022845be9677e22dd04))
|
21
|
+
* Fixes rubocop lint ([e02858b](https://github.com/itsmechlark/devise-auth0/commit/e02858b561f3d99691524795d43ae84fd5d8b978))
|
22
|
+
* Install bundler on DevContainer startup ([9ad89e4](https://github.com/itsmechlark/devise-auth0/commit/9ad89e43b1b1a99f06250c7bdc5b6006cd505cca))
|
23
|
+
* Move changelog type to release config ([01b4d9e](https://github.com/itsmechlark/devise-auth0/commit/01b4d9e02c981a3adc6c69fd64e9331838c3f618))
|
24
|
+
* Release Please config ([08af26d](https://github.com/itsmechlark/devise-auth0/commit/08af26d4002d3e89cb210cabd89ea768039193bc))
|
25
|
+
* Remove changelog ([bb7befe](https://github.com/itsmechlark/devise-auth0/commit/bb7befec90baad2c9f6f4671cb830a9e42491e11))
|
26
|
+
* Remove old changelog ([fae0a6c](https://github.com/itsmechlark/devise-auth0/commit/fae0a6cdad32a043c53820c78277df2c6acc872a))
|
27
|
+
* Support DevContainers ([5b937c9](https://github.com/itsmechlark/devise-auth0/commit/5b937c9696fea630eabaa9f4d745e4c64418e753))
|
28
|
+
* Test against Ruby 3.2 ([185bae5](https://github.com/itsmechlark/devise-auth0/commit/185bae5d12b17409e6ed62d0aa7be9870ca9c424))
|
29
|
+
* Update Changelog ([6df1d33](https://github.com/itsmechlark/devise-auth0/commit/6df1d33cf6810b752efc5bc4bf6d3f8691117847))
|
30
|
+
* Use Python 3.8 for codespell ([a6a8f35](https://github.com/itsmechlark/devise-auth0/commit/a6a8f3556ae54dd1ed0608eaa431772ef2ff1977))
|
data/LICENSE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 John Chlark Sumatra
|
4
|
+
Copyright (c) 2022 First Circle Growth Finance Corp.
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
8
|
+
in the Software without restriction, including without limitation the rights
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
11
|
+
furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in
|
14
|
+
all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
THE SOFTWARE.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
class Auth0CallbacksController < Devise::OmniauthCallbacksController
|
5
|
+
def callback
|
6
|
+
user = resource_class.from_auth0_omniauth(request.env["omniauth.auth"])
|
7
|
+
|
8
|
+
if user&.persisted?
|
9
|
+
set_flash_message(:notice, :success, kind: "Auth0") if is_navigational_format?
|
10
|
+
sign_in_and_redirect(user, event: :authentication)
|
11
|
+
else
|
12
|
+
session["devise.auth0_data"] = request.env["omniauth.auth"].except(:extra)
|
13
|
+
redirect_to(after_omniauth_callback_path_for(resource_name))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def after_omniauth_callback_path_for(scope)
|
20
|
+
new_session_path(scope)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "auth0"
|
4
|
+
|
5
|
+
module Devise
|
6
|
+
module Auth0
|
7
|
+
class Client < ::Auth0::Client
|
8
|
+
def initialize(config)
|
9
|
+
super(
|
10
|
+
client_id: config.client_id,
|
11
|
+
client_secret: config.client_secret,
|
12
|
+
domain: config.domain,
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "devise/auth0/exceptions"
|
4
|
+
|
5
|
+
module Devise
|
6
|
+
module Auth0
|
7
|
+
module Controllers
|
8
|
+
# Those helpers are convenience methods added to ApplicationController.
|
9
|
+
module Helpers
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
if respond_to?(:devise_group)
|
14
|
+
devise_group :auth0, contains: Devise.mappings.keys
|
15
|
+
end
|
16
|
+
|
17
|
+
if respond_to?(:helper_method)
|
18
|
+
helper_method :can?, :cannot?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def authorize!(*args)
|
23
|
+
options = args.extract_options!
|
24
|
+
message = options[:message]
|
25
|
+
|
26
|
+
if cannot?(*args)
|
27
|
+
raise AccessDenied.new(message, *args)
|
28
|
+
end
|
29
|
+
|
30
|
+
args
|
31
|
+
end
|
32
|
+
|
33
|
+
def can?(*args)
|
34
|
+
!!current_auth0&.can?(*args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def cannot?(*args)
|
38
|
+
!!current_auth0&.cannot?(*args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Auth0
|
5
|
+
# A general CanCan exception
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
8
|
+
class AccessDenied < Error
|
9
|
+
attr_reader :action, :subject
|
10
|
+
|
11
|
+
def initialize(message = nil, action = nil, resource_class = nil)
|
12
|
+
@message = message.presence || I18n.t(
|
13
|
+
:"unauthorized.default",
|
14
|
+
default: "You are not authorized to access this page.",
|
15
|
+
)
|
16
|
+
@action = action
|
17
|
+
@resource_class = resource_class
|
18
|
+
|
19
|
+
super(@message)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Auth0
|
5
|
+
# Helpers to parse token from a request and to a response
|
6
|
+
module Helpers
|
7
|
+
AUTH_METHOD = "Bearer"
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# Parses the token from a rack request
|
11
|
+
#
|
12
|
+
# @param env [Hash] rack env hash
|
13
|
+
# @return [String] JWT token
|
14
|
+
# @return [nil] if token is not present
|
15
|
+
def get_auth(env)
|
16
|
+
auth = env["HTTP_AUTHORIZATION"].presence
|
17
|
+
return unless auth
|
18
|
+
|
19
|
+
method, token = auth.split
|
20
|
+
method == AUTH_METHOD ? token : nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionDispatch
|
4
|
+
module Routing
|
5
|
+
class Mapper
|
6
|
+
protected
|
7
|
+
|
8
|
+
def devise_auth0_callback(mapping, controllers) # :nodoc:
|
9
|
+
return unless mapping.to.auth0_config.omniauth
|
10
|
+
|
11
|
+
path_prefix = Devise.omniauth_path_prefix || "/#{mapping.fullpath}/auth".squeeze("/")
|
12
|
+
set_omniauth_path_prefix!(path_prefix)
|
13
|
+
|
14
|
+
match(
|
15
|
+
"/auth/auth0",
|
16
|
+
to: "#{controllers[:auth0_callbacks]}#passthru",
|
17
|
+
as: :auth0_omniauth_authorize,
|
18
|
+
via: [:get, :post],
|
19
|
+
)
|
20
|
+
|
21
|
+
match(
|
22
|
+
"/auth/auth0/failure",
|
23
|
+
to: "#{controllers[:auth0_callbacks]}#failure",
|
24
|
+
as: :auth0_omniauth_failure,
|
25
|
+
via: [:get, :post],
|
26
|
+
)
|
27
|
+
|
28
|
+
match(
|
29
|
+
"/auth/auth0/callback",
|
30
|
+
to: "#{controllers[:auth0_callbacks]}#callback",
|
31
|
+
as: :auth0_omniauth_callback,
|
32
|
+
via: [:get, :post],
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "omniauth-auth0"
|
4
|
+
require "omniauth/rails_csrf_protection"
|
5
|
+
|
6
|
+
require "devise/auth0/rails/routes"
|
7
|
+
require "devise/auth0/controllers/helpers"
|
8
|
+
|
9
|
+
module Devise
|
10
|
+
module Auth0
|
11
|
+
class Engine < ::Rails::Engine
|
12
|
+
initializer "devise.auth0.cache", after: "initialize_cache" do |_app|
|
13
|
+
Devise.auth0.cache = Rails.cache
|
14
|
+
end
|
15
|
+
|
16
|
+
initializer "devise.auth0", before: "devise.omniauth" do |_app|
|
17
|
+
config = Devise.auth0
|
18
|
+
if config.omniauth
|
19
|
+
Devise.setup do |devise|
|
20
|
+
devise.omniauth(
|
21
|
+
:auth0,
|
22
|
+
config.client_id,
|
23
|
+
config.client_secret,
|
24
|
+
config.custom_domain,
|
25
|
+
{
|
26
|
+
authorize_params: {
|
27
|
+
audience: config.aud.join(","),
|
28
|
+
scope: config.scope,
|
29
|
+
},
|
30
|
+
},
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Patches the existing devise failure app to ensure a right mapping is used.
|
35
|
+
# Read more: devise/omniauth.rb
|
36
|
+
::OmniAuth.config.on_failure = proc do |env|
|
37
|
+
env["devise.mapping"] = ::Devise::Mapping.find_by_path!(env["PATH_INFO"], :fullpath)
|
38
|
+
controller_name = ActiveSupport::Inflector.camelize(env["devise.mapping"].controllers[:omniauth_callbacks])
|
39
|
+
controller_klass = ActiveSupport::Inflector.constantize("#{controller_name}Controller")
|
40
|
+
controller_klass.action(:failure).call(env)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
ActiveSupport.on_load(:action_controller) do
|
45
|
+
include Devise::Auth0::Controllers::Helpers
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "faraday"
|
4
|
+
require "faraday/http_cache"
|
5
|
+
require "jwt"
|
6
|
+
|
7
|
+
module Devise
|
8
|
+
module Auth0
|
9
|
+
# Helpers to parse token from a request and to a response
|
10
|
+
class Token
|
11
|
+
class << self
|
12
|
+
def parse(auth, resource_class)
|
13
|
+
token = new(auth, resource_class)
|
14
|
+
token.verify
|
15
|
+
token
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(auth, resource_class)
|
20
|
+
@auth = auth.presence
|
21
|
+
@resource_class = resource_class
|
22
|
+
end
|
23
|
+
|
24
|
+
def provider
|
25
|
+
auth0_id&.split("|")&.first
|
26
|
+
end
|
27
|
+
|
28
|
+
def uid
|
29
|
+
auth0_id&.split("|")&.last
|
30
|
+
end
|
31
|
+
|
32
|
+
def auth0_id
|
33
|
+
return if verify.nil?
|
34
|
+
return "auth0|#{verify[0]["azp"]}" if bot?
|
35
|
+
|
36
|
+
verify[0]["sub"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def user
|
40
|
+
@user ||= if bot?
|
41
|
+
{
|
42
|
+
"user_id" => uid,
|
43
|
+
"email" => "#{uid}@#{config.domain}",
|
44
|
+
}
|
45
|
+
else
|
46
|
+
::Devise.auth0.cache.fetch("devise-auth0/#{auth0_id}", expires_in: ::Devise.auth0.cache_expires_in) do
|
47
|
+
client.user(auth0_id)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def bot?
|
53
|
+
return false if verify.nil?
|
54
|
+
|
55
|
+
verify[0]["gty"] == "client-credentials"
|
56
|
+
end
|
57
|
+
|
58
|
+
def scopes
|
59
|
+
return [] if verify.nil?
|
60
|
+
|
61
|
+
verify[0]["scope"].to_s.split(" ")
|
62
|
+
end
|
63
|
+
|
64
|
+
def permissions
|
65
|
+
return [] if verify.nil?
|
66
|
+
|
67
|
+
verify[0]["permissions"].presence || []
|
68
|
+
end
|
69
|
+
|
70
|
+
def verify
|
71
|
+
@payload ||= JWT.decode(
|
72
|
+
@auth,
|
73
|
+
nil,
|
74
|
+
true, # Verify the signature of this token
|
75
|
+
algorithms: config.algorithm,
|
76
|
+
iss: issuer,
|
77
|
+
verify_iss: true,
|
78
|
+
aud: config.aud,
|
79
|
+
verify_aud: true,
|
80
|
+
) do |header|
|
81
|
+
jwks_hash[header["kid"]]
|
82
|
+
end
|
83
|
+
rescue JWT::DecodeError
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def valid?
|
88
|
+
!verify.nil?
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def config
|
94
|
+
@resource_class.auth0_config
|
95
|
+
end
|
96
|
+
|
97
|
+
def client
|
98
|
+
@resource_class.auth0_client
|
99
|
+
end
|
100
|
+
|
101
|
+
def issuer
|
102
|
+
"https://#{config.custom_domain.presence || config.domain.presence}/"
|
103
|
+
end
|
104
|
+
|
105
|
+
def jwks_hash
|
106
|
+
conn = ::Faraday.new("https://#{config.custom_domain}") do |f|
|
107
|
+
f.use(:http_cache, store: ::Devise.auth0.cache)
|
108
|
+
f.request(:retry, max: 3)
|
109
|
+
f.adapter(::Faraday.default_adapter)
|
110
|
+
end
|
111
|
+
jwks_keys = JSON.parse(conn.get("/.well-known/jwks.json").body)["keys"]
|
112
|
+
Hash[
|
113
|
+
jwks_keys
|
114
|
+
.map do |k|
|
115
|
+
[
|
116
|
+
k["kid"],
|
117
|
+
OpenSSL::X509::Certificate.new(
|
118
|
+
Base64.decode64(k["x5c"].first),
|
119
|
+
).public_key,
|
120
|
+
]
|
121
|
+
end
|
122
|
+
]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/devise/auth0.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "devise"
|
4
|
+
require "dry-configurable"
|
5
|
+
|
6
|
+
require "devise/auth0/client"
|
7
|
+
|
8
|
+
# Authentication library
|
9
|
+
module Devise
|
10
|
+
# Yields to Devise::Auth0.config
|
11
|
+
class << self
|
12
|
+
def auth0
|
13
|
+
return Devise::Auth0.config unless block_given?
|
14
|
+
|
15
|
+
yield(Devise::Auth0.config)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Models
|
20
|
+
autoload :Auth0, "devise/models/auth0"
|
21
|
+
end
|
22
|
+
|
23
|
+
module Strategies
|
24
|
+
autoload :Auth0, "devise/strategies/auth0"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Auth0 extension for devise
|
28
|
+
module Auth0
|
29
|
+
extend ::Dry::Configurable
|
30
|
+
|
31
|
+
setting(:algorithm, default: "RS256")
|
32
|
+
setting(
|
33
|
+
:aud,
|
34
|
+
default: ENV["AUTH0_AUDIENCE"].presence,
|
35
|
+
constructor: ->(aud) { aud.is_a?(Array) ? aud : aud.to_s.split(",") },
|
36
|
+
)
|
37
|
+
setting(:client_id, default: ENV["AUTH0_CLIENT_ID"].presence)
|
38
|
+
setting(:client_secret, default: ENV["AUTH0_CLIENT_SECRET"].presence)
|
39
|
+
setting(:custom_domain, default: ENV["AUTH0_CUSTOM_DOMAIN"].presence)
|
40
|
+
setting(:domain, default: ENV["AUTH0_DOMAIN"].presence)
|
41
|
+
setting(:omniauth, default: false)
|
42
|
+
setting(:scope, default: "openid")
|
43
|
+
setting(:email_domains_allowlist, default: [])
|
44
|
+
setting(:email_domains_blocklist, default: [])
|
45
|
+
setting(:cache)
|
46
|
+
setting(:cache_expires_in, default: 15.minutes)
|
47
|
+
|
48
|
+
class << self
|
49
|
+
def logout(record)
|
50
|
+
record.class.auth0_client.grants(user_id: record.auth0_id).each do |grant|
|
51
|
+
record.class.auth0_client.delete_grant(grant["id"], record.auth0_id)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
add_module(:auth0, strategy: true, controller: :auth0_callbacks, route: { auth0_callback: [:callback] })
|
58
|
+
end
|
59
|
+
|
60
|
+
require "devise/auth0/version"
|
61
|
+
require "devise/auth0/rails"
|
62
|
+
require "devise/strategies/auth0"
|
@@ -0,0 +1,210 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "mail"
|
4
|
+
require "devise/hooks/auth0"
|
5
|
+
|
6
|
+
module Devise
|
7
|
+
module Models
|
8
|
+
module Auth0
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
validates :uid, allow_blank: true, uniqueness: { scope: :provider, message: "should happen once per provider" }
|
13
|
+
with_options if: -> { respond_to?(:email) } do
|
14
|
+
validates :email, uniqueness: true
|
15
|
+
validate :email_domain_allowed, :email_domain_disallowed
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def required_fields(klass)
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def email_domain_allowed
|
26
|
+
return if self.class.auth0_config.email_domains_allowlist.empty?
|
27
|
+
|
28
|
+
m = Mail::Address.new(email)
|
29
|
+
return if m.domain.nil?
|
30
|
+
|
31
|
+
unless self.class.auth0_config.email_domains_allowlist.include?(m.domain)
|
32
|
+
errors.add(:email, :not_allowed)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def email_domain_disallowed
|
37
|
+
return if self.class.auth0_config.email_domains_blocklist.empty?
|
38
|
+
|
39
|
+
m = Mail::Address.new(email)
|
40
|
+
return if m.domain.nil?
|
41
|
+
|
42
|
+
if self.class.auth0_config.email_domains_blocklist.include?(m.domain)
|
43
|
+
errors.add(:email, :not_allowed)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def can?(action, resource_class = nil)
|
48
|
+
scope = [action]
|
49
|
+
if resource_class.is_a?(String)
|
50
|
+
scope << resource_class
|
51
|
+
elsif resource_class
|
52
|
+
resource_name = resource_class.name.underscore.split("/")
|
53
|
+
resource_name[-1] = resource_name[-1].pluralize
|
54
|
+
scope << resource_name.join("/")
|
55
|
+
end
|
56
|
+
auth0_scopes.include?(scope.join(":"))
|
57
|
+
end
|
58
|
+
|
59
|
+
# Convenience method which works the same as "can?" but returns the opposite value.
|
60
|
+
#
|
61
|
+
# cannot? :destroy, @project
|
62
|
+
#
|
63
|
+
def cannot?(*args)
|
64
|
+
!can?(*args)
|
65
|
+
end
|
66
|
+
|
67
|
+
def auth0_scopes=(scopes)
|
68
|
+
::Devise.auth0.cache.write(
|
69
|
+
"devise-auth0/#{auth0_id}/scopes",
|
70
|
+
scopes,
|
71
|
+
expires_in: ::Devise.auth0.cache_expires_in,
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
def auth0_scopes
|
76
|
+
::Devise.auth0.cache.fetch("devise-auth0/#{auth0_id}/scopes", expires_in: ::Devise.auth0.cache_expires_in) do
|
77
|
+
if bot?
|
78
|
+
self.class.auth0_client.client_grants(
|
79
|
+
client_id: uid,
|
80
|
+
audience: self.class.auth0_config.aud,
|
81
|
+
).first.try(:[], "scope")
|
82
|
+
else
|
83
|
+
user = self.class.auth0_client.users_by_email(email).find do |u|
|
84
|
+
u["identities"].any? { |i| i["user_id"] == uid }
|
85
|
+
end
|
86
|
+
return [] if user.nil?
|
87
|
+
|
88
|
+
permissions = []
|
89
|
+
page = 0
|
90
|
+
loop do
|
91
|
+
response_data = self.class.auth0_client
|
92
|
+
.get_user_permissions(
|
93
|
+
user["user_id"],
|
94
|
+
{ page: page, per_page: 100, include_totals: true },
|
95
|
+
)
|
96
|
+
|
97
|
+
response_data["permissions"].select do |permission|
|
98
|
+
self.class.auth0_config.aud.include?(permission["resource_server_identifier"])
|
99
|
+
end.each do |permission|
|
100
|
+
permissions << permission["permission_name"]
|
101
|
+
end
|
102
|
+
|
103
|
+
break if response_data["start"] / 100 == response_data["total"] / 100
|
104
|
+
|
105
|
+
page += 1
|
106
|
+
end
|
107
|
+
permissions
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def auth0_id
|
113
|
+
"#{provider}|#{uid}"
|
114
|
+
end
|
115
|
+
|
116
|
+
def after_auth0_token_created(token)
|
117
|
+
end
|
118
|
+
|
119
|
+
def after_auth0_token(token)
|
120
|
+
set_auth_id(token.provider, token.uid)
|
121
|
+
end
|
122
|
+
|
123
|
+
def after_auth0_omniauth_created(auth)
|
124
|
+
end
|
125
|
+
|
126
|
+
def after_auth0_omniauth(auth)
|
127
|
+
set_auth_id(auth.provider, auth.uid)
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def set_auth_id(provider, uid)
|
133
|
+
return if self.provider == provider && self.uid == uid
|
134
|
+
|
135
|
+
self.provider = provider
|
136
|
+
self.uid = uid.include?("|") ? uid.split("|").last : uid
|
137
|
+
save
|
138
|
+
end
|
139
|
+
|
140
|
+
module ClassMethods
|
141
|
+
Devise::Models.config(self, :auth0_options)
|
142
|
+
|
143
|
+
def from_auth0_token(token)
|
144
|
+
user = where(
|
145
|
+
auth0_where_conditions(
|
146
|
+
provider: token.provider,
|
147
|
+
uid: token.uid,
|
148
|
+
email: token.user["email"],
|
149
|
+
),
|
150
|
+
).first_or_create do |user|
|
151
|
+
user.provider = token.provider
|
152
|
+
user.uid = token.uid
|
153
|
+
user.email = token.user["email"] if user.respond_to?(:email=)
|
154
|
+
user.password = Devise.friendly_token[0, 20] if user.respond_to?(:password=)
|
155
|
+
user.bot = token.bot? if user.respond_to?(:bot=)
|
156
|
+
user.after_auth0_token_created(token)
|
157
|
+
end
|
158
|
+
user.auth0_scopes = token.scopes.dup.concat(token.permissions).uniq
|
159
|
+
user.after_auth0_token(token)
|
160
|
+
user
|
161
|
+
end
|
162
|
+
|
163
|
+
def parse_auth0_token(token)
|
164
|
+
::Devise::Auth0::Token.parse(token, self)
|
165
|
+
end
|
166
|
+
|
167
|
+
def from_auth0_omniauth(auth)
|
168
|
+
return unless auth0_config.omniauth
|
169
|
+
|
170
|
+
uid = auth.uid.include?("|") ? auth.uid.split("|").last : auth.uid
|
171
|
+
user = where(
|
172
|
+
auth0_where_conditions(
|
173
|
+
provider: auth.provider,
|
174
|
+
uid: uid,
|
175
|
+
email: auth.info.email,
|
176
|
+
),
|
177
|
+
).first_or_create do |user|
|
178
|
+
user.provider = auth.provider
|
179
|
+
user.uid = uid
|
180
|
+
user.email = auth.info.email if user.respond_to?(:email=)
|
181
|
+
user.password = Devise.friendly_token[0, 20] if user.respond_to?(:password=)
|
182
|
+
user.after_auth0_omniauth_created(auth)
|
183
|
+
end
|
184
|
+
user.after_auth0_omniauth(auth)
|
185
|
+
user
|
186
|
+
end
|
187
|
+
|
188
|
+
def auth0_where_conditions(provider:, uid:, email: nil)
|
189
|
+
sql = arel_table[:provider].eq(provider).and(arel_table[:uid].eq(uid))
|
190
|
+
sql = sql.or(arel_table[:email].eq(email)) if email && column_names.include?("email")
|
191
|
+
sql
|
192
|
+
end
|
193
|
+
|
194
|
+
def auth0_config
|
195
|
+
return @auth0_config unless @auth0_config.nil?
|
196
|
+
|
197
|
+
@auth0_config ||= ::Devise.auth0.pristine
|
198
|
+
@auth0_config.update(::Devise.auth0.values)
|
199
|
+
@auth0_config.update(auth0_options) if defined?(@auth0_options)
|
200
|
+
@auth0_config.finalize!
|
201
|
+
@auth0_config
|
202
|
+
end
|
203
|
+
|
204
|
+
def auth0_client
|
205
|
+
@auth0_client ||= ::Devise::Auth0::Client.new(auth0_config)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "devise/strategies/base"
|
4
|
+
|
5
|
+
require_relative "../auth0/helpers"
|
6
|
+
require_relative "../auth0/token"
|
7
|
+
|
8
|
+
module Devise
|
9
|
+
module Strategies
|
10
|
+
# Warden strategy to authenticate an user through a JWT token in the
|
11
|
+
# `Authorization` request header
|
12
|
+
class Auth0 < Devise::Strategies::Base
|
13
|
+
def valid?
|
14
|
+
!auth.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def store?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
def authenticate!
|
22
|
+
if token.valid?
|
23
|
+
resource = mapping.to.from_auth0_token(token)
|
24
|
+
return success!(resource) if resource.persisted?
|
25
|
+
end
|
26
|
+
|
27
|
+
fail!(:invalid)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def token
|
33
|
+
@token ||= mapping.to.parse_auth0_token(auth)
|
34
|
+
end
|
35
|
+
|
36
|
+
def auth
|
37
|
+
@auth ||= ::Devise::Auth0::Helpers.get_auth(env)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Warden::Strategies.add(:auth0, Devise::Strategies::Auth0)
|
data/lib/devise_auth0.rb
ADDED
metadata
ADDED
@@ -0,0 +1,484 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: devise_auth0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Chlark Sumatra
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-09-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: auth0
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: devise
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.8'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.8'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-configurable
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.13'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.13'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faraday
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.10.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.10.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday-http-cache
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: jwt
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.3'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mail
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: net-smtp
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: omniauth-auth0
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '3.0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '3.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: omniauth-rails_csrf_protection
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: appraisal
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '2.4'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '2.4'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: bundler
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '2.0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '2.0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: code-scanning-rubocop
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: dotenv
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: faker
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - "~>"
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '2.0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - "~>"
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '2.0'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: multi_json
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - ">="
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '0'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: multipart-parser
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - "~>"
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: 0.1.1
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - "~>"
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: 0.1.1
|
251
|
+
- !ruby/object:Gem::Dependency
|
252
|
+
name: pry-byebug
|
253
|
+
requirement: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - "~>"
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: '3.7'
|
258
|
+
type: :development
|
259
|
+
prerelease: false
|
260
|
+
version_requirements: !ruby/object:Gem::Requirement
|
261
|
+
requirements:
|
262
|
+
- - "~>"
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: '3.7'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: rack_session_access
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - ">="
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '0'
|
272
|
+
type: :development
|
273
|
+
prerelease: false
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - ">="
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
279
|
+
- !ruby/object:Gem::Dependency
|
280
|
+
name: rake
|
281
|
+
requirement: !ruby/object:Gem::Requirement
|
282
|
+
requirements:
|
283
|
+
- - "~>"
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: '13.0'
|
286
|
+
type: :development
|
287
|
+
prerelease: false
|
288
|
+
version_requirements: !ruby/object:Gem::Requirement
|
289
|
+
requirements:
|
290
|
+
- - "~>"
|
291
|
+
- !ruby/object:Gem::Version
|
292
|
+
version: '13.0'
|
293
|
+
- !ruby/object:Gem::Dependency
|
294
|
+
name: rspec-rails
|
295
|
+
requirement: !ruby/object:Gem::Requirement
|
296
|
+
requirements:
|
297
|
+
- - ">="
|
298
|
+
- !ruby/object:Gem::Version
|
299
|
+
version: '0'
|
300
|
+
type: :development
|
301
|
+
prerelease: false
|
302
|
+
version_requirements: !ruby/object:Gem::Requirement
|
303
|
+
requirements:
|
304
|
+
- - ">="
|
305
|
+
- !ruby/object:Gem::Version
|
306
|
+
version: '0'
|
307
|
+
- !ruby/object:Gem::Dependency
|
308
|
+
name: rubocop-performance
|
309
|
+
requirement: !ruby/object:Gem::Requirement
|
310
|
+
requirements:
|
311
|
+
- - ">="
|
312
|
+
- !ruby/object:Gem::Version
|
313
|
+
version: '0'
|
314
|
+
type: :development
|
315
|
+
prerelease: false
|
316
|
+
version_requirements: !ruby/object:Gem::Requirement
|
317
|
+
requirements:
|
318
|
+
- - ">="
|
319
|
+
- !ruby/object:Gem::Version
|
320
|
+
version: '0'
|
321
|
+
- !ruby/object:Gem::Dependency
|
322
|
+
name: rubocop-rails
|
323
|
+
requirement: !ruby/object:Gem::Requirement
|
324
|
+
requirements:
|
325
|
+
- - ">="
|
326
|
+
- !ruby/object:Gem::Version
|
327
|
+
version: '0'
|
328
|
+
type: :development
|
329
|
+
prerelease: false
|
330
|
+
version_requirements: !ruby/object:Gem::Requirement
|
331
|
+
requirements:
|
332
|
+
- - ">="
|
333
|
+
- !ruby/object:Gem::Version
|
334
|
+
version: '0'
|
335
|
+
- !ruby/object:Gem::Dependency
|
336
|
+
name: rubocop-rake
|
337
|
+
requirement: !ruby/object:Gem::Requirement
|
338
|
+
requirements:
|
339
|
+
- - ">="
|
340
|
+
- !ruby/object:Gem::Version
|
341
|
+
version: '0'
|
342
|
+
type: :development
|
343
|
+
prerelease: false
|
344
|
+
version_requirements: !ruby/object:Gem::Requirement
|
345
|
+
requirements:
|
346
|
+
- - ">="
|
347
|
+
- !ruby/object:Gem::Version
|
348
|
+
version: '0'
|
349
|
+
- !ruby/object:Gem::Dependency
|
350
|
+
name: rubocop-rspec
|
351
|
+
requirement: !ruby/object:Gem::Requirement
|
352
|
+
requirements:
|
353
|
+
- - ">="
|
354
|
+
- !ruby/object:Gem::Version
|
355
|
+
version: '0'
|
356
|
+
type: :development
|
357
|
+
prerelease: false
|
358
|
+
version_requirements: !ruby/object:Gem::Requirement
|
359
|
+
requirements:
|
360
|
+
- - ">="
|
361
|
+
- !ruby/object:Gem::Version
|
362
|
+
version: '0'
|
363
|
+
- !ruby/object:Gem::Dependency
|
364
|
+
name: rubocop-shopify
|
365
|
+
requirement: !ruby/object:Gem::Requirement
|
366
|
+
requirements:
|
367
|
+
- - "~>"
|
368
|
+
- !ruby/object:Gem::Version
|
369
|
+
version: '2.14'
|
370
|
+
type: :development
|
371
|
+
prerelease: false
|
372
|
+
version_requirements: !ruby/object:Gem::Requirement
|
373
|
+
requirements:
|
374
|
+
- - "~>"
|
375
|
+
- !ruby/object:Gem::Version
|
376
|
+
version: '2.14'
|
377
|
+
- !ruby/object:Gem::Dependency
|
378
|
+
name: simplecov
|
379
|
+
requirement: !ruby/object:Gem::Requirement
|
380
|
+
requirements:
|
381
|
+
- - ">="
|
382
|
+
- !ruby/object:Gem::Version
|
383
|
+
version: 0.21.2
|
384
|
+
type: :development
|
385
|
+
prerelease: false
|
386
|
+
version_requirements: !ruby/object:Gem::Requirement
|
387
|
+
requirements:
|
388
|
+
- - ">="
|
389
|
+
- !ruby/object:Gem::Version
|
390
|
+
version: 0.21.2
|
391
|
+
- !ruby/object:Gem::Dependency
|
392
|
+
name: timecop
|
393
|
+
requirement: !ruby/object:Gem::Requirement
|
394
|
+
requirements:
|
395
|
+
- - ">="
|
396
|
+
- !ruby/object:Gem::Version
|
397
|
+
version: '0'
|
398
|
+
type: :development
|
399
|
+
prerelease: false
|
400
|
+
version_requirements: !ruby/object:Gem::Requirement
|
401
|
+
requirements:
|
402
|
+
- - ">="
|
403
|
+
- !ruby/object:Gem::Version
|
404
|
+
version: '0'
|
405
|
+
- !ruby/object:Gem::Dependency
|
406
|
+
name: vcr
|
407
|
+
requirement: !ruby/object:Gem::Requirement
|
408
|
+
requirements:
|
409
|
+
- - "~>"
|
410
|
+
- !ruby/object:Gem::Version
|
411
|
+
version: '6.0'
|
412
|
+
type: :development
|
413
|
+
prerelease: false
|
414
|
+
version_requirements: !ruby/object:Gem::Requirement
|
415
|
+
requirements:
|
416
|
+
- - "~>"
|
417
|
+
- !ruby/object:Gem::Version
|
418
|
+
version: '6.0'
|
419
|
+
- !ruby/object:Gem::Dependency
|
420
|
+
name: webmock
|
421
|
+
requirement: !ruby/object:Gem::Requirement
|
422
|
+
requirements:
|
423
|
+
- - "~>"
|
424
|
+
- !ruby/object:Gem::Version
|
425
|
+
version: '3.4'
|
426
|
+
type: :development
|
427
|
+
prerelease: false
|
428
|
+
version_requirements: !ruby/object:Gem::Requirement
|
429
|
+
requirements:
|
430
|
+
- - "~>"
|
431
|
+
- !ruby/object:Gem::Version
|
432
|
+
version: '3.4'
|
433
|
+
description: Auth0 authentication for devise
|
434
|
+
email:
|
435
|
+
- clark@sumatra.com.ph
|
436
|
+
executables: []
|
437
|
+
extensions: []
|
438
|
+
extra_rdoc_files:
|
439
|
+
- LICENSE.md
|
440
|
+
files:
|
441
|
+
- CHANGELOG.md
|
442
|
+
- LICENSE.md
|
443
|
+
- app/controllers/devise/auth0_callbacks_controller.rb
|
444
|
+
- lib/devise/auth0.rb
|
445
|
+
- lib/devise/auth0/client.rb
|
446
|
+
- lib/devise/auth0/controllers/helpers.rb
|
447
|
+
- lib/devise/auth0/exceptions.rb
|
448
|
+
- lib/devise/auth0/helpers.rb
|
449
|
+
- lib/devise/auth0/rails.rb
|
450
|
+
- lib/devise/auth0/rails/routes.rb
|
451
|
+
- lib/devise/auth0/token.rb
|
452
|
+
- lib/devise/auth0/version.rb
|
453
|
+
- lib/devise/hooks/auth0.rb
|
454
|
+
- lib/devise/models/auth0.rb
|
455
|
+
- lib/devise/strategies/auth0.rb
|
456
|
+
- lib/devise_auth0.rb
|
457
|
+
homepage: https://github.com/itsmechlark/devise_auth0
|
458
|
+
licenses:
|
459
|
+
- MIT
|
460
|
+
metadata:
|
461
|
+
homepage_uri: https://github.com/itsmechlark/devise_auth0
|
462
|
+
changelog_uri: https://github.com/itsmechlark/devise_auth0/releases/tag/v1.0.0
|
463
|
+
source_code_uri: https://github.com/itsmechlark/devise_auth0/tree/v1.0.0
|
464
|
+
bug_tracker_uri: https://github.com/itsmechlark/devise_auth0/issues
|
465
|
+
post_install_message:
|
466
|
+
rdoc_options: []
|
467
|
+
require_paths:
|
468
|
+
- lib
|
469
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
470
|
+
requirements:
|
471
|
+
- - ">="
|
472
|
+
- !ruby/object:Gem::Version
|
473
|
+
version: '0'
|
474
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
475
|
+
requirements:
|
476
|
+
- - ">="
|
477
|
+
- !ruby/object:Gem::Version
|
478
|
+
version: '0'
|
479
|
+
requirements: []
|
480
|
+
rubygems_version: 3.2.3
|
481
|
+
signing_key:
|
482
|
+
specification_version: 4
|
483
|
+
summary: Auth0 authentication for devise
|
484
|
+
test_files: []
|