facebook-signed-request 0.0.2 → 0.1.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.
@@ -4,7 +4,7 @@ require "facebook-signed-request/version"
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "facebook-signed-request"
|
7
|
-
s.version = Facebook::
|
7
|
+
s.version = Facebook::SignedRequest::VERSION
|
8
8
|
s.authors = ["hukl"]
|
9
9
|
s.email = ["contact@smyck.org"]
|
10
10
|
s.homepage = ""
|
@@ -1,16 +1,29 @@
|
|
1
1
|
module Facebook
|
2
2
|
class SignedRequest
|
3
|
+
|
4
|
+
class << self
|
5
|
+
attr_accessor :secret
|
6
|
+
end
|
7
|
+
|
3
8
|
attr_reader :errors, :signature, :data
|
4
9
|
|
5
|
-
def initialize( request_data,
|
10
|
+
def initialize( request_data, options = {} )
|
6
11
|
@encoded_signature, @encoded_data = request_data.split(".", 2)
|
12
|
+
@secret = options[:secret] || SignedRequest.secret
|
13
|
+
@errors = []
|
14
|
+
|
7
15
|
|
8
16
|
if @encoded_signature.nil? || @encoded_data.nil?
|
9
17
|
raise ArgumentError, "Invalid Format. See http://developers.facebook.com/docs/authentication/signed_request/"
|
10
18
|
end
|
11
19
|
|
12
|
-
@
|
13
|
-
|
20
|
+
if @secret.nil?
|
21
|
+
raise ArgumentError, "No secret provided. Use SignedRequest.secret= or the options hash"
|
22
|
+
end
|
23
|
+
|
24
|
+
unless @secret.is_a?( String )
|
25
|
+
raise ArgumentError, "Secret should be a String"
|
26
|
+
end
|
14
27
|
|
15
28
|
@signature = extract_request_signature
|
16
29
|
@payload = extract_request_payload
|
@@ -18,8 +31,19 @@ module Facebook
|
|
18
31
|
|
19
32
|
validate_algorithm
|
20
33
|
validate_signature
|
34
|
+
validate_timestamp if options[:strict] == true
|
35
|
+
end
|
36
|
+
|
37
|
+
def base64_url_decode( encoded_string )
|
38
|
+
encoded_string << '=' until ( encoded_string.length % 4 == 0 )
|
39
|
+
Base64.strict_decode64(encoded_string.gsub("-", "+").gsub("_", "/"))
|
21
40
|
end
|
22
41
|
|
42
|
+
def valid?
|
43
|
+
@errors.empty?
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
23
47
|
|
24
48
|
def extract_request_signature
|
25
49
|
begin
|
@@ -44,12 +68,12 @@ module Facebook
|
|
44
68
|
return JSON.parse( @payload )
|
45
69
|
rescue
|
46
70
|
@errors << "Invalid JSON object"
|
47
|
-
return
|
71
|
+
return {}
|
48
72
|
end
|
49
73
|
end
|
50
74
|
|
51
75
|
def validate_algorithm
|
52
|
-
if @data
|
76
|
+
if @data['algorithm'] != "HMAC-SHA256"
|
53
77
|
@errors << "Invalid Algorithm. Expected: HMAC-SHA256"
|
54
78
|
end
|
55
79
|
end
|
@@ -66,13 +90,12 @@ module Facebook
|
|
66
90
|
end
|
67
91
|
end
|
68
92
|
|
69
|
-
def
|
70
|
-
|
71
|
-
Base64.strict_decode64(encoded_string.gsub("-", "+").gsub("_", "/"))
|
72
|
-
end
|
93
|
+
def validate_timestamp
|
94
|
+
timestamp = @data['expires']
|
73
95
|
|
74
|
-
|
75
|
-
|
96
|
+
if timestamp && Time.at( timestamp ) <= Time.now
|
97
|
+
raise ArgumentError, "OAuth Token has expired: #{Time.at( timestamp )}"
|
98
|
+
end
|
76
99
|
end
|
77
100
|
|
78
101
|
end
|
data/test/signed_request_test.rb
CHANGED
@@ -5,7 +5,9 @@ require 'test_helper'
|
|
5
5
|
class SignedRequestTest < Test::Unit::TestCase
|
6
6
|
|
7
7
|
def setup
|
8
|
-
|
8
|
+
|
9
|
+
Facebook::SignedRequest.secret = "897a956a2f7eadcc5783a458fe3e7556"
|
10
|
+
|
9
11
|
@valid_request = "vl0p_bGyDeVZ2I21cJvLd5C9CwpMkU2mcp1eUGWdvWs.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzMDg5ODg4MDAsImlzc3VlZF9hdCI6MTMwODk4NTAxOCwib2F1dGhfdG9rZW4iOiIxMTQ5NTIyOTg1OTM4MTN8Mi5BUUJBdHRSbExWbndxTlBaLjM2MDAuMTMwODk4ODgwMC4xLTEwMDAwMDY1NDM0MzE5OXxUNDl3M0Jxb1pVZWd5cHJ1NTFHcmE3MGhFRDgiLCJ1c2VyIjp7ImNvdW50cnkiOiJkZSIsImxvY2FsZSI6ImVuX1VTIiwiYWdlIjp7Im1pbiI6MjF9fSwidXNlcl9pZCI6IjEwMDAwMDY1NDM0MzE5OSJ9"
|
10
12
|
@invalid_request_1 = "l0p_bGyDeVZ2I21cJvLd5C9CwpMkU2mcp1eUGWdvWs.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzMDg5ODg4MDAsImlzc3VlZF9hdCI6MTMwODk4NTAxOCwib2F1dGhfdG9rZW4iOiIxMTQ5NTIyOTg1OTM4MTN8Mi5BUUJBdHRSbExWbndxTlBaLjM2MDAuMTMwODk4ODgwMC4xLTEwMDAwMDY1NDM0MzE5OXxUNDl3M0Jxb1pVZWd5cHJ1NTFHcmE3MGhFRDgiLCJ1c2VyIjp7ImNvdW50cnkiOiJkZSIsImxvY2FsZSI6ImVuX1VTIiwiYWdlIjp7Im1pbiI6MjF9fSwidXNlcl9pZCI6IjEwMDAwMDY1NDM0MzE5OSJ9"
|
11
13
|
@invalid_request_2 = "vl0p_bGyDeVZ2I21cJvLd5C9CwpMkU2mcp1eUGWdvWs.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzMDg5ODg4MDAsImlzc3VlZF9hdCI6MTMwODk4NTAxOCwib2F1dGhfdG9rZW4iOiIxMTQ5NTIyOTg1OTM4MTN8Mi5BUUJBdHRSbExWbndxTlBaLjM2MDAuMTMwODk4ODgwMC4xLTEwMDAwMDY1NDM0MzE5OXxUNDl3M0Jxb1pVZWd5cHJ1NTFHcmE3MGhFRDgiLCJ1c2VyIjp7ImNvdW50cnkiOiJkZSIsImxvY2FsZSI6ImVuX1VTIiwiYWdlIjp7Im1pbiI6MjF9fSwidXNlcl9pZCI6IjEwMDAwMDY1NDM0MzE5OSJ"
|
@@ -14,28 +16,65 @@ class SignedRequestTest < Test::Unit::TestCase
|
|
14
16
|
end
|
15
17
|
|
16
18
|
test "parsing a valid request" do
|
17
|
-
request = Facebook::SignedRequest.new( @valid_request
|
19
|
+
request = Facebook::SignedRequest.new( @valid_request )
|
18
20
|
assert request.valid?, "Request should be valid"
|
19
21
|
assert request.errors == [], "Request should contain no errors"
|
20
22
|
end
|
21
23
|
|
22
24
|
test "parsing a request with invalid signature" do
|
23
|
-
request = Facebook::SignedRequest.new( @invalid_request_1
|
25
|
+
request = Facebook::SignedRequest.new( @invalid_request_1 )
|
24
26
|
assert_equal false, request.valid?
|
25
27
|
assert_equal 2, request.errors.length
|
26
28
|
end
|
27
29
|
|
28
30
|
test "parsing a request with invalid payload" do
|
29
|
-
request = Facebook::SignedRequest.new( @invalid_request_2
|
31
|
+
request = Facebook::SignedRequest.new( @invalid_request_2 )
|
30
32
|
assert_equal false, request.valid?
|
31
33
|
assert_equal 4, request.errors.length
|
32
34
|
end
|
33
35
|
|
34
|
-
test "
|
35
|
-
|
36
|
+
test "new request with invalid secret" do
|
37
|
+
exception = assert_raise ArgumentError do
|
38
|
+
request = Facebook::SignedRequest.new( "foo.bar", :secret => 2 )
|
39
|
+
end
|
40
|
+
|
41
|
+
expected = "Secret should be a String"
|
42
|
+
|
43
|
+
assert_equal expected, exception.message
|
44
|
+
end
|
45
|
+
|
46
|
+
test "new request with missing secret" do
|
47
|
+
Facebook::SignedRequest.secret = nil
|
36
48
|
|
37
|
-
|
49
|
+
exception = assert_raise ArgumentError do
|
50
|
+
request = Facebook::SignedRequest.new( "foo.bar" )
|
51
|
+
end
|
38
52
|
|
53
|
+
expected = "No secret provided. Use SignedRequest.secret= or the options hash"
|
39
54
|
|
55
|
+
assert_equal expected, exception.message
|
40
56
|
end
|
57
|
+
|
58
|
+
test "new request with invalid parameters" do
|
59
|
+
exception = assert_raise ArgumentError do
|
60
|
+
request = Facebook::SignedRequest.new( "foobar" )
|
61
|
+
end
|
62
|
+
|
63
|
+
expected = "Invalid Format. See http://developers.facebook.com/docs/authentication/signed_request/"
|
64
|
+
|
65
|
+
assert_equal expected, exception.message
|
66
|
+
end
|
67
|
+
|
68
|
+
test "request with :strict => true fails for expired oauth token" do
|
69
|
+
exception = assert_raise ArgumentError do
|
70
|
+
request = Facebook::SignedRequest.new( @valid_request, :strict => true )
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
assert(
|
75
|
+
exception.message.match("OAuth Token has expired"),
|
76
|
+
"Wrong Exception message"
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
41
80
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: facebook-signed-request
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -21,7 +21,7 @@ extra_rdoc_files: []
|
|
21
21
|
files:
|
22
22
|
- .gitignore
|
23
23
|
- Gemfile
|
24
|
-
- README.
|
24
|
+
- README.md
|
25
25
|
- Rakefile
|
26
26
|
- facebook-signed-request.gemspec
|
27
27
|
- lib/facebook-signed-request.rb
|