cf-uaa-lib 1.3.5 → 1.3.6
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.
- data/lib/uaa/http.rb +7 -8
- data/lib/uaa/token_coder.rb +20 -9
- data/lib/uaa/version.rb +1 -1
- data/spec/token_coder_spec.rb +19 -16
- metadata +8 -3
data/lib/uaa/http.rb
CHANGED
@@ -26,9 +26,6 @@ class NotFound < UAAError; end
|
|
26
26
|
# Indicates a syntax error in a response from the UAA, e.g. missing required response field.
|
27
27
|
class BadResponse < UAAError; end
|
28
28
|
|
29
|
-
# Indicates a token is malformed or expired.
|
30
|
-
class InvalidToken < UAAError; end
|
31
|
-
|
32
29
|
# Indicates an error from the http client stack.
|
33
30
|
class HTTPException < UAAError; end
|
34
31
|
|
@@ -40,6 +37,9 @@ class TargetError < UAAError
|
|
40
37
|
end
|
41
38
|
end
|
42
39
|
|
40
|
+
# Indicates a token is malformed or expired.
|
41
|
+
class InvalidToken < TargetError; end
|
42
|
+
|
43
43
|
# Utility accessors and methods for objects that want to access JSON web APIs.
|
44
44
|
module Http
|
45
45
|
|
@@ -91,7 +91,7 @@ module Http
|
|
91
91
|
|
92
92
|
def json_parse_reply(style, status, body, headers)
|
93
93
|
raise ArgumentError unless style.nil? || style.is_a?(Symbol)
|
94
|
-
unless [200, 201, 204, 400, 401, 403].include? status
|
94
|
+
unless [200, 201, 204, 400, 401, 403, 409].include? status
|
95
95
|
raise (status == 404 ? NotFound : BadResponse), "invalid status response: #{status}"
|
96
96
|
end
|
97
97
|
if body && !body.empty? && (status == 204 || headers.nil? ||
|
@@ -99,9 +99,9 @@ module Http
|
|
99
99
|
raise BadResponse, "received invalid response content or type"
|
100
100
|
end
|
101
101
|
parsed_reply = Util.json_parse(body, style)
|
102
|
-
|
102
|
+
if status >= 400
|
103
103
|
raise parsed_reply && parsed_reply["error"] == "invalid_token" ?
|
104
|
-
InvalidToken : TargetError.new(parsed_reply), "error response"
|
104
|
+
InvalidToken.new(parsed_reply) : TargetError.new(parsed_reply), "error response"
|
105
105
|
end
|
106
106
|
parsed_reply
|
107
107
|
rescue DecodeError
|
@@ -133,8 +133,7 @@ module Http
|
|
133
133
|
[status, body, headers]
|
134
134
|
|
135
135
|
rescue Exception => e
|
136
|
-
|
137
|
-
logger.debug { "<---- no response due to exception: #{e}" }
|
136
|
+
logger.debug { "<---- no response due to exception: #{e.inspect}" }
|
138
137
|
raise e
|
139
138
|
end
|
140
139
|
|
data/lib/uaa/token_coder.rb
CHANGED
@@ -16,6 +16,17 @@ require "uaa/util"
|
|
16
16
|
|
17
17
|
module CF::UAA
|
18
18
|
|
19
|
+
# this code does not support the given token signature algorithim
|
20
|
+
class SignatureNotSupported < DecodeError; end
|
21
|
+
|
22
|
+
# this instance policy does not accept the given token signature algorithim
|
23
|
+
class SignatureNotAccepted < DecodeError; end
|
24
|
+
|
25
|
+
class InvalidSignature < DecodeError; end
|
26
|
+
class InvalidTokenFormat < DecodeError; end
|
27
|
+
class TokenExpired < AuthError; end
|
28
|
+
class InvalidAudience < AuthError; end
|
29
|
+
|
19
30
|
# This class is for OAuth Resource Servers.
|
20
31
|
# Resource Servers get tokens and need to validate and decode them,
|
21
32
|
# but they do not obtain them from the Authorization Server. This
|
@@ -68,7 +79,7 @@ class TokenCoder
|
|
68
79
|
elsif algo == "none"
|
69
80
|
sig = ""
|
70
81
|
else
|
71
|
-
raise
|
82
|
+
raise SignatureNotSupported, "unsupported signing method"
|
72
83
|
end
|
73
84
|
segments << Util.encode64(sig)
|
74
85
|
segments.join('.')
|
@@ -90,24 +101,24 @@ class TokenCoder
|
|
90
101
|
end
|
91
102
|
options = normalize_options(options)
|
92
103
|
segments = token.split('.')
|
93
|
-
raise
|
104
|
+
raise InvalidTokenFormat, "Not enough or too many segments" unless [2,3].include? segments.length
|
94
105
|
header_segment, payload_segment, crypto_segment = segments
|
95
106
|
signing_input = [header_segment, payload_segment].join('.')
|
96
107
|
header = Util.json_decode64(header_segment)
|
97
108
|
payload = Util.json_decode64(payload_segment, (:sym if options[:symbolize_keys]))
|
98
109
|
return payload unless options[:verify]
|
99
|
-
raise
|
110
|
+
raise SignatureNotAccepted, "Signature algorithm not accepted" unless
|
100
111
|
options[:accept_algorithms].include?(algo = header["alg"])
|
101
112
|
return payload if algo == 'none'
|
102
113
|
signature = Util.decode64(crypto_segment)
|
103
114
|
if ["HS256", "HS384", "HS512"].include?(algo)
|
104
|
-
raise
|
115
|
+
raise InvalidSignature, "Signature verification failed" unless
|
105
116
|
signature == OpenSSL::HMAC.digest(init_digest(algo), options[:skey], signing_input)
|
106
117
|
elsif ["RS256", "RS384", "RS512"].include?(algo)
|
107
|
-
raise
|
118
|
+
raise InvalidSignature, "Signature verification failed" unless
|
108
119
|
options[:pkey].verify(init_digest(algo), signature, signing_input)
|
109
120
|
else
|
110
|
-
raise
|
121
|
+
raise SignatureNotSupported, "Algorithm not supported"
|
111
122
|
end
|
112
123
|
payload
|
113
124
|
end
|
@@ -166,16 +177,16 @@ class TokenCoder
|
|
166
177
|
# @return (see TokenCoder.decode)
|
167
178
|
def decode(auth_header)
|
168
179
|
unless auth_header && (tkn = auth_header.split(' ')).length == 2 && tkn[0] =~ /^bearer$/i
|
169
|
-
raise
|
180
|
+
raise InvalidTokenFormat, "invalid authentication header: #{auth_header}"
|
170
181
|
end
|
171
182
|
reply = self.class.decode(tkn[1], @options)
|
172
183
|
auds = Util.arglist(reply[:aud] || reply['aud'])
|
173
184
|
if @options[:audience_ids] && (!auds || (auds & @options[:audience_ids]).empty?)
|
174
|
-
raise
|
185
|
+
raise InvalidAudience, "invalid audience: #{auds}"
|
175
186
|
end
|
176
187
|
exp = reply[:exp] || reply['exp']
|
177
188
|
unless exp.is_a?(Integer) && exp > Time.now.to_i
|
178
|
-
raise
|
189
|
+
raise TokenExpired, "token expired"
|
179
190
|
end
|
180
191
|
reply
|
181
192
|
end
|
data/lib/uaa/version.rb
CHANGED
data/spec/token_coder_spec.rb
CHANGED
@@ -26,9 +26,9 @@ describe TokenCoder do
|
|
26
26
|
@tkn_secret = "test_secret"
|
27
27
|
end
|
28
28
|
|
29
|
-
it "raises
|
30
|
-
expect { subject.decode(nil) }.to raise_exception(
|
31
|
-
expect { subject.decode("one two three") }.to raise_exception(
|
29
|
+
it "raises error if the given auth header is bad" do
|
30
|
+
expect { subject.decode(nil) }.to raise_exception(InvalidTokenFormat)
|
31
|
+
expect { subject.decode("one two three") }.to raise_exception(InvalidTokenFormat)
|
32
32
|
end
|
33
33
|
|
34
34
|
it "encodes/decodes a token using a symmetrical key" do
|
@@ -73,37 +73,40 @@ describe TokenCoder do
|
|
73
73
|
|
74
74
|
it "rejects a token with 'none' signature by default" do
|
75
75
|
tkn = subject.encode(@tkn_body, 'none')
|
76
|
-
expect { TokenCoder.decode(tkn) }.to raise_exception(
|
76
|
+
expect { TokenCoder.decode(tkn) }.to raise_exception(SignatureNotAccepted)
|
77
77
|
end
|
78
78
|
|
79
79
|
it "raises an error if the signing algorithm is not supported" do
|
80
|
-
expect { subject.encode(@tkn_body, 'baz') }.to raise_exception(
|
80
|
+
expect { subject.encode(@tkn_body, 'baz') }.to raise_exception(SignatureNotSupported)
|
81
81
|
end
|
82
82
|
|
83
|
-
it "raises an
|
83
|
+
it "raises an error if the token is for another resource server" do
|
84
84
|
tkn = subject.encode({'aud' => ["other_resource"], 'foo' => "bar"})
|
85
|
-
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(
|
85
|
+
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(InvalidAudience)
|
86
86
|
end
|
87
87
|
|
88
|
-
it "raises
|
88
|
+
it "raises an error if the token is signed by an unknown signing key" do
|
89
89
|
other = TokenCoder.new(:audience_ids => "test_resource", :skey => "other_secret")
|
90
90
|
tkn = other.encode(@tkn_body)
|
91
|
-
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(
|
91
|
+
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(InvalidSignature)
|
92
92
|
end
|
93
93
|
|
94
|
-
it "raises
|
94
|
+
it "raises an error if the token is an unknown signing algorithm" do
|
95
95
|
segments = [Util.json_encode64(:typ => "JWT", :alg =>"BADALGO")]
|
96
96
|
segments << Util.json_encode64(@tkn_body)
|
97
97
|
segments << Util.encode64("BADSIG")
|
98
98
|
tkn = segments.join('.')
|
99
|
-
|
99
|
+
tc = TokenCoder.new(:audience_ids => "test_resource",
|
100
|
+
:skey => "test_secret", :pkey => OpenSSL::PKey::RSA.generate(512),
|
101
|
+
:accept_algorithms => "BADALGO")
|
102
|
+
expect { tc.decode("bEaReR #{tkn}") }.to raise_exception(SignatureNotSupported)
|
100
103
|
end
|
101
104
|
|
102
|
-
it "raises
|
105
|
+
it "raises an error if the token is malformed" do
|
103
106
|
tkn = "one.two.three.four"
|
104
|
-
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(
|
107
|
+
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(InvalidTokenFormat)
|
105
108
|
tkn = "onlyone"
|
106
|
-
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(
|
109
|
+
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(InvalidTokenFormat)
|
107
110
|
end
|
108
111
|
|
109
112
|
it "raises a decode error if a token segment is malformed" do
|
@@ -114,9 +117,9 @@ describe TokenCoder do
|
|
114
117
|
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(DecodeError)
|
115
118
|
end
|
116
119
|
|
117
|
-
it "raises an
|
120
|
+
it "raises an error if the token has expired" do
|
118
121
|
tkn = subject.encode({'foo' => "bar", 'exp' => Time.now.to_i - 60 })
|
119
|
-
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(
|
122
|
+
expect { subject.decode("bEaReR #{tkn}") }.to raise_exception(TokenExpired)
|
120
123
|
end
|
121
124
|
|
122
125
|
it "decodes a token without validation" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cf-uaa-lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2013-01-
|
16
|
+
date: 2013-01-29 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: multi_json
|
@@ -193,12 +193,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
193
193
|
- - ! '>='
|
194
194
|
- !ruby/object:Gem::Version
|
195
195
|
version: '0'
|
196
|
+
segments:
|
197
|
+
- 0
|
198
|
+
hash: 1720438765571027333
|
196
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
200
|
none: false
|
198
201
|
requirements:
|
199
202
|
- - ! '>='
|
200
203
|
- !ruby/object:Gem::Version
|
201
204
|
version: '0'
|
205
|
+
segments:
|
206
|
+
- 0
|
207
|
+
hash: 1720438765571027333
|
202
208
|
requirements: []
|
203
209
|
rubyforge_project: cf-uaa-lib
|
204
210
|
rubygems_version: 1.8.23
|
@@ -206,4 +212,3 @@ signing_key:
|
|
206
212
|
specification_version: 3
|
207
213
|
summary: Client library for CloudFoundry UAA
|
208
214
|
test_files: []
|
209
|
-
has_rdoc:
|