kinde_sdk 1.6.0 → 1.6.1
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a51e08a86c0ebee1cd68dea496cb049da5d43600f5afb7fe9a536d2697b1640
|
4
|
+
data.tar.gz: ebc062da13f17b1a5556114d7ee2f6182e35a24ed25ad1d2aba38a135cf431e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d285428c93ed0abce5b77e2a90359e54c82d54a1596d4d2177eec28417646ce67c04909aa6b609d0cf4ed0aef7473229c24d2d759c77c20284e8bc653d46009
|
7
|
+
data.tar.gz: 5373b19121f97d843bd085702e1bffde03bd03796384beab6294e88d467c424f2bcfe37322020a872f825ebf0d5d087bc41ccfef4b6f5a61294ca954f121dd28
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'action_controller'
|
2
|
+
require 'uri'
|
3
|
+
require 'cgi'
|
4
|
+
require 'net/http'
|
5
|
+
require 'json'
|
6
|
+
require 'jwt'
|
7
|
+
|
8
|
+
module KindeSdk
|
9
|
+
class AuthController < ActionController::Base
|
10
|
+
# Add before_action to validate nonce in callback
|
11
|
+
before_action :validate_state, only: :callback
|
12
|
+
|
13
|
+
def auth
|
14
|
+
# Generate a secure random nonce
|
15
|
+
nonce = SecureRandom.urlsafe_base64(16)
|
16
|
+
|
17
|
+
# Call KindeSdk.auth_url with nonce
|
18
|
+
auth_data = KindeSdk.auth_url(nonce: nonce)
|
19
|
+
|
20
|
+
# Store in session
|
21
|
+
session[:code_verifier] = auth_data[:code_verifier] if auth_data[:code_verifier].present?
|
22
|
+
session[:auth_nonce] = nonce
|
23
|
+
session[:auth_state] = {
|
24
|
+
requested_at: Time.current.to_i,
|
25
|
+
redirect_url: auth_data[:url]
|
26
|
+
}
|
27
|
+
|
28
|
+
redirect_to auth_data[:url], allow_other_host: true
|
29
|
+
end
|
30
|
+
|
31
|
+
def callback
|
32
|
+
tokens = KindeSdk.fetch_tokens(
|
33
|
+
params[:code],
|
34
|
+
code_verifier: KindeSdk.config.pkce_enabled ? session[:code_verifier] : nil
|
35
|
+
).slice(:access_token, :id_token, :refresh_token, :expires_at)
|
36
|
+
|
37
|
+
|
38
|
+
# Validate nonce in ID token
|
39
|
+
id_token = tokens[:id_token]
|
40
|
+
issuer = KindeSdk.config.domain
|
41
|
+
client_id = KindeSdk.config.client_id
|
42
|
+
original_nonce = session[:auth_nonce]
|
43
|
+
unless validate_nonce(id_token, original_nonce, issuer, client_id)
|
44
|
+
Rails.logger.warn("Nonce validation failed")
|
45
|
+
redirect_to "/", alert: "Invalid authentication nonce"
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
# Store tokens and user in session
|
50
|
+
session[:kinde_auth] = OAuth2::AccessToken.from_hash(KindeSdk.config.oauth_client, tokens).to_hash
|
51
|
+
.slice(:access_token, :refresh_token, :expires_at)
|
52
|
+
session[:kinde_user] = KindeSdk.client(tokens).oauth.get_user.to_hash
|
53
|
+
|
54
|
+
# Clear nonce and state after successful authentication
|
55
|
+
session.delete(:auth_nonce)
|
56
|
+
session.delete(:auth_state)
|
57
|
+
session.delete(:code_verifier)
|
58
|
+
redirect_to "/"
|
59
|
+
rescue StandardError => e
|
60
|
+
Rails.logger.error("Authentication callback failed: #{e.message}")
|
61
|
+
redirect_to "/", alert: "Authentication failed"
|
62
|
+
end
|
63
|
+
|
64
|
+
def client_credentials_auth
|
65
|
+
result = KindeSdk.client_credentials_access(
|
66
|
+
client_id: ENV["KINDE_MANAGEMENT_CLIENT_ID"],
|
67
|
+
client_secret: ENV["KINDE_MANAGEMENT_CLIENT_SECRET"]
|
68
|
+
)
|
69
|
+
|
70
|
+
if result["error"].present?
|
71
|
+
Rails.logger.error("Client credentials auth failed: #{result['error']}")
|
72
|
+
raise result["error"]
|
73
|
+
end
|
74
|
+
|
75
|
+
$redis.set("kinde_m2m_token", result["access_token"], ex: result["expires_in"].to_i)
|
76
|
+
redirect_to mgmt_path
|
77
|
+
end
|
78
|
+
|
79
|
+
def logout
|
80
|
+
redirect_to KindeSdk.logout_url, allow_other_host: true
|
81
|
+
end
|
82
|
+
|
83
|
+
def logout_callback
|
84
|
+
reset_session
|
85
|
+
redirect_to "/"
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def validate_state
|
91
|
+
# Check if nonce and state exist in session
|
92
|
+
unless session[:auth_nonce] && session[:auth_state]
|
93
|
+
Rails.logger.warn("Missing session state or nonce [#{session[:auth_nonce]}] [#{session[:auth_state]}]")
|
94
|
+
redirect_to "/", alert: "Invalid authentication state"
|
95
|
+
return
|
96
|
+
end
|
97
|
+
|
98
|
+
# Verify nonce returned matches stored nonce
|
99
|
+
returned_state = params[:state]
|
100
|
+
stored_state = session[:auth_state]
|
101
|
+
stored_url = stored_state["redirect_url"]
|
102
|
+
|
103
|
+
# Extract the state from the stored redirect_url
|
104
|
+
parsed_url = URI.parse(stored_url)
|
105
|
+
query_params = CGI.parse(parsed_url.query || "")
|
106
|
+
stored_state_from_url = query_params["state"]&.first
|
107
|
+
|
108
|
+
# Verify returned state matches the state extracted from the redirect_url
|
109
|
+
unless returned_state.present? && returned_state == stored_state_from_url
|
110
|
+
Rails.logger.warn("State validation failed: returned=#{returned_state}, expected=#{stored_state_from_url}")
|
111
|
+
redirect_to "/", alert: "Invalid authentication state"
|
112
|
+
return
|
113
|
+
end
|
114
|
+
|
115
|
+
# Optional: Check state age (e.g., expires after 15 minutes)
|
116
|
+
if Time.current.to_i - stored_state["requested_at"] > 900
|
117
|
+
Rails.logger.warn("Authentication state expired")
|
118
|
+
redirect_to "/", alert: "Authentication session expired"
|
119
|
+
return
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
def validate_nonce(id_token, original_nonce, issuer, client_id)
|
125
|
+
jwks_uri = URI.parse("#{issuer}/.well-known/jwks.json")
|
126
|
+
jwks_response = Net::HTTP.get(jwks_uri)
|
127
|
+
jwks = JSON.parse(jwks_response)
|
128
|
+
|
129
|
+
decoded_token = JWT.decode(
|
130
|
+
id_token,
|
131
|
+
nil,
|
132
|
+
true,
|
133
|
+
algorithm: 'RS256',
|
134
|
+
iss: issuer,
|
135
|
+
aud: client_id,
|
136
|
+
verify_iss: true,
|
137
|
+
verify_aud: true,
|
138
|
+
jwks: { keys: jwks['keys'] }
|
139
|
+
)
|
140
|
+
|
141
|
+
payload = decoded_token[0]
|
142
|
+
nonce_from_token = payload['nonce']
|
143
|
+
|
144
|
+
nonce_from_token == original_nonce
|
145
|
+
rescue StandardError => e
|
146
|
+
Rails.logger.error("Nonce validation error: #{e.message}")
|
147
|
+
false
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
end
|
152
|
+
end
|
data/config/routes.rb
ADDED
data/lib/kinde_sdk/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kinde_sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kinde Australia Pty Ltd
|
@@ -141,6 +141,9 @@ executables: []
|
|
141
141
|
extensions: []
|
142
142
|
extra_rdoc_files: []
|
143
143
|
files:
|
144
|
+
- app/assets/stylesheets/kinde/ruby/sdk/application.css
|
145
|
+
- app/controllers/kinde_sdk/auth_controller.rb
|
146
|
+
- config/routes.rb
|
144
147
|
- kinde_api/README.md
|
145
148
|
- kinde_api/docs/APIsApi.md
|
146
149
|
- kinde_api/docs/AddAPIsRequest.md
|