himari 0.2.0 → 0.3.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 +4 -4
- data/lib/himari/app.rb +21 -3
- data/lib/himari/authorization_code.rb +13 -1
- data/lib/himari/decisions/authorization.rb +5 -4
- data/lib/himari/decisions/base.rb +13 -7
- data/lib/himari/id_token.rb +4 -2
- data/lib/himari/rule_processor.rb +7 -2
- data/lib/himari/services/downstream_authorization.rb +5 -4
- data/lib/himari/version.rb +1 -1
- data/public/public/index.css +9 -0
- data/views/login.erb +6 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ef5f3bac5f8a375751669378420729ab8dbe9ce40c1e1dec0fb5a3ac938b304
|
4
|
+
data.tar.gz: ed87e0922bc863813624c34d217f02fd9f06fec442fd01a8b0c1daf760b6ca48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97c69604496c88d5b6e0f38cf0693cdd07ee6dd15b73d12e724efcea058a2f44492fcbe57ed5ece878f36e7bc2631a028c1464f9bc17d33f519eb2f17b8ff576
|
7
|
+
data.tar.gz: 3a9fff6c67bec527df79527f9e436c5703d95e822e0b0d3bc4cc460e003205d238a9e8ea965f2fbb931a18389282dfa2b770e60b931eaadc82dd683b413f841a
|
data/lib/himari/app.rb
CHANGED
@@ -127,6 +127,7 @@ module Himari
|
|
127
127
|
authz = AuthorizationCode.make(
|
128
128
|
client_id: decision.client.id,
|
129
129
|
claims: decision.claims,
|
130
|
+
lifetime: decision.lifetime,
|
130
131
|
)
|
131
132
|
|
132
133
|
Himari::Services::OidcAuthorizationEndpoint.new(
|
@@ -141,7 +142,20 @@ module Himari
|
|
141
142
|
end
|
142
143
|
rescue Himari::Services::DownstreamAuthorization::ForbiddenError => e
|
143
144
|
logger&.warn(Himari::LogLine.new('authorize: downstream forbidden', req: request_as_log, allowed: e.result.authz_result.allowed, err: e.class.inspect, result: e.as_log))
|
144
|
-
|
145
|
+
|
146
|
+
@notice = message_human = e.result.authz_result&.user_facing_message
|
147
|
+
|
148
|
+
case e.result.authz_result&.suggestion
|
149
|
+
when nil
|
150
|
+
# do nothing
|
151
|
+
when :reauthenticate
|
152
|
+
logger&.warn(Himari::LogLine.new('authorize: prompt login to reauthenticate', req: request_as_log, allowed: e.result.authz_result.allowed, err: e.class.inspect, result: e.as_log))
|
153
|
+
next erb(:login)
|
154
|
+
else
|
155
|
+
raise ArgumentError, "Unknown suggestion value for DownstreamAuthorization denial; #{e.as_log.inspect}"
|
156
|
+
end
|
157
|
+
|
158
|
+
halt(403, "Forbidden#{message_human ? "; #{message_human}" : nil}")
|
145
159
|
end
|
146
160
|
|
147
161
|
token_ep = proc do
|
@@ -182,9 +196,12 @@ module Himari
|
|
182
196
|
end
|
183
197
|
|
184
198
|
omniauth_callback = proc do
|
199
|
+
authhash = request.env['omniauth.auth']
|
200
|
+
next halt(400, 'Bad Request') unless authhash
|
201
|
+
|
185
202
|
# do upstream auth
|
186
203
|
authn = Himari::Services::UpstreamAuthentication.from_request(request).perform
|
187
|
-
logger&.info(Himari::LogLine.new('authentication allowed', req: request_as_log, allowed: authn.authn_result.allowed, uid:
|
204
|
+
logger&.info(Himari::LogLine.new('authentication allowed', req: request_as_log, allowed: authn.authn_result.allowed, uid: authhash[:uid], provider: authhash[:provider], result: authn.as_log))
|
188
205
|
raise unless authn.authn_result.allowed # sanity check
|
189
206
|
|
190
207
|
given_back_to = request.env['omniauth.params']&.fetch('back_to', nil)
|
@@ -203,7 +220,8 @@ module Himari
|
|
203
220
|
redirect back_to
|
204
221
|
rescue Himari::Services::UpstreamAuthentication::UnauthorizedError => e
|
205
222
|
logger&.warn(Himari::LogLine.new('authentication denied', req: request_as_log, err: e.class.inspect, allowed: e.result.authn_result.allowed, uid: request.env.fetch('omniauth.auth')[:uid], provider: request.env.fetch('omniauth.auth')[:provider], result: e.as_log))
|
206
|
-
|
223
|
+
message_human = e.result.authn_result&.user_facing_message
|
224
|
+
halt(401, "Unauthorized#{message_human ? "; #{message_human}" : nil}")
|
207
225
|
end
|
208
226
|
get '/auth/:provider/callback', &omniauth_callback
|
209
227
|
post '/auth/:provider/callback', &omniauth_callback
|
@@ -10,17 +10,25 @@ module Himari
|
|
10
10
|
nonce
|
11
11
|
code_challenge
|
12
12
|
code_challenge_method
|
13
|
+
created_at
|
14
|
+
lifetime
|
13
15
|
expiry
|
14
16
|
)
|
15
17
|
AuthorizationCode = Struct.new(*authz_attrs, keyword_init: true) do
|
16
18
|
def self.make(**kwargs)
|
17
19
|
new(
|
18
20
|
code: SecureRandom.urlsafe_base64(32),
|
19
|
-
|
21
|
+
created_at: Time.now.to_i,
|
20
22
|
**kwargs,
|
21
23
|
)
|
22
24
|
end
|
23
25
|
|
26
|
+
alias _expiry_raw expiry
|
27
|
+
private :_expiry_raw
|
28
|
+
def expiry
|
29
|
+
self._expiry_raw || (self.expiry = created_at + (lifetime || 900))
|
30
|
+
end
|
31
|
+
|
24
32
|
def valid_redirect_uri?(given_uri)
|
25
33
|
redirect_uri == given_uri
|
26
34
|
end
|
@@ -59,6 +67,8 @@ module Himari
|
|
59
67
|
claims: claims,
|
60
68
|
nonce: nonce,
|
61
69
|
openid: openid,
|
70
|
+
created_at: created_at.to_i,
|
71
|
+
lifetime: lifetime.to_i,
|
62
72
|
expiry: expiry.to_i,
|
63
73
|
pkce: pkce?,
|
64
74
|
pkce_method: code_challenge_method,
|
@@ -76,6 +86,8 @@ module Himari
|
|
76
86
|
nonce: nonce,
|
77
87
|
code_challenge: code_challenge,
|
78
88
|
code_challenge_method: code_challenge_method,
|
89
|
+
created_at: created_at.to_i,
|
90
|
+
lifetime: lifetime.to_i,
|
79
91
|
expiry: expiry.to_i,
|
80
92
|
}
|
81
93
|
end
|
@@ -19,14 +19,15 @@ module Himari
|
|
19
19
|
|
20
20
|
allow_effects(:allow, :deny, :continue, :skip)
|
21
21
|
|
22
|
-
def initialize(claims: {}, allowed_claims: DEFAULT_ALLOWED_CLAIMS, lifetime: 3600
|
22
|
+
def initialize(claims: {}, allowed_claims: DEFAULT_ALLOWED_CLAIMS, lifetime: 3600)
|
23
23
|
super()
|
24
24
|
@claims = claims
|
25
25
|
@allowed_claims = allowed_claims
|
26
26
|
@lifetime = lifetime
|
27
27
|
end
|
28
28
|
|
29
|
-
attr_reader :claims, :allowed_claims
|
29
|
+
attr_reader :claims, :allowed_claims
|
30
|
+
attr_accessor :lifetime
|
30
31
|
|
31
32
|
def to_evolve_args
|
32
33
|
{
|
@@ -37,10 +38,10 @@ module Himari
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def as_log
|
40
|
-
to_h.merge(claims:
|
41
|
+
to_h.merge(claims: output_claims, lifetime: @lifetime&.to_i)
|
41
42
|
end
|
42
43
|
|
43
|
-
def
|
44
|
+
def output_claims
|
44
45
|
claims.select { |k,_v| allowed_claims.include?(k) }
|
45
46
|
end
|
46
47
|
end
|
@@ -18,7 +18,7 @@ module Himari
|
|
18
18
|
raise "#{self.class.name}.valid_effects is missing [BUG]" unless self.class.valid_effects
|
19
19
|
end
|
20
20
|
|
21
|
-
attr_reader :effect, :effect_comment, :rule_name
|
21
|
+
attr_reader :effect, :effect_comment, :effect_user_facing_message, :effect_suggestion, :rule_name
|
22
22
|
|
23
23
|
def to_evolve_args
|
24
24
|
raise NotImplementedError
|
@@ -29,7 +29,10 @@ module Himari
|
|
29
29
|
rule_name: rule_name,
|
30
30
|
effect: effect,
|
31
31
|
effect_comment: effect_comment,
|
32
|
-
}
|
32
|
+
}.tap do |x|
|
33
|
+
x[:effect_user_facing_message] = effect_user_facing_message if effect_user_facing_message
|
34
|
+
x[:effect_suggestion] = effect_suggestion if effect_suggestion
|
35
|
+
end
|
33
36
|
end
|
34
37
|
|
35
38
|
def as_log
|
@@ -46,18 +49,21 @@ module Himari
|
|
46
49
|
self
|
47
50
|
end
|
48
51
|
|
49
|
-
def decide!(effect, comment = "")
|
52
|
+
def decide!(effect, comment = "", user_facing_message: nil, suggest: nil)
|
50
53
|
raise DecisionAlreadyMade, "decision can only be made once per rule (#{rule_name})" if @effect
|
51
54
|
raise InvalidEffect, "this effect is not valid under this rule. Valid effects: #{self.class.valid_effects.inspect} (#{rule_name})" unless self.class.valid_effects.include?(effect)
|
55
|
+
raise InvalidEffect, "only deny effect can have suggestion" if suggest&& effect != :deny
|
52
56
|
@effect = effect
|
53
57
|
@effect_comment = comment
|
58
|
+
@effect_user_facing_message = user_facing_message
|
59
|
+
@effect_suggestion = suggest
|
54
60
|
nil
|
55
61
|
end
|
56
62
|
|
57
|
-
def allow!(
|
58
|
-
def continue!(
|
59
|
-
def deny!(
|
60
|
-
def skip!(
|
63
|
+
def allow!(*args, **kwargs); decide!(:allow, *args, **kwargs); end
|
64
|
+
def continue!(*args, **kwargs); decide!(:continue, *args, **kwargs); end
|
65
|
+
def deny!(*args, **kwargs); decide!(:deny, *args, **kwargs); end
|
66
|
+
def skip!(*args, **kwargs); decide!(:skip, *args, **kwargs); end
|
61
67
|
end
|
62
68
|
end
|
63
69
|
end
|
data/lib/himari/id_token.rb
CHANGED
@@ -11,11 +11,12 @@ module Himari
|
|
11
11
|
claims: authz.claims,
|
12
12
|
client_id: authz.client_id,
|
13
13
|
nonce: authz.nonce,
|
14
|
+
lifetime: authz.lifetime,
|
14
15
|
**kwargs
|
15
16
|
)
|
16
17
|
end
|
17
18
|
|
18
|
-
def initialize(claims:, client_id:, nonce:, signing_key:, issuer:, access_token: nil, time: Time.now)
|
19
|
+
def initialize(claims:, client_id:, nonce:, signing_key:, issuer:, access_token: nil, time: Time.now, lifetime: 3600)
|
19
20
|
@claims = claims
|
20
21
|
@client_id = client_id
|
21
22
|
@nonce = nonce
|
@@ -23,6 +24,7 @@ module Himari
|
|
23
24
|
@issuer = issuer
|
24
25
|
@access_token = access_token
|
25
26
|
@time = time
|
27
|
+
@lifetime = lifetime
|
26
28
|
end
|
27
29
|
|
28
30
|
attr_reader :claims, :nonce, :signing_key
|
@@ -34,7 +36,7 @@ module Himari
|
|
34
36
|
aud: @client_id,
|
35
37
|
iat: @time.to_i,
|
36
38
|
nbf: @time.to_i,
|
37
|
-
exp: (@time +
|
39
|
+
exp: (@time + @lifetime).to_i,
|
38
40
|
).merge(
|
39
41
|
@nonce ? { nonce: @nonce } : {}
|
40
42
|
).merge(
|
@@ -2,7 +2,7 @@ module Himari
|
|
2
2
|
class RuleProcessor
|
3
3
|
class MissingDecisionError < StandardError; end
|
4
4
|
|
5
|
-
Result = Struct.new(:rule_name, :allowed, :explicit_deny, :decision, :decision_log, keyword_init: true) do
|
5
|
+
Result = Struct.new(:rule_name, :allowed, :explicit_deny, :decision, :decision_log, :user_facing_message, :suggestion, keyword_init: true) do
|
6
6
|
def as_log
|
7
7
|
{
|
8
8
|
rule_name: rule_name,
|
@@ -10,7 +10,9 @@ module Himari
|
|
10
10
|
explicit_deny: explicit_deny,
|
11
11
|
decision: decision&.as_log,
|
12
12
|
decision_log: decision_log.map(&:to_h),
|
13
|
-
}
|
13
|
+
}.tap do |x|
|
14
|
+
x[:suggestion] = suggestion if suggestion
|
15
|
+
end
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
@@ -47,6 +49,7 @@ module Himari
|
|
47
49
|
result.decision = decision
|
48
50
|
result.allowed = true
|
49
51
|
result.explicit_deny = false
|
52
|
+
result.user_facing_message = decision.effect_user_facing_message
|
50
53
|
|
51
54
|
when :continue
|
52
55
|
@decision = decision
|
@@ -61,6 +64,8 @@ module Himari
|
|
61
64
|
result.decision = nil
|
62
65
|
result.allowed = false
|
63
66
|
result.explicit_deny = true
|
67
|
+
result.user_facing_message = decision.effect_user_facing_message
|
68
|
+
result.suggestion = decision.effect_suggestion
|
64
69
|
|
65
70
|
else
|
66
71
|
raise "Unknown effect #{decision.effect} [BUG]"
|
@@ -21,7 +21,7 @@ module Himari
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
Result = Struct.new(:client, :claims, :authz_result) do
|
24
|
+
Result = Struct.new(:client, :claims, :lifetime, :authz_result) do
|
25
25
|
def as_log
|
26
26
|
{
|
27
27
|
client: client.as_log,
|
@@ -63,10 +63,11 @@ module Himari
|
|
63
63
|
context = Himari::Decisions::Authorization::Context.new(claims: @session.claims, user_data: @session.user_data, request: @request, client: @client).freeze
|
64
64
|
|
65
65
|
authorization = Himari::RuleProcessor.new(context, Himari::Decisions::Authorization.new(claims: @session.claims.dup)).run(@authz_rules)
|
66
|
-
raise ForbiddenError.new(Result.new(@client, nil, authorization)) unless authorization.allowed
|
66
|
+
raise ForbiddenError.new(Result.new(@client, nil, nil, authorization)) unless authorization.allowed
|
67
67
|
|
68
|
-
claims = authorization.decision.
|
69
|
-
|
68
|
+
claims = authorization.decision.output_claims
|
69
|
+
lifetime = authorization.decision.lifetime
|
70
|
+
Result.new(@client, claims, lifetime, authorization)
|
70
71
|
end
|
71
72
|
end
|
72
73
|
end
|
data/lib/himari/version.rb
CHANGED
data/public/public/index.css
CHANGED
@@ -58,6 +58,15 @@ main > header img, main > footer img {
|
|
58
58
|
margin-top: 30px;
|
59
59
|
}
|
60
60
|
|
61
|
+
.notice {
|
62
|
+
background-color: white;
|
63
|
+
border: 1px #bfa88a solid;
|
64
|
+
border-radius: 4px;
|
65
|
+
padding: 4px;
|
66
|
+
margin: 12px;
|
67
|
+
margin-bottom: 24px;
|
68
|
+
}
|
69
|
+
|
61
70
|
.d-none {
|
62
71
|
display: none;
|
63
72
|
}
|
data/views/login.erb
CHANGED