userbin 0.4.5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +87 -111
- data/lib/userbin.rb +18 -39
- data/lib/userbin/configuration.rb +14 -16
- data/lib/userbin/errors.rb +5 -0
- data/lib/userbin/helpers.rb +83 -0
- data/lib/userbin/jwt.rb +40 -0
- data/lib/userbin/models/base.rb +24 -0
- data/lib/userbin/models/challenge.rb +4 -0
- data/lib/userbin/models/session.rb +11 -0
- data/lib/userbin/models/user.rb +9 -0
- data/lib/userbin/request.rb +99 -0
- data/lib/userbin/utils.rb +28 -0
- data/lib/userbin/version.rb +1 -1
- data/spec/configuration_spec.rb +8 -0
- data/spec/fixtures/vcr_cassettes/session_create.yml +47 -0
- data/spec/fixtures/vcr_cassettes/session_refresh.yml +47 -0
- data/spec/fixtures/vcr_cassettes/session_verify.yml +47 -0
- data/spec/fixtures/vcr_cassettes/user_find.yml +44 -0
- data/spec/fixtures/vcr_cassettes/user_find_non_existing.yml +42 -0
- data/spec/fixtures/vcr_cassettes/user_import.yml +46 -0
- data/spec/fixtures/vcr_cassettes/user_update.yml +47 -0
- data/spec/helpers_spec.rb +38 -0
- data/spec/jwt_spec.rb +67 -0
- data/spec/models/session_spec.rb +33 -0
- data/spec/models/user_spec.rb +43 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/utils_spec.rb +36 -0
- metadata +128 -36
- data/lib/userbin/authentication.rb +0 -132
- data/lib/userbin/basic_auth.rb +0 -31
- data/lib/userbin/current.rb +0 -17
- data/lib/userbin/events.rb +0 -40
- data/lib/userbin/rails/auth_helpers.rb +0 -22
- data/lib/userbin/railtie.rb +0 -14
- data/lib/userbin/session.rb +0 -26
- data/lib/userbin/userbin.rb +0 -104
- data/spec/session_spec.rb +0 -40
- data/spec/userbin_spec.rb +0 -102
@@ -1,132 +0,0 @@
|
|
1
|
-
module Userbin
|
2
|
-
class Authentication
|
3
|
-
|
4
|
-
CLOSING_BODY_TAG = %r{</body>}
|
5
|
-
|
6
|
-
def initialize(app, options = {})
|
7
|
-
@app = app
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(env)
|
11
|
-
if !Userbin.config.app_id || !Userbin.config.api_secret
|
12
|
-
raise ConfigurationError, "app_id and api_secret must be present"
|
13
|
-
end
|
14
|
-
|
15
|
-
Thread.current[:userbin] = nil
|
16
|
-
env['userbin.unauthenticated'] = false
|
17
|
-
|
18
|
-
request = Rack::Request.new(env)
|
19
|
-
|
20
|
-
begin
|
21
|
-
jwt = Userbin.authenticate!(request)
|
22
|
-
|
23
|
-
if !Userbin.authenticated? && Userbin.config.protected_path &&
|
24
|
-
env["PATH_INFO"].start_with?(Userbin.config.protected_path)
|
25
|
-
|
26
|
-
return render_gateway(env["PATH_INFO"])
|
27
|
-
end
|
28
|
-
|
29
|
-
generate_response(env, jwt)
|
30
|
-
rescue Userbin::SecurityError
|
31
|
-
message =
|
32
|
-
'Userbin::SecurityError: Invalid session. Refresh to try again.'
|
33
|
-
headers = {
|
34
|
-
'Content-Type' => 'text/text'
|
35
|
-
}
|
36
|
-
|
37
|
-
Rack::Utils.delete_cookie_header!(
|
38
|
-
headers, '_ubt', value = {})
|
39
|
-
|
40
|
-
[ 400, headers, [message] ]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def script_tag(login_path)
|
45
|
-
script_url = ENV.fetch('USERBIN_SCRIPT_URL') {
|
46
|
-
"//js.userbin.com"
|
47
|
-
}
|
48
|
-
path = login_path || Userbin.config.protected_path
|
49
|
-
|
50
|
-
tag = "<script src='#{script_url}?#{Userbin.config.app_id}'></script>\n"
|
51
|
-
tag += "<script type='text/javascript'>\n"
|
52
|
-
tag += " Userbin.config({\n"
|
53
|
-
if Userbin.config.root_path
|
54
|
-
tag += " logoutRedirectUrl: '#{Userbin.config.root_path}',\n"
|
55
|
-
end
|
56
|
-
tag += " loginRedirectUrl: '#{path}',\n" if path
|
57
|
-
tag += " reloadOnSuccess: true\n"
|
58
|
-
tag += " });\n"
|
59
|
-
tag += "</script>\n"
|
60
|
-
end
|
61
|
-
|
62
|
-
def inject_tags(body, login_path = nil)
|
63
|
-
if body[CLOSING_BODY_TAG]
|
64
|
-
body = body.gsub(CLOSING_BODY_TAG, script_tag(login_path) + '\\0')
|
65
|
-
end
|
66
|
-
body
|
67
|
-
end
|
68
|
-
|
69
|
-
def render_gateway(current_path)
|
70
|
-
script_url = ENV["USERBIN_SCRIPT_URL"] || '//js.userbin.com'
|
71
|
-
|
72
|
-
login_page = <<-LOGIN_PAGE
|
73
|
-
<!DOCTYPE html>
|
74
|
-
<html>
|
75
|
-
<head>
|
76
|
-
<meta charset="utf-8">
|
77
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
78
|
-
<title>Log in</title>
|
79
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
80
|
-
</head>
|
81
|
-
<body>
|
82
|
-
<a class="ub-login-form"></a>
|
83
|
-
</body>
|
84
|
-
</html>
|
85
|
-
LOGIN_PAGE
|
86
|
-
|
87
|
-
login_page = inject_tags(login_page, current_path)
|
88
|
-
|
89
|
-
headers = { 'Content-Type' => 'text/html' }
|
90
|
-
|
91
|
-
[403, headers, [login_page]]
|
92
|
-
end
|
93
|
-
|
94
|
-
def generate_response(env, jwt)
|
95
|
-
status, headers, response = @app.call(env)
|
96
|
-
|
97
|
-
# application stack is responsible for setting userbin.authenticated
|
98
|
-
return render_gateway(env["PATH_INFO"]) if env['userbin.unauthenticated']
|
99
|
-
|
100
|
-
if headers['Content-Type'] && headers['Content-Type']['text/html']
|
101
|
-
if response.respond_to?(:body)
|
102
|
-
body = [*response.body]
|
103
|
-
else
|
104
|
-
body = response
|
105
|
-
end
|
106
|
-
if !Userbin.config.skip_script_injection
|
107
|
-
body = body.each.map do |chunk|
|
108
|
-
inject_tags(chunk)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
if response.respond_to?(:body)
|
112
|
-
response.body = body
|
113
|
-
else
|
114
|
-
response = body
|
115
|
-
end
|
116
|
-
unless body.empty?
|
117
|
-
headers['Content-Length'] = Rack::Utils.bytesize(body.flatten[0]).to_s
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
if jwt
|
122
|
-
Rack::Utils.set_cookie_header!(
|
123
|
-
headers, '_ubt', value: jwt, path: '/')
|
124
|
-
else
|
125
|
-
Rack::Utils.delete_cookie_header!(
|
126
|
-
headers, '_ubt', value = {})
|
127
|
-
end
|
128
|
-
|
129
|
-
[status, headers, response]
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
data/lib/userbin/basic_auth.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
module Userbin
|
2
|
-
class BasicAuth < Faraday::Middleware
|
3
|
-
def call(env)
|
4
|
-
value = Base64.encode64([Userbin.config.app_id, Userbin.config.api_secret].join(':'))
|
5
|
-
value.gsub!("\n", '')
|
6
|
-
env[:request_headers]["Authorization"] = "Basic #{value}"
|
7
|
-
@app.call(env)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
class VerifySignature < Faraday::Response::Middleware
|
12
|
-
def call(env)
|
13
|
-
@app.call(env).on_complete do
|
14
|
-
Userbin.decode_jwt(env[:body])
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class ParseSignedJSON < Faraday::Response::Middleware
|
20
|
-
def on_complete(env)
|
21
|
-
json = MultiJson.load(env[:body], symbolize_keys: true)
|
22
|
-
signature = env[:response_headers]['x-userbin-signature']
|
23
|
-
json[:signature] = signature if signature
|
24
|
-
env[:body] = {
|
25
|
-
data: json,
|
26
|
-
errors: [],
|
27
|
-
metadata: {}
|
28
|
-
}
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/userbin/current.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
module Userbin
|
2
|
-
class Current
|
3
|
-
attr_accessor :token, :expires_at, :user
|
4
|
-
|
5
|
-
def initialize(data)
|
6
|
-
if data
|
7
|
-
@token = data['id']
|
8
|
-
@expires_at = data['expires_at']
|
9
|
-
@user = Userbin::User.new(data['user'])
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def authenticated?
|
14
|
-
!@user.nil?
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
data/lib/userbin/events.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
module Userbin
|
2
|
-
|
3
|
-
Callback = Struct.new(:pattern, :block) do; end
|
4
|
-
|
5
|
-
class Events
|
6
|
-
def self.on(*names, &block)
|
7
|
-
pattern = Regexp.union(names.empty? ? TYPE_LIST.to_a : names)
|
8
|
-
callbacks.each do |callback|
|
9
|
-
if pattern == callback.pattern
|
10
|
-
callbacks.delete(callback)
|
11
|
-
callbacks << Userbin::Callback.new(pattern, block)
|
12
|
-
return
|
13
|
-
end
|
14
|
-
end
|
15
|
-
callbacks << Userbin::Callback.new(pattern, block)
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.trigger(raw_event)
|
19
|
-
event = Userbin::Event.new(raw_event)
|
20
|
-
callbacks.each do |callback|
|
21
|
-
if event.type =~ callback.pattern
|
22
|
-
object = case event['type']
|
23
|
-
when /^user\./
|
24
|
-
Userbin::User.new(event.object)
|
25
|
-
else
|
26
|
-
event.object
|
27
|
-
end
|
28
|
-
model = event.instance_exec object, &callback.block
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def self.callbacks
|
36
|
-
@callbacks ||= []
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Userbin
|
2
|
-
module AuthHelpers
|
3
|
-
def authenticate_user!
|
4
|
-
unless user_logged_in?
|
5
|
-
env['userbin.unauthenticated'] = true
|
6
|
-
render nothing: true
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def current_user
|
11
|
-
Userbin.current_user
|
12
|
-
end
|
13
|
-
|
14
|
-
def user_logged_in?
|
15
|
-
Userbin.user_logged_in?
|
16
|
-
end
|
17
|
-
|
18
|
-
def user_signed_in?
|
19
|
-
Userbin.user_signed_in?
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/userbin/railtie.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'userbin/rails/auth_helpers'
|
2
|
-
|
3
|
-
module Userbin
|
4
|
-
ActiveSupport.on_load(:action_controller) do
|
5
|
-
include AuthHelpers
|
6
|
-
end
|
7
|
-
|
8
|
-
class Railtie < Rails::Railtie
|
9
|
-
initializer "userbin" do |app|
|
10
|
-
ActionView::Base.send :include, AuthHelpers
|
11
|
-
app.config.middleware.use "Userbin::Authentication"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/lib/userbin/session.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'her'
|
2
|
-
|
3
|
-
module Userbin
|
4
|
-
class Model
|
5
|
-
include Her::Model
|
6
|
-
end
|
7
|
-
|
8
|
-
class User < Model; end
|
9
|
-
|
10
|
-
class Session < Model
|
11
|
-
has_one :user
|
12
|
-
|
13
|
-
# Hack to avoid loading a remote user
|
14
|
-
def user
|
15
|
-
return self['user'] if self['user'].is_a?(User)
|
16
|
-
User.new(self['user']) if self['user']
|
17
|
-
end
|
18
|
-
|
19
|
-
def authenticated?
|
20
|
-
!user.id.nil? rescue false
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
class Event < Model
|
25
|
-
end
|
26
|
-
end
|
data/lib/userbin/userbin.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
require 'jwt'
|
2
|
-
|
3
|
-
module Userbin
|
4
|
-
def self.decode_jwt(jwt)
|
5
|
-
JWT.decode(jwt, Userbin.config.api_secret)
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.authenticate!(request)
|
9
|
-
jwt = request.cookies['_ubt']
|
10
|
-
return unless jwt
|
11
|
-
|
12
|
-
decoded = Userbin.decode_jwt(jwt)
|
13
|
-
|
14
|
-
if Time.now > Time.at(decoded['expires_at'] / 1000)
|
15
|
-
jwt = refresh_session(decoded['id'])
|
16
|
-
return unless jwt
|
17
|
-
|
18
|
-
decoded = Userbin.decode_jwt(jwt)
|
19
|
-
|
20
|
-
if Time.now > Time.at(decoded['expires_at'] / 1000)
|
21
|
-
raise Userbin::SecurityError
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
self.current = Userbin::Session.new(decoded)
|
26
|
-
|
27
|
-
return jwt
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.refresh_session(session_id)
|
31
|
-
api_endpoint = ENV["USERBIN_API_ENDPOINT"] || 'https://api.userbin.com'
|
32
|
-
uri = URI("#{api_endpoint}/sessions/#{session_id}/refresh.jwt")
|
33
|
-
uri.user = config.app_id
|
34
|
-
uri.password = config.api_secret
|
35
|
-
net = Net::HTTP.post_form(uri, {})
|
36
|
-
net.body
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.current
|
40
|
-
Thread.current[:userbin]
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.current=(value)
|
44
|
-
Thread.current[:userbin] = value
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.authenticated?
|
48
|
-
current.authenticated? rescue false
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.logged_in?
|
52
|
-
authenticated?
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.user_logged_in?
|
56
|
-
authenticated?
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.user_signed_in?
|
60
|
-
authenticated?
|
61
|
-
end
|
62
|
-
|
63
|
-
def self._current_user
|
64
|
-
current.user if current
|
65
|
-
end
|
66
|
-
|
67
|
-
def self.current_profile
|
68
|
-
_current_user
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.current_user
|
72
|
-
if _current_user
|
73
|
-
if Userbin.config.find_user
|
74
|
-
u = Userbin.config.find_user.call(_current_user.id)
|
75
|
-
if u
|
76
|
-
u
|
77
|
-
else
|
78
|
-
if Userbin.config.create_user
|
79
|
-
|
80
|
-
# Fetch a full profile from the API. This way we can get more
|
81
|
-
# sensitive details than those stored in the cookie. It also checks
|
82
|
-
# that the user still exists in Userbin.
|
83
|
-
profile = User.find(_current_user.id)
|
84
|
-
|
85
|
-
u = Userbin.config.create_user.call(profile)
|
86
|
-
if u
|
87
|
-
u
|
88
|
-
else
|
89
|
-
_current_user
|
90
|
-
end
|
91
|
-
else
|
92
|
-
raise ConfigurationError, "You need to implement create_user"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
else
|
96
|
-
_current_user
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.user
|
102
|
-
current_user
|
103
|
-
end
|
104
|
-
end
|
data/spec/session_spec.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'multi_json'
|
3
|
-
|
4
|
-
describe 'Userbin::Session' do
|
5
|
-
before do
|
6
|
-
Userbin.configure do |config|
|
7
|
-
config.app_id = '100000000000000'
|
8
|
-
config.api_secret = 'test'
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
before do
|
13
|
-
data = {
|
14
|
-
id: "Prars5v7xz2xwWvF5LEqfEUHCoNNsV7V",
|
15
|
-
created_at: 1378978281000,
|
16
|
-
expires_at: 1378981881000,
|
17
|
-
user: {
|
18
|
-
confirmed_at: nil,
|
19
|
-
created_at: 1378978280000,
|
20
|
-
email: "johan@userbin.com",
|
21
|
-
id: "TF15JEy7HRxDYx6U435zzEwydKJcptUr",
|
22
|
-
last_sign_in_at: nil,
|
23
|
-
local_id: nil
|
24
|
-
}
|
25
|
-
}
|
26
|
-
stub_request(:post, /\/users\/.*\/sessions/).to_return(
|
27
|
-
status: 200,
|
28
|
-
headers: {'X-Userbin-Signature' => 'abcd'},
|
29
|
-
body: MultiJson.encode(data)
|
30
|
-
)
|
31
|
-
end
|
32
|
-
|
33
|
-
xit 'creates a session' do
|
34
|
-
allow(OpenSSL::HMAC).to receive(:hexdigest) { 'abcd' }
|
35
|
-
user = Userbin::User.new(id: 'guid1')
|
36
|
-
session = user.sessions.create
|
37
|
-
session.user.email.should == 'johan@userbin.com'
|
38
|
-
session.signature.should == 'abcd'
|
39
|
-
end
|
40
|
-
end
|
data/spec/userbin_spec.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'cgi'
|
3
|
-
|
4
|
-
describe Userbin do
|
5
|
-
before do
|
6
|
-
Userbin.configure do |config|
|
7
|
-
config.app_id = '1000'
|
8
|
-
config.api_secret = '1234'
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
let (:args) do
|
13
|
-
{
|
14
|
-
"HTTP_COOKIE" => "_ubs=abcd; _ubd=#{CGI.escape(MultiJson.encode(session))} "
|
15
|
-
}
|
16
|
-
end
|
17
|
-
|
18
|
-
let (:session) do
|
19
|
-
{
|
20
|
-
"id" => 'xyz',
|
21
|
-
"expires_at" => 1478981881000,
|
22
|
-
"user" => {
|
23
|
-
"id" => 'abc'
|
24
|
-
}
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
let (:request) do
|
29
|
-
Rack::Request.new({
|
30
|
-
'HTTP_X_USERBIN_SIGNATURE' => 'abcd',
|
31
|
-
'CONTENT_TYPE' => 'application/json',
|
32
|
-
'rack.input' => StringIO.new()
|
33
|
-
}.merge(args))
|
34
|
-
end
|
35
|
-
|
36
|
-
let (:response) do
|
37
|
-
Rack::Response.new("", 200, {})
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'when session is created' do
|
41
|
-
|
42
|
-
it 'authenticates with class methods' do
|
43
|
-
allow(OpenSSL::HMAC).to receive(:hexdigest) { 'abcd' }
|
44
|
-
Userbin.authenticate!(request)
|
45
|
-
Userbin.should be_authenticated
|
46
|
-
Userbin.current_user.id.should == "abc"
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'renews' do
|
50
|
-
stub_request(:post, /.*userbin\.com.*/).to_return(:status => 200, :body => "{\"id\":\"Prars5v7xz2xwWvF5LEqfEUHCoNNsV7V\",\"created_at\":1378978281000,\"expires_at\":1378981881000,\"user\":{\"confirmed_at\":null,\"created_at\":1378978280000,\"email\":\"admin@getapp6133.com\",\"id\":\"TF15JEy7HRxDYx6U435zzEwydKJcptUr\",\"last_sign_in_at\":null,\"local_id\":null}}", :headers => {'X-Userbin-Signature' => 'abcd'})
|
51
|
-
allow(OpenSSL::HMAC).to receive(:hexdigest) { 'abcd' }
|
52
|
-
Userbin.authenticate!(request, Time.at(1478981882)) # expired 1s
|
53
|
-
Userbin.current.id.should == 'Prars5v7xz2xwWvF5LEqfEUHCoNNsV7V'
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'does not renew' do
|
57
|
-
stub_request(:post, /.*userbin\.com.*/).to_return(:status => 404)
|
58
|
-
allow(OpenSSL::HMAC).to receive(:hexdigest) { 'abcd' }
|
59
|
-
Userbin.authenticate!(request, Time.at(1478981882)) # expired 1s
|
60
|
-
end
|
61
|
-
|
62
|
-
xit 'authenticate with correct signature' do
|
63
|
-
expect {
|
64
|
-
Userbin.authenticate!(request)
|
65
|
-
}.to raise_error { Userbin::SecurityError }
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'does not authenticate incorrect signature' do
|
69
|
-
expect {
|
70
|
-
Userbin.authenticate!(request)
|
71
|
-
}.to raise_error { Userbin::SecurityError }
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
context 'when session is deleted' do
|
76
|
-
let (:args) do
|
77
|
-
{
|
78
|
-
"HTTP_COOKIE" => "userbin_signature=abcd;"
|
79
|
-
}
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'does not authenticate' do
|
83
|
-
allow(OpenSSL::HMAC).to receive(:hexdigest) { 'abcd' }
|
84
|
-
Userbin.authenticate!(request)
|
85
|
-
Userbin.should_not be_authenticated
|
86
|
-
Userbin.user.should be_nil
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
context 'when params are present' do
|
91
|
-
let (:args) do
|
92
|
-
{
|
93
|
-
"QUERY_STRING" => "userbin_signature=abcd&userbin_data=#{MultiJson.encode(session)}"
|
94
|
-
}
|
95
|
-
end
|
96
|
-
|
97
|
-
xit 'authenticates with class methods' do
|
98
|
-
allow(OpenSSL::HMAC).to receive(:hexdigest) { 'abcd' }
|
99
|
-
Userbin.authenticate_events!(request)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|