userbin 1.6.1 → 1.7.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 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