userbin 1.6.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9c4187739931daad2ab4737e663b9d048ab3728d
4
- data.tar.gz: 0e22aae813008c87dce6625c8735ca819358cb1f
3
+ metadata.gz: 8a4569c81702c9644066b6bdaa74246a068632ba
4
+ data.tar.gz: 17a9fd3f2c51969565ca485adf025601e74b4029
5
5
  SHA512:
6
- metadata.gz: 3938f98100098d8b5b8f0048addfbbc89fc8204e4e68c83c57f8546565e63dfb84bf67cd2bd3f9cfa039d14d0adf5b809c66bcc7e5609025a441bd8172f9dccc
7
- data.tar.gz: 046433d4a20b1a5c18fe719d4ada56b4d46dce15a0bcbc8610f22c6292e46f656141b4e1cab99876f7f9257b5b1405289beace703a3e0cf66a16ae43dea661cf
6
+ metadata.gz: 79a9d2ac54fd2dafed09ca930e769f48b01d8b1b8896cde859f7ea98c2fa599b77529018409dac5ab41b902da43882878d43df8160079d324c4ffe78206b3b5b
7
+ data.tar.gz: b7024885c8ee6fca6566550b763ca2f81f7684fbda42bce710c90bf1e27378ade15597ab93a0b4db6b2384a3be06811f0b7e0bd166b1a526b2af0f4f08623d7e
data/README.md CHANGED
@@ -5,286 +5,47 @@
5
5
  [![Dependency Status](https://gemnasium.com/userbin/userbin-ruby.png)](https://gemnasium.com/userbin/userbin-ruby)
6
6
  [![Coverage Status](https://coveralls.io/repos/userbin/userbin-ruby/badge.png)](https://coveralls.io/r/userbin/userbin-ruby)
7
7
 
8
- **[Userbin](https://userbin.com) adds an additional security layer to your application by providing account takeover protection and two-factor authentication in a white-label package**
9
-
10
- Your users **do not** need to be signed up or registered for Userbin before using the service and there's no need for them to download any proprietary apps. Also, Userbin requires **no modification of your current database schema** as it uses your local user IDs.
11
-
12
- ## Table of Contents
13
-
14
- - [Installation](#installation)
15
- - [Getting Started](#getting-started)
16
- - [Active Sessions](#active-sessions)
17
- - [Security Events](#security-events)
18
- - [Two-factor Authentication](#two-factor-authentication)
19
- - [Pairing with Google Authenticator](#pairing-with-google-authenticator)
20
- - [Pairing with Phone Number (SMS)](#pairing-with-phone-number-sms)
21
- - [Pairing with YubiKey](#pairing-with-yubikey)
22
- - [Enabling and Disabling](#enabling-and-disabling)
23
- - [Authenticating](#authenticating)
24
- - [Backup Codes](#backup-codes)
25
- - [List Pairings](#list-pairings)
8
+ **[Userbin](https://userbin.com) adds real-time monitoring of your authentication stack, instantly notifying you and your users on potential account hijacks.**
26
9
 
27
10
  ## Installation
28
11
 
29
12
  Add the `userbin` gem to your `Gemfile`
30
13
 
31
14
  ```ruby
32
- gem "userbin"
15
+ gem 'userbin'
33
16
  ```
34
17
 
35
18
  Load and configure the library with your Userbin API secret in an initializer or similar.
36
19
 
37
20
  ```ruby
38
- Userbin.api_secret = "YOUR_API_SECRET"
21
+ Userbin.api_secret = 'YOUR_API_SECRET'
39
22
  ```
40
23
 
41
- ## Getting started
42
-
43
- ### 1. Logging in and out
24
+ A Userbin client instance will automatically be made available as `userbin` in your Rails, Sinatra or Padrino controllers.
44
25
 
45
- You should call `login` as soon as the user has logged in to your application to start the Userbin session. Pass a unique user identifier, and an *optional* hash of user properties which are used when searching for users in your dashboard.
26
+ ## Tracking security events
46
27
 
47
- ```ruby
48
- def your_after_login_hook
49
- userbin.login(current_user.id, email: current_user.email)
50
- end
51
- ```
28
+ `track` lets you record the security-related actions your users perform. The more actions you track, the more accurate Userbin is in identifying fraudsters.
52
29
 
53
- When a user logs out from within your application, call `logout` to tell Userbin to remove the session from the user's [active sessions](#active-sessions).
30
+ When you have access to a logged in user, send along the same user identifier as when you initiated Userbin.js.
54
31
 
55
32
  ```ruby
56
- def your_after_logout_hook
57
- userbin.logout
58
- end
33
+ userbin.track(
34
+ user_id: user.id,
35
+ name: 'login.succeeded')
59
36
  ```
60
37
 
61
- **Check that it works** by logging in to your application and watch your user appear in the [Userbin dashboard](https://dashboard.userbin.com).
62
-
63
- ### 2. Protecting routes
64
-
65
- Call `authorize!` just before your `current_user` is being initialized. Usually you'll want to override your normal authentication filter, e.g. `authenticate_user!` if you're using Devise.
66
-
67
- - `UserUnauthorizedError` will be raised if `login` has not yet been called, or if the session is no longer valid.
68
- - `ChallengeRequiredError` will be raised when the user has enabled two-factor authentication and is logging in from an untrusted device.
38
+ If you don't have access to a logged in user just omit `user_id`, typically when tracking failed logins.
69
39
 
70
40
  ```ruby
71
- class ApplicationController < ActionController::Base
72
- rescue_from Userbin::UserUnauthorizedError, with: :user_unauthorized
73
- rescue_from Userbin::ChallengeRequiredError, with: :challenge_required
74
-
75
- # IMPLEMENT: Override the authentication method from your framework
76
- def authenticate_user!
77
- userbin.authorize!
78
- super
79
- end
80
-
81
- # IMPLEMENT: Log out your user locally
82
- def user_unauthorized
83
- sign_out
84
- redirect_to root_path
85
- end
86
-
87
- # IMPLEMENT: Redirect to two-factor authentication login
88
- def challenge_required
89
- redirect_to show_challenge_path
90
- end
91
- end
41
+ userbin.track(name: 'login.failed')
92
42
  ```
93
43
 
94
- Then use the overridden filter in your protected routes as you normally would, and all your critical flows will be protected from account takeover.
95
-
96
- ```ruby
97
- class AccountController < ApplicationController
98
- before_filter :authenticate_user!
99
- end
100
- ```
101
-
102
- ## Active Sessions
103
-
104
- Show a list of sessions currently signed to a user's account.
105
-
106
- The *context* is from the last recorded [security event](#security-events) on a session.
107
-
108
- ```ruby
109
- userbin.sessions.each do |session|
110
- puts session.id # => 'yt9BkoHzcQoou4jqbQbJUqqMdxyxvCBr'
111
- puts session.context.ip # => '88.12.129.1'
112
- end
113
- ```
114
-
115
- Destroy a session to revoke access and trigger a `UserUnauthorizedError` the next time `authorize!` refreshes the session token, which is within 5 minutes.
116
-
117
- ```ruby
118
- userbin.sessions.destroy('yt9BkoHzcQoou4jqbQbJUqqMdxyxvCBr')
119
- ```
120
-
121
- ## Security Events
122
-
123
- List a user's recent account activity, which include security events such as user logins and failed two-factor attempts. See the [Event API](https://api.userbin.com/#events) for a list of all the available events.
124
-
125
- ```ruby
126
- userbin.events.each do |event|
127
- puts event.name # => 'session.created'
128
- puts event.context.ip # => '88.12.129.1'
129
- puts event.context.location.country # => 'Sweden'
130
- puts event.context.user_agent.browser # => 'Chrome'
131
- end
132
- ```
133
-
134
- ## Two-factor Authentication
135
-
136
- Using two-factor authentication involves two steps: **pairing** and **authenticating**.
137
-
138
- ### Pairing
139
-
140
- Before your users can protect their account with two-factor authentication, they will need to pair their their preferred way of authenticating. The [Pairing API](https://api.userbin.com/#pairings) lets users add, verify, and remove authentication channels. Only *verified* pairings are valid for authentication.
141
-
142
- #### Pairing with Google Authenticator
143
-
144
- The user visits a page to add Google Authenticator to their account. First create a new Authenticator pairing to generate a QR code image.
145
-
146
- ```ruby
147
- @authenticator = userbin.pairings.create(type: 'authenticator')
148
- ```
149
-
150
- Render a page containing the QR code, which the user scans with Google Authenticator.
151
-
152
- ```erb
153
- <img src="<%= @authenticator[:qr_url] %>">
154
- ```
155
-
156
- After scanning the QR code, the user will enter the 6 digit token that Google Authenticator displays, and submit the form. Capture the response and verify the pairing.
157
-
158
- ```ruby
159
- begin
160
- userbin.pairings.verify(params[:pairing_id], response: params[:code])
161
- rescue Userbin::InvalidParametersError
162
- flash.notice = 'Wrong code, try again'
163
- end
164
- ```
165
-
166
- #### Pairing with Phone Number (SMS)
167
-
168
- Create a new phone number pairing which will send out a verification SMS.
169
-
170
- ```ruby
171
- @phone_number = userbin.pairings.create(
172
- type: 'phone_number', number: '+1739855455')
173
- ```
174
-
175
- Catch the code from the user to pair the phone number.
176
-
177
- ```ruby
178
- begin
179
- userbin.pairings.verify(params[:pairing_id], response: params[:code])
180
- rescue Userbin::InvalidParametersError
181
- flash.notice = 'Wrong code, try again'
182
- end
183
- ```
184
-
185
- #### Pairing with YubiKey
186
-
187
- YubiKeys are immediately verified for two-factor authentication.
188
-
189
- ```ruby
190
- begin
191
- userbin.pairings.create(type: 'yubikey', otp: params[:code])
192
- rescue Userbin::InvalidParametersError
193
- flash.notice = 'Wrong code, try again'
194
- end
195
- ```
196
-
197
- #### Enabling and Disabling
198
-
199
- For the sake of flexibility, two-factor authentication isn't enabled automatically when you add your first pairing.
200
-
201
- ```ruby
202
- userbin.enable_mfa!
203
- userbin.disable_mfa!
204
- ```
205
-
206
- ### Authenticating
207
-
208
- If the user has enabled two-factor authentication, `authorize!` might raise `ChallengeRequiredError`, which means they'll have to verify a challenge to proceed.
209
-
210
- Capture this error just as with UserUnauthorizedError and redirect the user to a path **not protected** by `authorize!`.
211
-
212
- If the user tries to reach a path protected by `authorize!` after a challenge has been created but still not verified, the session will be destroyed and UserUnauthorizedError raised.
213
-
214
- ```ruby
215
- class ApplicationController < ActionController::Base
216
- rescue_from Userbin::ChallengeRequiredError do |exception|
217
- redirect_to show_challenge_path
218
- end
219
- # ...
220
- end
221
- ```
222
-
223
- Create a challenge, which will send the user and SMS if this is the default pairing. After the challenge has been verified, `authorize!` will not throw any further exceptions until any suspicious behavior is detected.
224
-
225
- When you call `trust_device`, the user will not be challenged for secondary authentication when they log in to your application from that device for a set period of time. You could add this to your form as a checkbox option.
226
-
227
- ```ruby
228
- class ChallengeController < ApplicationController
229
- def show
230
- @challenge = userbin.challenges.create
231
- end
232
-
233
- def verify
234
- challenge_id = params.require(:challenge_id)
235
- code = params.require(:code)
236
-
237
- userbin.challenges.verify(challenge_id, response: code)
238
-
239
- # Avoid verification on next login for better experience
240
- userbin.trust_device if params[:trust_device]
241
-
242
- # Yay, the challenge was verified!
243
- redirect_to root_url
244
-
245
- rescue Userbin::ForbiddenError => e
246
- sign_out # log out your user locally
247
-
248
- flash.notice = 'Wrong code, bye!'
249
- redirect_to root_path
250
- end
251
- end
252
- ```
253
-
254
- ### Backup Codes
255
-
256
- List or generate new backup codes used for when the user didn't bring their authentication device.
257
-
258
- ```ruby
259
- userbin.backup_codes
260
- userbin.generate_backup_codes(count: 8)
261
- ```
262
-
263
- ### List Pairings
264
-
265
- List all pairings.
266
-
267
- ```ruby
268
- # List all pairings
269
- userbin.pairings.each do |pairing|
270
- puts pairing.id # => 'yt9BkoHzcQoou4jqbQbJUqqMdxyxvCBr'
271
- puts pairing.type # => 'authenticator'
272
- puts pairing.default # => true
273
- end
274
- ```
275
-
276
- Set a pairing as the default one.
277
-
278
- ```ruby
279
- userbin.pairings.set_default!('yt9BkoHzcQoou4jqbQbJUqqMdxyxvCBr')
280
- ```
281
-
282
- Remove a pairing. If you remove the default pairing, two-factor authentication will be disabled.
283
-
284
- ```ruby
285
- userbin.pairings.destroy('yt9BkoHzcQoou4jqbQbJUqqMdxyxvCBr')
286
- ```
44
+ All the available events are:
287
45
 
46
+ - `login.succeeded`
47
+ - `login.failed`
48
+ - `logout.succeeded`
288
49
 
289
50
  ## Configuration
290
51
 
@@ -293,7 +54,7 @@ Userbin.configure do |config|
293
54
  # Same as setting it through Userbin.api_secret
294
55
  config.api_secret = 'secret'
295
56
 
296
- # Userbin::RequestError is raised when timing out (default: 2.0)
57
+ # Userbin::RequestError is raised when timing out (default: 30.0)
297
58
  config.request_timeout = 2.0
298
59
  end
299
60
  ```
@@ -1,3 +1,4 @@
1
+ require 'pry'
1
2
  require 'her'
2
3
  require 'userbin/ext/her'
3
4
  require 'faraday_middleware'
@@ -32,7 +32,8 @@ module Userbin
32
32
 
33
33
  @request_context = {
34
34
  ip: request.ip,
35
- user_agent: request.user_agent
35
+ user_agent: request.user_agent,
36
+ cookie_id: cookies['__cid']
36
37
  }
37
38
  end
38
39
 
@@ -126,5 +127,9 @@ module Userbin
126
127
  def has_default_pairing?
127
128
  @store.session_token ? @store.session_token.has_default_pairing? : false
128
129
  end
130
+
131
+ def track(opts = {})
132
+ Userbin::Event.post('/v1/events', opts)
133
+ end
129
134
  end
130
135
  end
@@ -106,9 +106,11 @@ module Userbin
106
106
  return @app.call(env) unless userbin
107
107
 
108
108
  userbin.request_context.each do |key, value|
109
- header =
109
+ if value
110
+ header =
110
111
  "X-Userbin-#{key.to_s.gsub('_', '-').gsub(/\w+/) {|m| m.capitalize}}"
111
- env[:request_headers][header] = value
112
+ env[:request_headers][header] = value
113
+ end
112
114
  end
113
115
  @app.call(env)
114
116
  end
@@ -1,3 +1,3 @@
1
1
  module Userbin
2
- VERSION = "1.6.1"
2
+ VERSION = "1.7.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: userbin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-20 00:00:00.000000000 Z
11
+ date: 2014-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: her