facebook-signed-request 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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