perimeter_x 1.2.0 → 1.3.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +3 -0
- data/Gemfile.lock +10 -5
- data/Rakefile +1 -0
- data/changelog.md +8 -0
- data/examples/app/controllers/home_controller.rb +1 -1
- data/lib/perimeter_x.rb +39 -19
- data/lib/perimeterx/configuration.rb +2 -2
- data/lib/perimeterx/internal/clients/perimeter_x_activity_client.rb +7 -4
- data/lib/perimeterx/internal/{perimeter_x_cookie_v1.rb → payload/perimeter_x_cookie_v1.rb} +1 -1
- data/lib/perimeterx/internal/{perimeter_x_cookie_v3.rb → payload/perimeter_x_cookie_v3.rb} +1 -1
- data/lib/perimeterx/internal/{perimeter_x_cookie.rb → payload/perimeter_x_payload.rb} +9 -4
- data/lib/perimeterx/internal/payload/perimeter_x_token_v1.rb +38 -0
- data/lib/perimeterx/internal/payload/perimeter_x_token_v3.rb +36 -0
- data/lib/perimeterx/internal/perimeter_x_context.rb +30 -19
- data/lib/perimeterx/internal/validators/perimeter_x_captcha_validator.rb +1 -1
- data/lib/perimeterx/internal/validators/perimeter_x_cookie_validator.rb +13 -10
- data/lib/perimeterx/internal/validators/perimeter_x_s2s_validator.rb +4 -3
- data/lib/perimeterx/utils/px_constants.rb +23 -17
- data/lib/perimeterx/utils/px_http_client.rb +1 -1
- data/lib/perimeterx/utils/px_template_factory.rb +12 -6
- data/lib/perimeterx/utils/templates/block.mobile.mustache +133 -0
- data/lib/perimeterx/utils/templates/captcha.mobile.mustache +196 -0
- data/lib/perimeterx/version.rb +1 -1
- data/readme.md +1 -1
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f3a1b696f592b2f1478cc376a96475a5d5f0778
|
4
|
+
data.tar.gz: e859865af132477c953d6aed1a7c70bb927b432e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f67c50466d0a347d7d5e3dc6c30f66332a3dabb27a34152e49c36a6614fa06ce81bc02d8f50ba2e061f9fb4cef8b21e9fb684d2d2b8b138ffab87298d0e1f81
|
7
|
+
data.tar.gz: 35d39968545b296e04f02bed0bb2c67b40ca1ff6773e352533fbe06e2795ad630a838d159fe517a12702e79d5054d81ef828fa966e9278dec7fd6eaa37dd2e06
|
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
perimeter_x (1.0
|
4
|
+
perimeter_x (1.3.0)
|
5
5
|
activesupport (>= 4.2.0)
|
6
|
-
|
6
|
+
concurrent-ruby (~> 1.0, >= 1.0.5)
|
7
7
|
mustache (~> 1.0, >= 1.0.3)
|
8
|
+
typhoeus (~> 1.1, >= 1.1.2)
|
8
9
|
|
9
10
|
GEM
|
10
11
|
remote: https://rubygems.org/
|
@@ -16,13 +17,15 @@ GEM
|
|
16
17
|
tzinfo (~> 1.1)
|
17
18
|
concurrent-ruby (1.0.5)
|
18
19
|
diff-lcs (1.3)
|
19
|
-
|
20
|
-
|
20
|
+
ethon (0.10.1)
|
21
|
+
ffi (>= 1.3.0)
|
22
|
+
ffi (1.9.18)
|
23
|
+
i18n (0.8.6)
|
21
24
|
metaclass (0.0.4)
|
22
25
|
minitest (5.10.1)
|
23
26
|
mocha (1.2.1)
|
24
27
|
metaclass (~> 0.0.1)
|
25
|
-
mustache (1.0.
|
28
|
+
mustache (1.0.5)
|
26
29
|
rake (10.4.2)
|
27
30
|
rspec (3.5.0)
|
28
31
|
rspec-core (~> 3.5.0)
|
@@ -38,6 +41,8 @@ GEM
|
|
38
41
|
rspec-support (~> 3.5.0)
|
39
42
|
rspec-support (3.5.0)
|
40
43
|
thread_safe (0.3.6)
|
44
|
+
typhoeus (1.1.2)
|
45
|
+
ethon (>= 0.9.0)
|
41
46
|
tzinfo (1.2.3)
|
42
47
|
thread_safe (~> 0.1)
|
43
48
|
|
data/Rakefile
CHANGED
data/changelog.md
CHANGED
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
7
7
|
|
8
|
+
## [1.3.0] - 2017-06-04
|
9
|
+
### Added
|
10
|
+
- Sending client_uuid on page_requested activities
|
11
|
+
- Supporting mobile sdk
|
12
|
+
### Fixed
|
13
|
+
- Using `request.env` instead of `env`
|
14
|
+
|
8
15
|
## [1.2.0] - 2017-06-04
|
9
16
|
### Fixed
|
10
17
|
- Default timeouts for post api requests
|
@@ -27,3 +34,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
27
34
|
- Constants on px_constants
|
28
35
|
- Cookie Validation flow when cookie score was over the configured threshold
|
29
36
|
- Using symbols instead of strings for requests body
|
37
|
+
|
data/lib/perimeter_x.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
require 'json'
|
3
|
+
require 'base64'
|
1
4
|
require 'perimeterx/configuration'
|
2
5
|
require 'perimeterx/utils/px_logger'
|
3
6
|
require 'perimeterx/utils/px_constants'
|
@@ -10,29 +13,46 @@ require 'perimeterx/internal/validators/perimeter_x_cookie_validator'
|
|
10
13
|
require 'perimeterx/internal/validators/perimeter_x_captcha_validator'
|
11
14
|
|
12
15
|
module PxModule
|
13
|
-
|
14
16
|
# Module expose API
|
15
17
|
def px_verify_request
|
16
|
-
verified, px_ctx = PerimeterX.instance.verify(env)
|
18
|
+
verified, px_ctx = PerimeterX.instance.verify(request.env)
|
17
19
|
|
18
20
|
# Invalidate _pxCaptcha, can be done only on the controller level
|
19
|
-
cookies[:_pxCaptcha] = {
|
21
|
+
cookies[:_pxCaptcha] = {value: "", expires: -1.minutes.from_now}
|
20
22
|
|
21
|
-
|
23
|
+
unless verified
|
22
24
|
# In case custon block handler exists
|
23
25
|
if (PerimeterX.instance.px_config.key?(:custom_block_handler))
|
24
|
-
PerimeterX.instance.px_config[:logger].debug(
|
26
|
+
PerimeterX.instance.px_config[:logger].debug('PxModule[px_verify_request]: custom_block_handler triggered')
|
25
27
|
return instance_exec(px_ctx, &PerimeterX.instance.px_config[:custom_block_handler])
|
26
28
|
else
|
27
29
|
# Generate template
|
28
|
-
PerimeterX.instance.px_config[:logger].debug(
|
30
|
+
PerimeterX.instance.px_config[:logger].debug('PxModule[px_verify_request]: sending default block page')
|
29
31
|
html = PxTemplateFactory.get_template(px_ctx, PerimeterX.instance.px_config)
|
30
|
-
response.headers[
|
32
|
+
response.headers['Content-Type'] = 'text/html'
|
31
33
|
response.status = 403
|
32
|
-
|
34
|
+
# Web handler
|
35
|
+
if px_ctx.context[:cookie_origin] == 'cookie'
|
36
|
+
PerimeterX.instance.px_config[:logger].debug('PxModule[px_verify_request]: web block')
|
37
|
+
response.headers['Content-Type'] = 'text/html'
|
38
|
+
render :html => html
|
39
|
+
else # Mobile SDK
|
40
|
+
PerimeterX.instance.px_config[:logger].debug('PxModule[px_verify_request]: mobile sdk block')
|
41
|
+
response.headers['Content-Type'] = 'application/json'
|
42
|
+
hash_json = {
|
43
|
+
:action => px_ctx.context[:block_action],
|
44
|
+
:uuid => px_ctx.context[:uuid],
|
45
|
+
:vid => px_ctx.context[:vid],
|
46
|
+
:appId => PerimeterX.instance.px_config[:app_id],
|
47
|
+
:page => Base64.strict_encode64(html),
|
48
|
+
:collectorUrl => "https://collector-#{PerimeterX.instance.px_config[:app_id]}.perimeterx.net"
|
49
|
+
}
|
50
|
+
render :json => hash_json
|
51
|
+
end
|
33
52
|
end
|
34
53
|
end
|
35
54
|
|
55
|
+
# Request was verified
|
36
56
|
return verified
|
37
57
|
end
|
38
58
|
|
@@ -41,7 +61,7 @@ module PxModule
|
|
41
61
|
end
|
42
62
|
|
43
63
|
|
44
|
-
#
|
64
|
+
# PerimeterX Module
|
45
65
|
class PerimeterX
|
46
66
|
@@__instance = nil
|
47
67
|
@@mutex = Mutex.new
|
@@ -62,19 +82,19 @@ module PxModule
|
|
62
82
|
|
63
83
|
def self.instance
|
64
84
|
return @@__instance if !@@__instance.nil?
|
65
|
-
raise Exception.new(
|
85
|
+
raise Exception.new('Please initialize perimeter x first')
|
66
86
|
end
|
67
87
|
|
68
88
|
|
69
89
|
#Instance Methods
|
70
90
|
def verify(env)
|
71
91
|
begin
|
72
|
-
@logger.debug(
|
73
|
-
req = ActionDispatch::Request.new(env)
|
92
|
+
@logger.debug('PerimeterX[pxVerify]')
|
74
93
|
if (!@px_config[:module_enabled])
|
75
|
-
@logger.warn(
|
94
|
+
@logger.warn('Module is disabled')
|
76
95
|
return true
|
77
96
|
end
|
97
|
+
req = ActionDispatch::Request.new(env)
|
78
98
|
px_ctx = PerimeterXContext.new(@px_config, req)
|
79
99
|
|
80
100
|
# Captcha phase
|
@@ -96,7 +116,7 @@ module PxModule
|
|
96
116
|
end
|
97
117
|
rescue Exception => e
|
98
118
|
@logger.error("#{e.backtrace.first}: #{e.message} (#{e.class})")
|
99
|
-
e.backtrace.drop(1).map {
|
119
|
+
e.backtrace.drop(1).map {|s| @logger.error("\t#{s}")}
|
100
120
|
return true
|
101
121
|
end
|
102
122
|
end
|
@@ -111,11 +131,11 @@ module PxModule
|
|
111
131
|
@px_cookie_validator = PerimeterxCookieValidator.new(@px_config)
|
112
132
|
@px_s2s_validator = PerimeterxS2SValidator.new(@px_config, @px_http_client)
|
113
133
|
@px_captcha_validator = PerimeterxCaptchaValidator.new(@px_config, @px_http_client)
|
114
|
-
@logger.debug(
|
134
|
+
@logger.debug('PerimeterX[initialize]Z')
|
115
135
|
end
|
116
136
|
|
117
137
|
private def handle_verification(px_ctx)
|
118
|
-
@logger.debug(
|
138
|
+
@logger.debug('PerimeterX[handle_verification]')
|
119
139
|
@logger.debug("PerimeterX[handle_verification]: processing ended - score:#{px_ctx.context[:score]}, uuid:#{px_ctx.context[:uuid]}")
|
120
140
|
|
121
141
|
score = px_ctx.context[:score]
|
@@ -130,12 +150,12 @@ module PxModule
|
|
130
150
|
@px_activity_client.send_block_activity(px_ctx)
|
131
151
|
|
132
152
|
# In case were in monitor mode, end here
|
133
|
-
if(@px_config[:module_mode] == PxModule::MONITOR_MODE)
|
134
|
-
@logger.debug(
|
153
|
+
if (@px_config[:module_mode] == PxModule::MONITOR_MODE)
|
154
|
+
@logger.debug('PerimeterX[handle_verification]: monitor mode is on, passing request')
|
135
155
|
return true
|
136
156
|
end
|
137
157
|
|
138
|
-
@logger.debug(
|
158
|
+
@logger.debug('PerimeterX[handle_verification]: verification ended, the request should be blocked')
|
139
159
|
|
140
160
|
return false, px_ctx
|
141
161
|
end
|
@@ -20,7 +20,7 @@ module PxModule
|
|
20
20
|
:api_connect_timeout => 1,
|
21
21
|
:api_timeout => 1,
|
22
22
|
:max_buffer_len => 10,
|
23
|
-
:send_page_activities =>
|
23
|
+
:send_page_activities => true,
|
24
24
|
:send_block_activities => true,
|
25
25
|
:sdk_name => PxModule::SDK_NAME,
|
26
26
|
:debug => false,
|
@@ -31,7 +31,7 @@ module PxModule
|
|
31
31
|
|
32
32
|
def initialize(params)
|
33
33
|
PX_DEFAULT[:perimeterx_server_host] = "https://sapi-#{params[:app_id].downcase}.perimeterx.net"
|
34
|
-
@configuration = PX_DEFAULT.merge(params)
|
34
|
+
@configuration = PX_DEFAULT.merge(params)
|
35
35
|
@configuration[:logger] = PxLogger.new(@configuration[:debug])
|
36
36
|
end
|
37
37
|
end
|
@@ -18,6 +18,8 @@ module PxModule
|
|
18
18
|
end
|
19
19
|
|
20
20
|
details[:module_version] = @px_config[:sdk_name]
|
21
|
+
details[:cookie_origin] = px_ctx.context[:cookie_origin]
|
22
|
+
|
21
23
|
px_data = {
|
22
24
|
:type => activity_type,
|
23
25
|
:headers => format_headers(px_ctx),
|
@@ -53,9 +55,9 @@ module PxModule
|
|
53
55
|
end
|
54
56
|
|
55
57
|
details = {
|
56
|
-
:block_uuid
|
57
|
-
:block_score
|
58
|
-
:block_reason
|
58
|
+
:block_uuid => px_ctx.context[:uuid],
|
59
|
+
:block_score => px_ctx.context[:score],
|
60
|
+
:block_reason => px_ctx.context[:blocking_reason]
|
59
61
|
}
|
60
62
|
|
61
63
|
send_to_perimeterx(PxModule::BLOCK_ACTIVITY, px_ctx, details)
|
@@ -70,7 +72,8 @@ module PxModule
|
|
70
72
|
|
71
73
|
details = {
|
72
74
|
:http_version => px_ctx.context[:http_version],
|
73
|
-
:http_method => px_ctx.context[:http_method]
|
75
|
+
:http_method => px_ctx.context[:http_method],
|
76
|
+
:client_uuid => px_ctx.context[:uuid]
|
74
77
|
}
|
75
78
|
|
76
79
|
if (px_ctx.context.key?(:decoded_cookie))
|
@@ -4,7 +4,7 @@ require 'openssl'
|
|
4
4
|
require 'perimeterx/internal/exceptions/px_cookie_decryption_exception'
|
5
5
|
|
6
6
|
module PxModule
|
7
|
-
class
|
7
|
+
class PerimeterxPayload
|
8
8
|
attr_accessor :px_cookie, :px_config, :px_ctx, :cookie_secret, :decoded_cookie
|
9
9
|
|
10
10
|
def initialize(px_config)
|
@@ -13,7 +13,12 @@ module PxModule
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.px_cookie_factory(px_ctx, px_config)
|
16
|
-
if
|
16
|
+
if px_ctx.context[:cookie_origin] == 'header'
|
17
|
+
if (px_ctx.context[:px_cookie].key?(:v3))
|
18
|
+
return PerimeterxTokenV3.new(px_config,px_ctx)
|
19
|
+
end
|
20
|
+
return PerimeterxTokenV1.new(px_config,px_ctx)
|
21
|
+
elsif (px_ctx.context[:px_cookie].key?(:v3))
|
17
22
|
return PerimeterxCookieV3.new(px_config, px_ctx)
|
18
23
|
end
|
19
24
|
return PerimeterxCookieV1.new(px_config, px_ctx)
|
@@ -131,8 +136,8 @@ module PxModule
|
|
131
136
|
hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, @cookie_secret, hmac_str)
|
132
137
|
# ref: https://thisdata.com/blog/timing-attacks-against-string-comparison/
|
133
138
|
password_correct = ActiveSupport::SecurityUtils.secure_compare(
|
134
|
-
|
135
|
-
|
139
|
+
::Digest::SHA256.hexdigest(cookie_hmac),
|
140
|
+
::Digest::SHA256.hexdigest(hmac)
|
136
141
|
)
|
137
142
|
|
138
143
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module PxModule
|
2
|
+
class PerimeterxTokenV1 < PerimeterxPayload
|
3
|
+
|
4
|
+
attr_accessor :px_config, :px_ctx
|
5
|
+
|
6
|
+
def initialize(px_config, px_ctx)
|
7
|
+
super(px_config)
|
8
|
+
@px_ctx = px_ctx
|
9
|
+
@px_cookie = px_ctx.get_px_cookie
|
10
|
+
@cookie_secret = px_config[:cookie_key]
|
11
|
+
@logger.debug('PerimeterxTokenV1[initialize]')
|
12
|
+
end
|
13
|
+
|
14
|
+
def cookie_score
|
15
|
+
return @decoded_cookie[:s][:b]
|
16
|
+
end
|
17
|
+
|
18
|
+
def cookie_hmac
|
19
|
+
return @decoded_cookie[:h]
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_format?(cookie)
|
23
|
+
return cookie.key?(:t) && cookie.key?(:s) && cookie[:s].key?(:b) && cookie.key?(:s) && cookie.key?(:v) && cookie.key?(:h)
|
24
|
+
end
|
25
|
+
|
26
|
+
def cookie_block_action
|
27
|
+
return 'c'
|
28
|
+
end
|
29
|
+
|
30
|
+
def secured?
|
31
|
+
hmac_str = "#{cookie_time}#{@decoded_cookie[:s][:a]}#{cookie_score}#{cookie_uuid}#{cookie_vid}"
|
32
|
+
|
33
|
+
return hmac_valid?(hmac_str, cookie_hmac)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PxModule
|
2
|
+
class PerimeterxTokenV3 < PerimeterxPayload
|
3
|
+
|
4
|
+
attr_accessor :px_config, :px_ctx, :cookie_hash
|
5
|
+
|
6
|
+
def initialize(px_config, px_ctx)
|
7
|
+
super(px_config)
|
8
|
+
hash, cookie = px_ctx.get_px_cookie().split(':', 2)
|
9
|
+
@px_cookie = cookie
|
10
|
+
@cookie_hash = hash
|
11
|
+
@px_ctx = px_ctx
|
12
|
+
@cookie_secret = px_config[:cookie_key]
|
13
|
+
@logger.debug('PerimeterxTokenV3[initialize]')
|
14
|
+
end
|
15
|
+
|
16
|
+
def cookie_score
|
17
|
+
return @decoded_cookie[:s]
|
18
|
+
end
|
19
|
+
|
20
|
+
def cookie_hmac
|
21
|
+
return @cookie_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid_format?(cookie)
|
25
|
+
return cookie.key?(:t) && cookie.key?(:s) && cookie.key?(:u) && cookie.key?(:u) && cookie.key?(:a)
|
26
|
+
end
|
27
|
+
|
28
|
+
def cookie_block_action
|
29
|
+
@decoded_cookie[:a]
|
30
|
+
end
|
31
|
+
|
32
|
+
def secured?
|
33
|
+
return hmac_valid?(@px_cookie, cookie_hmac)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -7,31 +7,42 @@ module PxModule
|
|
7
7
|
attr_accessor :px_config
|
8
8
|
|
9
9
|
def initialize(px_config, req)
|
10
|
-
@logger = px_config[:logger]
|
11
|
-
@logger.debug(
|
10
|
+
@logger = px_config[:logger]
|
11
|
+
@logger.debug('PerimeterXContext[initialize]')
|
12
12
|
@context = Hash.new
|
13
13
|
|
14
14
|
@context[:px_cookie] = Hash.new
|
15
15
|
@context[:headers] = Hash.new
|
16
|
+
@context[:cookie_origin] = 'cookie'
|
16
17
|
cookies = req.cookies
|
17
|
-
|
18
|
+
|
19
|
+
# Get token from header
|
20
|
+
if req.headers[PxModule::TOKEN_HEADER]
|
21
|
+
@context[:cookie_origin] = 'header'
|
22
|
+
token = req.headers[PxModule::TOKEN_HEADER]
|
23
|
+
if token.include? ':'
|
24
|
+
exploded_token = token.split(':', 2)
|
25
|
+
cookie_sym = "v#{exploded_token[0]}".to_sym
|
26
|
+
@context[:px_cookie][cookie_sym] = exploded_token[1]
|
27
|
+
end
|
28
|
+
elsif !cookies.empty? # Get cookie from jar
|
18
29
|
# Prepare hashed cookies
|
19
30
|
cookies.each do |k, v|
|
20
31
|
case k.to_s
|
21
|
-
when
|
32
|
+
when '_px3'
|
22
33
|
@context[:px_cookie][:v3] = v
|
23
|
-
when
|
34
|
+
when '_px'
|
24
35
|
@context[:px_cookie][:v1] = v
|
25
|
-
when
|
36
|
+
when '_pxCaptcha'
|
26
37
|
@context[:px_captcha] = v
|
27
38
|
end
|
28
39
|
end #end case
|
29
40
|
end #end empty cookies
|
30
41
|
|
31
42
|
req.headers.each do |k, v|
|
32
|
-
if (k.start_with?
|
33
|
-
header = k.to_s.gsub(
|
34
|
-
header = header.gsub(
|
43
|
+
if (k.start_with? 'HTTP_')
|
44
|
+
header = k.to_s.gsub('HTTP_', '')
|
45
|
+
header = header.gsub('_', '-').downcase
|
35
46
|
@context[:headers][header.to_sym] = v
|
36
47
|
end
|
37
48
|
end #end headers foreach
|
@@ -52,9 +63,9 @@ module PxModule
|
|
52
63
|
end
|
53
64
|
|
54
65
|
if req.server_protocol
|
55
|
-
httpVer = req.server_protocol.split(
|
66
|
+
httpVer = req.server_protocol.split('/')
|
56
67
|
if httpVer.size > 0
|
57
|
-
@context[:http_version] = httpVer[1]
|
68
|
+
@context[:http_version] = httpVer[1]
|
58
69
|
end
|
59
70
|
end
|
60
71
|
@context[:http_method] = req.method
|
@@ -65,19 +76,19 @@ module PxModule
|
|
65
76
|
sensitive_routes.each do |sensitive_route|
|
66
77
|
return true if uri.start_with? sensitive_route
|
67
78
|
end
|
68
|
-
|
79
|
+
false
|
69
80
|
end
|
70
81
|
|
71
82
|
def set_block_action_type(action)
|
72
83
|
@context[:block_action] = case action
|
73
|
-
when
|
74
|
-
|
75
|
-
when
|
76
|
-
return
|
77
|
-
when
|
78
|
-
return
|
84
|
+
when 'c'
|
85
|
+
'captcha'
|
86
|
+
when 'b'
|
87
|
+
return 'block'
|
88
|
+
when 'j'
|
89
|
+
return 'challenge'
|
79
90
|
else
|
80
|
-
return
|
91
|
+
return captcha
|
81
92
|
end
|
82
93
|
end
|
83
94
|
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'perimeterx/utils/px_constants'
|
2
|
-
require 'perimeterx/internal/
|
3
|
-
require 'perimeterx/internal/
|
4
|
-
require 'perimeterx/internal/
|
2
|
+
require 'perimeterx/internal/payload/perimeter_x_payload'
|
3
|
+
require 'perimeterx/internal/payload/perimeter_x_token_v1'
|
4
|
+
require 'perimeterx/internal/payload/perimeter_x_token_v3'
|
5
|
+
require 'perimeterx/internal/payload/perimeter_x_cookie_v1'
|
6
|
+
require 'perimeterx/internal/payload/perimeter_x_cookie_v3'
|
5
7
|
|
6
8
|
module PxModule
|
7
9
|
class PerimeterxCookieValidator
|
@@ -24,7 +26,7 @@ module PxModule
|
|
24
26
|
end
|
25
27
|
|
26
28
|
# Deserialize cookie start
|
27
|
-
cookie =
|
29
|
+
cookie = PerimeterxPayload.px_cookie_factory(px_ctx, @px_config)
|
28
30
|
if (!cookie.deserialize())
|
29
31
|
@logger.warn("PerimeterxCookieValidator:[verify]: invalid cookie")
|
30
32
|
px_ctx.context[:s2s_call_reason] = PxModule::COOKIE_DECRYPTION_FAILED
|
@@ -46,6 +48,7 @@ module PxModule
|
|
46
48
|
if (cookie.high_score?)
|
47
49
|
@logger.warn("PerimeterxCookieValidator:[verify]: cookie high score")
|
48
50
|
px_ctx.context[:s2s_call_reason] = PxModule::COOKIE_HIGH_SCORE
|
51
|
+
px_ctx.context[:blocking_reason] = 'cookie_high_score'
|
49
52
|
return true, px_ctx
|
50
53
|
end
|
51
54
|
|
@@ -54,12 +57,12 @@ module PxModule
|
|
54
57
|
px_ctx.context[:s2s_call_reason] = PxModule::COOKIE_VALIDATION_FAILED
|
55
58
|
return false, px_ctx
|
56
59
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
|
61
|
+
if (px_ctx.context[:sensitive_route])
|
62
|
+
@logger.info("PerimeterxCookieValidator:[verify]: cookie was verified but route is sensitive")
|
63
|
+
px_ctx.context[:s2s_call_reason] = PxModule::SENSITIVE_ROUTE
|
64
|
+
return false, px_ctx
|
65
|
+
end
|
63
66
|
|
64
67
|
@logger.debug("PerimeterxCookieValidator:[verify]: cookie validation passed succesfully")
|
65
68
|
|
@@ -5,11 +5,11 @@ module PxModule
|
|
5
5
|
|
6
6
|
def initialize(px_config, http_client)
|
7
7
|
super(px_config, http_client)
|
8
|
-
@logger.debug(
|
8
|
+
@logger.debug('PerimeterxS2SValidator[initialize]')
|
9
9
|
end
|
10
10
|
|
11
11
|
def send_risk_request(px_ctx)
|
12
|
-
@logger.debug(
|
12
|
+
@logger.debug('PerimeterxS2SValidator[send_risk_request]: send_risk_request')
|
13
13
|
|
14
14
|
risk_mode = PxModule::RISK_MODE_ACTIVE
|
15
15
|
if @px_config[:module_mode] == PxModule::MONITOR_MODE
|
@@ -26,6 +26,7 @@ module PxModule
|
|
26
26
|
:additional => {
|
27
27
|
:s2s_call_reason => px_ctx.context[:s2s_call_reason],
|
28
28
|
:module_version => @px_config[:sdk_name],
|
29
|
+
:cookie_origin => px_ctx.context[:cookie_origin],
|
29
30
|
:http_method => px_ctx.context[:http_method],
|
30
31
|
:http_version => px_ctx.context[:http_version],
|
31
32
|
:risk_mode => risk_mode
|
@@ -103,7 +104,7 @@ module PxModule
|
|
103
104
|
if(response.code != 200)
|
104
105
|
@logger.warn("PerimeterxS2SValidator[verify]: bad response, return code #{response.code}")
|
105
106
|
px_ctx.context[:uuid] = ""
|
106
|
-
px_ctx.context[:s2s_error_msg] = response_body[:message]
|
107
|
+
px_ctx.context[:s2s_error_msg] = !response_body || response_body[:message].nil? ? 'unknown' : response_body[:message]
|
107
108
|
end
|
108
109
|
|
109
110
|
@logger.debug("PerimeterxS2SValidator[verify]: done")
|
@@ -4,33 +4,35 @@ module PxModule
|
|
4
4
|
# Misc
|
5
5
|
MONITOR_MODE = 1
|
6
6
|
ACTIVE_MODE = 2
|
7
|
-
RISK_MODE_ACTIVE =
|
8
|
-
RISK_MODE_MONITOR =
|
7
|
+
RISK_MODE_ACTIVE = 'active_blocking'
|
8
|
+
RISK_MODE_MONITOR = 'monitor'
|
9
9
|
SDK_NAME = "RUBY SDK v#{PxModule::VERSION}"
|
10
10
|
|
11
11
|
# Routes
|
12
|
-
API_V1_S2S =
|
13
|
-
API_V1_CAPTCHA =
|
14
|
-
API_V2_RISK =
|
12
|
+
API_V1_S2S = '/api/v1/collector/s2s'
|
13
|
+
API_V1_CAPTCHA = '/api/v1/risk/captcha'
|
14
|
+
API_V2_RISK = '/api/v2/risk'
|
15
15
|
|
16
16
|
# Activity Types
|
17
|
-
BLOCK_ACTIVITY =
|
18
|
-
PAGE_REQUESTED_ACTIVITY =
|
17
|
+
BLOCK_ACTIVITY = 'block'
|
18
|
+
PAGE_REQUESTED_ACTIVITY = 'page_requested'
|
19
19
|
|
20
20
|
# PxContext
|
21
|
-
NO_COOKIE =
|
22
|
-
INVALID_COOKIE =
|
23
|
-
EXPIRED_COOKIE =
|
24
|
-
COOKIE_HIGH_SCORE =
|
25
|
-
COOKIE_VALIDATION_FAILED =
|
26
|
-
COOKIE_DECRYPTION_FAILED =
|
27
|
-
SENSITIVE_ROUTE =
|
21
|
+
NO_COOKIE = 'no_cookie'
|
22
|
+
INVALID_COOKIE = 'invalid_cookie'
|
23
|
+
EXPIRED_COOKIE = 'cookie_expired'
|
24
|
+
COOKIE_HIGH_SCORE = 'cookie_high_score'
|
25
|
+
COOKIE_VALIDATION_FAILED = 'cookie_validation_failed'
|
26
|
+
COOKIE_DECRYPTION_FAILED = 'cookie_decryption_failed'
|
27
|
+
SENSITIVE_ROUTE = 'sensitive_route'
|
28
28
|
|
29
29
|
# Templates
|
30
|
-
BLOCK_TEMPLATE =
|
31
|
-
CAPTCHA_TEMPLATE =
|
30
|
+
BLOCK_TEMPLATE = 'block'
|
31
|
+
CAPTCHA_TEMPLATE = 'captcha'
|
32
|
+
TEMPLATE_EXT = '.mustache'
|
32
33
|
|
33
|
-
|
34
|
+
|
35
|
+
# Template Props
|
34
36
|
PROP_REF_ID = :refId
|
35
37
|
PROP_APP_ID = :appId
|
36
38
|
PROP_VID = :vid
|
@@ -39,7 +41,11 @@ module PxModule
|
|
39
41
|
PROP_CUSTOM_LOGO = :customLogo
|
40
42
|
PROP_CSS_REF = :cssRef
|
41
43
|
PROP_JS_REF = :jsRef
|
44
|
+
HOST_URL = :hostUrl
|
42
45
|
|
43
46
|
VISIBLE = 'visible'
|
44
47
|
HIDDEN = 'hidden'
|
48
|
+
|
49
|
+
# Mobile SDK
|
50
|
+
TOKEN_HEADER = 'X-PX-AUTHORIZATION'
|
45
51
|
end
|
@@ -15,7 +15,7 @@ module PxModule
|
|
15
15
|
@logger.debug("PxHttpClient[initialize]: HTTP client is being initilized with base_uri: #{px_config[:perimeterx_server_host]}")
|
16
16
|
end
|
17
17
|
|
18
|
-
# Runs a POST
|
18
|
+
# Runs a POST command to Perimeter X servers
|
19
19
|
# Params:
|
20
20
|
# +path+:: string containing uri
|
21
21
|
# +body+:: hash object, containing the request body, must be converted to json format
|
@@ -5,15 +5,20 @@ module PxModule
|
|
5
5
|
|
6
6
|
def self.get_template(px_ctx, px_config)
|
7
7
|
logger = px_config[:logger]
|
8
|
-
if (px_config[:challenge_enabled] && px_ctx.context[:block_action] ==
|
9
|
-
logger.debug(
|
8
|
+
if (px_config[:challenge_enabled] && px_ctx.context[:block_action] == 'challenge')
|
9
|
+
logger.debug('PxTemplateFactory[get_template]: px challange triggered')
|
10
10
|
return px_ctx.context[:block_action_data].html_safe
|
11
11
|
end
|
12
12
|
|
13
|
-
logger.debug(
|
14
|
-
template_type =
|
13
|
+
logger.debug('PxTemplateFactory[get_template]: rendering template')
|
14
|
+
template_type = px_ctx.context[:block_action] == 'captcha' ? PxModule::CAPTCHA_TEMPLATE : BLOCK_TEMPLATE
|
15
15
|
|
16
|
-
|
16
|
+
template_postfix = ''
|
17
|
+
if px_ctx.context[:cookie_origin] == 'header'
|
18
|
+
template_postfix = '.mobile'
|
19
|
+
end
|
20
|
+
|
21
|
+
Mustache.template_file = "#{File.dirname(__FILE__) }/templates/#{template_type}#{template_postfix}#{PxModule::TEMPLATE_EXT}"
|
17
22
|
view = Mustache.new
|
18
23
|
|
19
24
|
view[PxModule::PROP_APP_ID] = px_config[:app_id]
|
@@ -23,9 +28,10 @@ module PxModule
|
|
23
28
|
view[PxModule::PROP_CUSTOM_LOGO] = px_config[:custom_logo]
|
24
29
|
view[PxModule::PROP_CSS_REF] = px_config[:css_ref]
|
25
30
|
view[PxModule::PROP_JS_REF] = px_config[:js_ref]
|
31
|
+
view[PxModule::HOST_URL] = "https://collector-#{px_config[:app_id]}.perimeterx.net"
|
26
32
|
view[PxModule::PROP_LOGO_VISIBILITY] = px_config[:custom_logo] ? PxModule::VISIBLE : PxModule::HIDDEN
|
27
33
|
|
28
34
|
return view.render.html_safe
|
29
35
|
end
|
30
36
|
end #end class
|
31
|
-
end #end module
|
37
|
+
end #end module
|
@@ -0,0 +1,133 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
6
|
+
<title>Access to this page has been denied.</title>
|
7
|
+
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300" rel="stylesheet">
|
8
|
+
<style>
|
9
|
+
html,body{
|
10
|
+
margin: 0;
|
11
|
+
padding: 0;
|
12
|
+
font-family: 'Open Sans', sans-serif;
|
13
|
+
color: #000;
|
14
|
+
}
|
15
|
+
|
16
|
+
a{
|
17
|
+
color: #c5c5c5;
|
18
|
+
text-decoration: none;
|
19
|
+
}
|
20
|
+
|
21
|
+
.container{
|
22
|
+
align-items: center;
|
23
|
+
display: flex;
|
24
|
+
flex: 1;
|
25
|
+
justify-content: space-between;
|
26
|
+
flex-direction: column;
|
27
|
+
height: 100%;
|
28
|
+
}
|
29
|
+
|
30
|
+
.container > div {
|
31
|
+
width: 100%;
|
32
|
+
display: flex;
|
33
|
+
justify-content:center;
|
34
|
+
}
|
35
|
+
|
36
|
+
.container > div > div {
|
37
|
+
display: flex;
|
38
|
+
width: 80%;
|
39
|
+
}
|
40
|
+
|
41
|
+
.customer-logo-wrapper{
|
42
|
+
padding-top: 2rem;
|
43
|
+
flex-grow: 0;
|
44
|
+
background-color: #fff;
|
45
|
+
visibility: {{logoVisibility}};
|
46
|
+
}
|
47
|
+
|
48
|
+
.customer-logo{
|
49
|
+
border-bottom: 1px solid #000;
|
50
|
+
}
|
51
|
+
|
52
|
+
.customer-logo > img{
|
53
|
+
padding-bottom: 1rem;
|
54
|
+
max-height: 50px;
|
55
|
+
max-width: auto;
|
56
|
+
}
|
57
|
+
|
58
|
+
.page-title-wrapper{
|
59
|
+
flex-grow: 2;
|
60
|
+
}
|
61
|
+
.page-title {
|
62
|
+
flex-direction: column-reverse;
|
63
|
+
}
|
64
|
+
|
65
|
+
.content-wrapper{
|
66
|
+
flex-grow: 5;
|
67
|
+
}
|
68
|
+
.content{
|
69
|
+
flex-direction: column;
|
70
|
+
}
|
71
|
+
|
72
|
+
.page-footer-wrapper{
|
73
|
+
align-items: center;
|
74
|
+
flex-grow: 0.2;
|
75
|
+
background-color: #000;
|
76
|
+
color: #c5c5c5;
|
77
|
+
font-size: 70%;
|
78
|
+
}
|
79
|
+
@media (min-width:768px){
|
80
|
+
html,body{
|
81
|
+
height: 100%;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
</style>
|
85
|
+
<!-- Custom CSS -->
|
86
|
+
{{# cssRef }}
|
87
|
+
<link rel="stylesheet" type="text/css" href="{{cssRef}}" />
|
88
|
+
{{/ cssRef }}
|
89
|
+
</head>
|
90
|
+
<body>
|
91
|
+
<section class="container">
|
92
|
+
<div class="customer-logo-wrapper">
|
93
|
+
<div class="customer-logo">
|
94
|
+
<img src="{{customLogo}}" alt="Logo"/>
|
95
|
+
</div>
|
96
|
+
</div>
|
97
|
+
<div class="page-title-wrapper">
|
98
|
+
<div class="page-title">
|
99
|
+
<h1>Access to this page has been denied.</h1>
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
<div class="content-wrapper">
|
103
|
+
<div class="content">
|
104
|
+
<p>
|
105
|
+
You have been blocked because we believe you are using automation tools to browse the website.
|
106
|
+
</p>
|
107
|
+
<p>
|
108
|
+
Please note that Javascript and Cookies must be enabled on your browser to access the website.
|
109
|
+
</p>
|
110
|
+
<p>
|
111
|
+
If you think you have been blocked by mistake, please contact the website administrator with the reference ID below.
|
112
|
+
</p>
|
113
|
+
<p>
|
114
|
+
Reference ID: #{{refId}}
|
115
|
+
</p>
|
116
|
+
</div>
|
117
|
+
</div>
|
118
|
+
<div class="page-footer-wrapper">
|
119
|
+
<div class="page-footer">
|
120
|
+
<p>
|
121
|
+
Powered by
|
122
|
+
<a href="https://www.perimeterx.com">PerimeterX</a>
|
123
|
+
, Inc.
|
124
|
+
</p>
|
125
|
+
</div>
|
126
|
+
</div>
|
127
|
+
</section>
|
128
|
+
<!-- Custom Script -->
|
129
|
+
{{# jsRef }}
|
130
|
+
<script src="{{jsRef}}"></script>
|
131
|
+
{{/ jsRef }}
|
132
|
+
</body>
|
133
|
+
</html>
|
@@ -0,0 +1,196 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
6
|
+
<title>Access to this page has been denied.</title>
|
7
|
+
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300" rel="stylesheet">
|
8
|
+
<style>
|
9
|
+
html,body{
|
10
|
+
margin: 0;
|
11
|
+
padding: 0;
|
12
|
+
font-family: 'Open Sans', sans-serif;
|
13
|
+
color: #000;
|
14
|
+
}
|
15
|
+
|
16
|
+
a{
|
17
|
+
color: #c5c5c5;
|
18
|
+
text-decoration: none;
|
19
|
+
}
|
20
|
+
|
21
|
+
.container{
|
22
|
+
align-items: center;
|
23
|
+
display: flex;
|
24
|
+
flex: 1;
|
25
|
+
justify-content: space-between;
|
26
|
+
flex-direction: column;
|
27
|
+
height: 100%;
|
28
|
+
}
|
29
|
+
|
30
|
+
.container > div {
|
31
|
+
width: 100%;
|
32
|
+
display: flex;
|
33
|
+
justify-content:center;
|
34
|
+
}
|
35
|
+
|
36
|
+
.container > div > div {
|
37
|
+
display: flex;
|
38
|
+
width: 80%;
|
39
|
+
}
|
40
|
+
|
41
|
+
.customer-logo-wrapper{
|
42
|
+
padding-top: 2rem;
|
43
|
+
flex-grow: 0;
|
44
|
+
background-color: #fff;
|
45
|
+
visibility: {{logoVisibility}};
|
46
|
+
}
|
47
|
+
|
48
|
+
.customer-logo{
|
49
|
+
border-bottom: 1px solid #000;
|
50
|
+
}
|
51
|
+
|
52
|
+
.customer-logo > img{
|
53
|
+
padding-bottom: 1rem;
|
54
|
+
max-height: 50px;
|
55
|
+
max-width: auto;
|
56
|
+
}
|
57
|
+
|
58
|
+
.page-title-wrapper{
|
59
|
+
flex-grow: 2;
|
60
|
+
}
|
61
|
+
.page-title {
|
62
|
+
flex-direction: column-reverse;
|
63
|
+
}
|
64
|
+
|
65
|
+
.content-wrapper{
|
66
|
+
flex-grow: 5;
|
67
|
+
}
|
68
|
+
.content{
|
69
|
+
flex-direction: column;
|
70
|
+
}
|
71
|
+
|
72
|
+
.page-footer-wrapper{
|
73
|
+
align-items: center;
|
74
|
+
flex-grow: 0.2;
|
75
|
+
background-color: #000;
|
76
|
+
color: #c5c5c5;
|
77
|
+
font-size: 70%;
|
78
|
+
}
|
79
|
+
|
80
|
+
@media (min-width:768px){
|
81
|
+
html,body{
|
82
|
+
height: 100%;
|
83
|
+
}
|
84
|
+
}
|
85
|
+
</style>
|
86
|
+
<!-- Custom CSS -->
|
87
|
+
{{#cssRef}}
|
88
|
+
<link rel="stylesheet" type="text/css" href="{{cssRef}}" />
|
89
|
+
{{/cssRef}}
|
90
|
+
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
|
91
|
+
</head>
|
92
|
+
|
93
|
+
<body>
|
94
|
+
<section class="container">
|
95
|
+
<div class="customer-logo-wrapper">
|
96
|
+
<div class="customer-logo">
|
97
|
+
<img src="{{customLogo}}" alt="Logo"/>
|
98
|
+
</div>
|
99
|
+
</div>
|
100
|
+
<div class="page-title-wrapper">
|
101
|
+
<div class="page-title">
|
102
|
+
<h1>Please verify you are a human</h1>
|
103
|
+
</div>
|
104
|
+
</div>
|
105
|
+
<div class="content-wrapper">
|
106
|
+
<div class="content">
|
107
|
+
<p>
|
108
|
+
Please click "I am not a robot" to continue
|
109
|
+
</p>
|
110
|
+
<div class="g-recaptcha" data-sitekey="6Lcj-R8TAAAAABs3FrRPuQhLMbp5QrHsHufzLf7b" data-callback="handleCaptcha" data-theme="dark">
|
111
|
+
</div>
|
112
|
+
<p>
|
113
|
+
Access to this page has been denied because we believe you are using automation tools to browse the website.
|
114
|
+
</p>
|
115
|
+
<p>
|
116
|
+
This may happen as a result of the following:
|
117
|
+
</p>
|
118
|
+
<ul>
|
119
|
+
<li>
|
120
|
+
Javascript is disabled or blocked by an extension (ad blockers for example)
|
121
|
+
</li>
|
122
|
+
<li>
|
123
|
+
Your browser does not support cookies
|
124
|
+
</li>
|
125
|
+
</ul>
|
126
|
+
<p>
|
127
|
+
Please make sure that Javascript and cookies are enabled on your browser and that you are not blocking them from loading.
|
128
|
+
</p>
|
129
|
+
<p>
|
130
|
+
Reference ID: #{{refId}}
|
131
|
+
</p>
|
132
|
+
</div>
|
133
|
+
</div>
|
134
|
+
<div class="page-footer-wrapper">
|
135
|
+
<div class="page-footer">
|
136
|
+
<p>
|
137
|
+
Powered by
|
138
|
+
<a href="https://www.perimeterx.com">PerimeterX</a>
|
139
|
+
, Inc.
|
140
|
+
</p>
|
141
|
+
</div>
|
142
|
+
</div>
|
143
|
+
</section>
|
144
|
+
<!-- Captcha -->
|
145
|
+
<script>
|
146
|
+
function captchaSolved(res) {
|
147
|
+
window.location.href = '/px/captcha_callback?status=' + res.status;
|
148
|
+
}
|
149
|
+
|
150
|
+
function handleCaptcha(response) {
|
151
|
+
var appId = '{{appId}}';
|
152
|
+
var vid = '{{vid}}';
|
153
|
+
var uuid = '{{uuid}}';
|
154
|
+
var collectorUrl = '{{{hostUrl}}}';
|
155
|
+
var req = new XMLHttpRequest();
|
156
|
+
req.open('POST', collectorUrl + '/api/v1/collector/captcha');
|
157
|
+
req.setRequestHeader('Content-Type', 'application/json');
|
158
|
+
req.addEventListener('error', function() {
|
159
|
+
captchaSolved({
|
160
|
+
status: 1
|
161
|
+
});
|
162
|
+
});
|
163
|
+
req.addEventListener('cancel', function() {
|
164
|
+
captchaSolved({
|
165
|
+
status: 2
|
166
|
+
});
|
167
|
+
});
|
168
|
+
req.addEventListener('load', function() {
|
169
|
+
if (req.status == 200) {
|
170
|
+
try {
|
171
|
+
var responseJSON = JSON.parse(req.responseText);
|
172
|
+
return captchaSolved(responseJSON);
|
173
|
+
} catch (ex) {}
|
174
|
+
}
|
175
|
+
captchaSolved({
|
176
|
+
status: 3
|
177
|
+
});
|
178
|
+
});
|
179
|
+
req.send(JSON.stringify({
|
180
|
+
appId: appId,
|
181
|
+
uuid: uuid,
|
182
|
+
vid: vid,
|
183
|
+
pxCaptcha: response,
|
184
|
+
hostname: window.location.hostname,
|
185
|
+
request: {
|
186
|
+
url: window.location.href
|
187
|
+
}
|
188
|
+
}));
|
189
|
+
}
|
190
|
+
</script>
|
191
|
+
<!-- Custom Script -->
|
192
|
+
{{#jsRef}}
|
193
|
+
<script src="{{jsRef}}"></script>
|
194
|
+
{{/jsRef}}
|
195
|
+
</body>
|
196
|
+
</html>
|
data/lib/perimeterx/version.rb
CHANGED
data/readme.md
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perimeter_x
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nitzan Goldfeder
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -156,6 +156,7 @@ extra_rdoc_files:
|
|
156
156
|
- changelog.md
|
157
157
|
files:
|
158
158
|
- ".gitignore"
|
159
|
+
- ".travis.yml"
|
159
160
|
- Dockerfile
|
160
161
|
- Gemfile
|
161
162
|
- Gemfile.lock
|
@@ -171,10 +172,12 @@ files:
|
|
171
172
|
- lib/perimeterx/internal/clients/perimeter_x_activity_client.rb
|
172
173
|
- lib/perimeterx/internal/clients/perimeter_x_risk_client.rb
|
173
174
|
- lib/perimeterx/internal/exceptions/px_cookie_decryption_exception.rb
|
175
|
+
- lib/perimeterx/internal/payload/perimeter_x_cookie_v1.rb
|
176
|
+
- lib/perimeterx/internal/payload/perimeter_x_cookie_v3.rb
|
177
|
+
- lib/perimeterx/internal/payload/perimeter_x_payload.rb
|
178
|
+
- lib/perimeterx/internal/payload/perimeter_x_token_v1.rb
|
179
|
+
- lib/perimeterx/internal/payload/perimeter_x_token_v3.rb
|
174
180
|
- lib/perimeterx/internal/perimeter_x_context.rb
|
175
|
-
- lib/perimeterx/internal/perimeter_x_cookie.rb
|
176
|
-
- lib/perimeterx/internal/perimeter_x_cookie_v1.rb
|
177
|
-
- lib/perimeterx/internal/perimeter_x_cookie_v3.rb
|
178
181
|
- lib/perimeterx/internal/validators/perimeter_x_captcha_validator.rb
|
179
182
|
- lib/perimeterx/internal/validators/perimeter_x_cookie_validator.rb
|
180
183
|
- lib/perimeterx/internal/validators/perimeter_x_s2s_validator.rb
|
@@ -182,7 +185,9 @@ files:
|
|
182
185
|
- lib/perimeterx/utils/px_http_client.rb
|
183
186
|
- lib/perimeterx/utils/px_logger.rb
|
184
187
|
- lib/perimeterx/utils/px_template_factory.rb
|
188
|
+
- lib/perimeterx/utils/templates/block.mobile.mustache
|
185
189
|
- lib/perimeterx/utils/templates/block.mustache
|
190
|
+
- lib/perimeterx/utils/templates/captcha.mobile.mustache
|
186
191
|
- lib/perimeterx/utils/templates/captcha.mustache
|
187
192
|
- lib/perimeterx/version.rb
|
188
193
|
- perimeter_x.gemspec
|