cf-uaa-lib 1.3.5 → 1.3.6
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|