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.
@@ -1,4 +1,6 @@
1
- ## Usage
1
+ Usage
2
+ =====
3
+
2
4
 
3
5
  ```ruby
4
6
  require 'facebook-signed-request'
@@ -30,6 +32,4 @@ request.data
30
32
  # },
31
33
  # "user_id"=>"100000656666199"
32
34
  # }
33
-
34
-
35
35
  ```
@@ -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::Signed::Request::VERSION
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, secret )
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
- @errors = []
13
- @secret = secret
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 nil
71
+ return {}
48
72
  end
49
73
  end
50
74
 
51
75
  def validate_algorithm
52
- if @data.nil? || @data['algorithm'] != "HMAC-SHA256"
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 base64_url_decode( encoded_string )
70
- encoded_string << '=' until ( encoded_string.length % 4 == 0 )
71
- Base64.strict_decode64(encoded_string.gsub("-", "+").gsub("_", "/"))
72
- end
93
+ def validate_timestamp
94
+ timestamp = @data['expires']
73
95
 
74
- def valid?
75
- @errors.empty?
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
@@ -1,7 +1,5 @@
1
1
  module Facebook
2
- module Signed
3
- module Request
4
- VERSION = "0.0.2"
5
- end
2
+ class SignedRequest
3
+ VERSION = "0.1.0"
6
4
  end
7
5
  end
@@ -5,7 +5,9 @@ require 'test_helper'
5
5
  class SignedRequestTest < Test::Unit::TestCase
6
6
 
7
7
  def setup
8
- @secret = "897a956a2f7eadcc5783a458fe3e7556"
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, @secret )
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, @secret )
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, @secret )
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 "re-encoding of payload" do
35
- request = Facebook::SignedRequest.new( @foo, @secret )
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
- puts Base64.encode64 request.data.to_json.to_s
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.2
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.markdown
24
+ - README.md
25
25
  - Rakefile
26
26
  - facebook-signed-request.gemspec
27
27
  - lib/facebook-signed-request.rb