devise_token_auth 0.1.28 → 0.1.29.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +61 -1
- data/app/controllers/devise_token_auth/{auth_controller.rb → omniauth_callbacks_controller.rb} +22 -33
- data/app/controllers/devise_token_auth/registrations_controller.rb +2 -0
- data/app/controllers/devise_token_auth/sessions_controller.rb +1 -1
- data/app/controllers/devise_token_auth/token_validations_controller.rb +23 -0
- data/app/models/devise_token_auth/concerns/user.rb +1 -3
- data/config/initializers/devise.rb +0 -9
- data/config/routes.rb +12 -1
- data/lib/devise_token_auth/engine.rb +8 -0
- data/lib/devise_token_auth/rails/routes.rb +30 -9
- data/lib/devise_token_auth/version.rb +1 -1
- data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +0 -2
- data/test/controllers/devise_token_auth/{auth_controller_test.rb → omniauth_callbacks_controller_test.rb} +4 -4
- data/test/controllers/devise_token_auth/registrations_controller_test.rb +6 -0
- data/test/controllers/overrides/confirmations_controller_test.rb +44 -0
- data/test/controllers/overrides/omniauth_callbacks_controller_test.rb +44 -0
- data/test/controllers/overrides/passwords_controller_test.rb +62 -0
- data/test/controllers/overrides/registrations_controller_test.rb +40 -0
- data/test/controllers/overrides/sessions_controller_test.rb +33 -0
- data/test/controllers/overrides/token_validations_controller_test.rb +38 -0
- data/test/dummy/app/controllers/overrides/confirmations_controller.rb +32 -0
- data/test/dummy/app/controllers/overrides/omniauth_callbacks_controller.rb +14 -0
- data/test/dummy/app/controllers/overrides/passwords_controller.rb +39 -0
- data/test/dummy/app/controllers/overrides/registrations_controller.rb +27 -0
- data/test/dummy/app/controllers/overrides/sessions_controller.rb +43 -0
- data/test/dummy/app/controllers/overrides/token_validations_controller.rb +23 -0
- data/test/dummy/{tmp/generators/app/models/mang.rb → app/models/evil_user.rb} +1 -1
- data/test/dummy/config/routes.rb +9 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/{tmp/generators/db/migrate/20140924174608_devise_token_auth_create_mangs.rb → db/migrate/20140928231203_devise_token_auth_create_evil_users.rb} +10 -9
- data/test/dummy/db/schema.rb +33 -1
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +437 -0
- data/test/dummy/log/test.log +72703 -0
- data/test/dummy/tmp/generators/config/routes.rb +0 -5
- data/test/dummy/tmp/generators/db/migrate/{20140924174608_devise_token_auth_create_users.rb → 20140930001137_devise_token_auth_create_users.rb} +0 -2
- data/test/fixtures/evil_users.yml +29 -0
- data/test/fixtures/mangs.yml +0 -2
- data/test/fixtures/users.yml +0 -2
- metadata +40 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27aae401ac1cd56896e88990fafd43722ae0874d
|
4
|
+
data.tar.gz: 641556555fefe2509adf75b29125a94abb9ca14a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a439fc3a695c0aeec35b4a15b9c5da795fa66ceffe917d03a3b9da79ebe713b59a742af02911f0bd0d301a79f6c5785c101dda0ea15fc93dc44b7614e556fb76
|
7
|
+
data.tar.gz: f6e51f041bee6233ffa21a92888fc62fcd1be9fd871bc233c946e2735b3745e3f0a0d640ba7eb26ab486eea759d49acdf8ab108e6b268412bcbf73b10826d581
|
data/README.md
CHANGED
@@ -42,6 +42,7 @@ The fully configured api used in the demo can be found [here](https://github.com
|
|
42
42
|
* [Controller Integration](#controller-concerns)
|
43
43
|
* [Model Integration](#model-concerns)
|
44
44
|
* [Using Multiple User Classes](#using-multiple-models)
|
45
|
+
* [Custom Controller Overrides](#custom-controller-overrides)
|
45
46
|
* [Conceptual Diagrams](#conceptual)
|
46
47
|
* [Token Management](#about-token-management)
|
47
48
|
* [Batch Requests](#about-batch-requests)
|
@@ -75,12 +76,18 @@ You will need to create a [user model](#model-concerns), [define routes](#mounti
|
|
75
76
|
rails g devise_token_auth:install [USER_CLASS] [MOUNT_PATH]
|
76
77
|
~~~
|
77
78
|
|
79
|
+
**Example**:
|
80
|
+
|
81
|
+
~~~bash
|
82
|
+
rails g devise_token_auth:install User /auth
|
83
|
+
~~~
|
84
|
+
|
78
85
|
This generator accepts the following optional arguments:
|
79
86
|
|
80
87
|
| Argument | Default | Description |
|
81
88
|
|---|---|---|
|
82
89
|
| USER_CLASS | `User` | The name of the class to use for user authentication. |
|
83
|
-
| MOUNT_PATH |
|
90
|
+
| MOUNT_PATH | `/auth` | The path at which to mount the authentication routes. [Read more](#usage). |
|
84
91
|
|
85
92
|
The following events will take place when using the install generator:
|
86
93
|
|
@@ -498,6 +505,59 @@ In the above example, the following methods will be available (in addition to `c
|
|
498
505
|
* `current_member`
|
499
506
|
* `member_signed_in?`
|
500
507
|
|
508
|
+
## Custom Controller Overrides
|
509
|
+
|
510
|
+
The built-in controllers can be overridden with your own custom controllers.
|
511
|
+
|
512
|
+
For example, the default behavior of the [`validate_token`](https://github.com/lynndylanhurley/devise_token_auth/blob/8a33d25deaedb4809b219e557e82ec7ec61bf940/app/controllers/devise_token_auth/token_validations_controller.rb#L6) method of the [`TokenValidationController`](https://github.com/lynndylanhurley/devise_token_auth/blob/8a33d25deaedb4809b219e557e82ec7ec61bf940/app/controllers/devise_token_auth/token_validations_controller.rb) is to return the `User` object as json (sans password and token data). The following example shows how to override the `validate_token` action to include a model method as well.
|
513
|
+
|
514
|
+
##### Example: controller overrides
|
515
|
+
|
516
|
+
~~~ruby
|
517
|
+
# config/routes.rb
|
518
|
+
Rails.application.routes.draw do
|
519
|
+
...
|
520
|
+
mount_devise_token_auth_for 'User', at: '/auth', controllers: {
|
521
|
+
token_validations: 'overrides/token_validations'
|
522
|
+
}
|
523
|
+
end
|
524
|
+
|
525
|
+
# app/controllers/overrides/token_validations_controller.rb
|
526
|
+
module Overrides
|
527
|
+
class TokenValidationsController < DeviseTokenAuth::TokenValidationsController
|
528
|
+
|
529
|
+
def validate_token
|
530
|
+
# @user will have been set by set_user_by_token concern
|
531
|
+
if @user
|
532
|
+
render json: {
|
533
|
+
data: @user.as_json(methods: :calculate_operating_thetan)
|
534
|
+
}
|
535
|
+
else
|
536
|
+
render json: {
|
537
|
+
success: false,
|
538
|
+
errors: ["Invalid login credentials"]
|
539
|
+
}, status: 401
|
540
|
+
end
|
541
|
+
end
|
542
|
+
end
|
543
|
+
end
|
544
|
+
~~~
|
545
|
+
|
546
|
+
##### Example: all :controller options with default settings:
|
547
|
+
|
548
|
+
~~~ruby
|
549
|
+
mount_devise_token_auth_for 'User', at: '/auth', controllers: {
|
550
|
+
confirmations: 'devise_token_auth/confirmations',
|
551
|
+
passwords: 'devise_token_auth/passwords',
|
552
|
+
omniauth_callbacks: 'devise_token_auth/omniauth_callbacks',
|
553
|
+
registrations: 'devise_token_auth/registrations',
|
554
|
+
sessions: 'devise_token_auth/sessions',
|
555
|
+
token_validations: 'devise_token_auth/token_validations'
|
556
|
+
}
|
557
|
+
~~~
|
558
|
+
|
559
|
+
**Note:** Controller overrides must implement the expected actions of the controllers that they replace.
|
560
|
+
|
501
561
|
# Conceptual
|
502
562
|
|
503
563
|
None of the following information is required to use this gem, but read on if you're curious.
|
data/app/controllers/devise_token_auth/{auth_controller.rb → omniauth_callbacks_controller.rb}
RENAMED
@@ -1,25 +1,6 @@
|
|
1
1
|
module DeviseTokenAuth
|
2
|
-
class
|
2
|
+
class OmniauthCallbacksController < DeviseTokenAuth::ApplicationController
|
3
3
|
skip_after_filter :update_auth_header, :only => [:omniauth_success, :omniauth_failure]
|
4
|
-
skip_before_filter :assert_is_devise_resource!, :only => [:validate_token]
|
5
|
-
before_filter :set_user_by_token, :only => [:validate_token]
|
6
|
-
|
7
|
-
def validate_token
|
8
|
-
# @user will have been set by set_user_token concern
|
9
|
-
if @user
|
10
|
-
render json: {
|
11
|
-
success: true,
|
12
|
-
data: @user.as_json(except: [
|
13
|
-
:tokens, :confirm_success_url, :reset_password_redirect_url, :created_at, :updated_at
|
14
|
-
])
|
15
|
-
}
|
16
|
-
else
|
17
|
-
render json: {
|
18
|
-
success: false,
|
19
|
-
errors: ["Invalid login credentials"]
|
20
|
-
}, status: 401
|
21
|
-
end
|
22
|
-
end
|
23
4
|
|
24
5
|
def omniauth_success
|
25
6
|
# find or create user by provider and provider uid
|
@@ -32,7 +13,7 @@ module DeviseTokenAuth
|
|
32
13
|
@client_id = SecureRandom.urlsafe_base64(nil, false)
|
33
14
|
@token = SecureRandom.urlsafe_base64(nil, false)
|
34
15
|
|
35
|
-
@auth_origin_url = generate_url(
|
16
|
+
@auth_origin_url = generate_url(auth_params['auth_origin_url'], {
|
36
17
|
token: @token,
|
37
18
|
client_id: @client_id,
|
38
19
|
uid: @user.uid
|
@@ -52,12 +33,7 @@ module DeviseTokenAuth
|
|
52
33
|
}
|
53
34
|
|
54
35
|
# sync user info with provider, update/generate auth token
|
55
|
-
@user
|
56
|
-
nickname: auth_hash['info']['nickname'],
|
57
|
-
name: auth_hash['info']['name'],
|
58
|
-
image: auth_hash['info']['image'],
|
59
|
-
email: auth_hash['info']['email']
|
60
|
-
})
|
36
|
+
assign_provider_attrs(@user, auth_hash)
|
61
37
|
|
62
38
|
# assign any additional (whitelisted) attributes
|
63
39
|
extra_params = whitelisted_params
|
@@ -74,6 +50,15 @@ module DeviseTokenAuth
|
|
74
50
|
end
|
75
51
|
end
|
76
52
|
|
53
|
+
def assign_provider_attrs(user, auth_hash)
|
54
|
+
user.assign_attributes({
|
55
|
+
nickname: auth_hash['info']['nickname'],
|
56
|
+
name: auth_hash['info']['name'],
|
57
|
+
image: auth_hash['info']['image'],
|
58
|
+
email: auth_hash['info']['email']
|
59
|
+
})
|
60
|
+
end
|
61
|
+
|
77
62
|
def omniauth_failure
|
78
63
|
@error = params[:message]
|
79
64
|
|
@@ -83,14 +68,18 @@ module DeviseTokenAuth
|
|
83
68
|
end
|
84
69
|
|
85
70
|
def auth_hash
|
86
|
-
|
71
|
+
params["auth_hash"]
|
72
|
+
end
|
73
|
+
|
74
|
+
def auth_params
|
75
|
+
params["auth_params"]
|
87
76
|
end
|
88
77
|
|
89
78
|
def whitelisted_params
|
90
79
|
whitelist = devise_parameter_sanitizer.for(:sign_up)
|
91
80
|
|
92
81
|
whitelist.inject({}){|coll, key|
|
93
|
-
param =
|
82
|
+
param = auth_params[key.to_s]
|
94
83
|
if param
|
95
84
|
coll[key] = param
|
96
85
|
end
|
@@ -104,8 +93,8 @@ module DeviseTokenAuth
|
|
104
93
|
|
105
94
|
# pull resource class from omniauth return
|
106
95
|
def resource_name
|
107
|
-
if
|
108
|
-
|
96
|
+
if auth_params
|
97
|
+
auth_params['resource_class'].constantize
|
109
98
|
else
|
110
99
|
super
|
111
100
|
end
|
@@ -113,8 +102,8 @@ module DeviseTokenAuth
|
|
113
102
|
|
114
103
|
# necessary for access to devise_parameter_sanitizers
|
115
104
|
def devise_mapping
|
116
|
-
if
|
117
|
-
Devise.mappings[
|
105
|
+
if auth_params
|
106
|
+
Devise.mappings[auth_params['resource_class'].underscore.to_sym]
|
118
107
|
else
|
119
108
|
request.env['devise.mapping']
|
120
109
|
end
|
@@ -20,6 +20,8 @@ module DeviseTokenAuth
|
|
20
20
|
end
|
21
21
|
|
22
22
|
begin
|
23
|
+
# override email confirmation, must be sent manually from ctrl
|
24
|
+
User.skip_callback("create", :after, :send_on_create_confirmation_instructions)
|
23
25
|
if @resource.save
|
24
26
|
@resource.send_confirmation_instructions({
|
25
27
|
client_config: params[:config_name],
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DeviseTokenAuth
|
2
|
+
class TokenValidationsController < DeviseTokenAuth::ApplicationController
|
3
|
+
skip_before_filter :assert_is_devise_resource!, :only => [:validate_token]
|
4
|
+
before_filter :set_user_by_token, :only => [:validate_token]
|
5
|
+
|
6
|
+
def validate_token
|
7
|
+
# @user will have been set by set_user_token concern
|
8
|
+
if @user
|
9
|
+
render json: {
|
10
|
+
success: true,
|
11
|
+
data: @user.as_json(except: [
|
12
|
+
:tokens, :created_at, :updated_at
|
13
|
+
])
|
14
|
+
}
|
15
|
+
else
|
16
|
+
render json: {
|
17
|
+
success: false,
|
18
|
+
errors: ["Invalid login credentials"]
|
19
|
+
}, status: 401
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -6,7 +6,7 @@ module DeviseTokenAuth::Concerns::User
|
|
6
6
|
# :confirmable, :lockable, :timeoutable and :omniauthable
|
7
7
|
devise :database_authenticatable, :registerable,
|
8
8
|
:recoverable, :rememberable, :trackable, :validatable,
|
9
|
-
:confirmable
|
9
|
+
:confirmable, :omniauthable
|
10
10
|
|
11
11
|
serialize :tokens, JSON
|
12
12
|
|
@@ -48,7 +48,6 @@ module DeviseTokenAuth::Concerns::User
|
|
48
48
|
send_devise_notification(:confirmation_instructions, @raw_confirmation_token, opts)
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
51
|
# override devise method to include additional info as opts hash
|
53
52
|
def send_reset_password_instructions(opts=nil)
|
54
53
|
token = set_reset_password_token
|
@@ -71,7 +70,6 @@ module DeviseTokenAuth::Concerns::User
|
|
71
70
|
end
|
72
71
|
|
73
72
|
|
74
|
-
|
75
73
|
def valid_token?(token, client_id='default')
|
76
74
|
client_id ||= 'default'
|
77
75
|
|
data/config/routes.rb
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
2
|
if defined?(::OmniAuth)
|
3
|
-
|
3
|
+
match "#{::OmniAuth::config.path_prefix}/:provider/callback", to: redirect {|params, request|
|
4
|
+
devise_mapping = request.env['omniauth.params']['resource_class'].underscore.to_sym
|
5
|
+
mount_point = Devise.mappings[devise_mapping].as_json["path_prefix"]
|
6
|
+
|
7
|
+
qs = {
|
8
|
+
auth_hash: request.env['omniauth.auth'],
|
9
|
+
auth_params: request.env['omniauth.params']
|
10
|
+
}.to_query
|
11
|
+
|
12
|
+
"#{mount_point}/#{params[:provider]}/callback?#{qs}"
|
13
|
+
}, via: :all
|
4
14
|
end
|
15
|
+
|
5
16
|
end
|
@@ -7,6 +7,14 @@ module DeviseTokenAuth
|
|
7
7
|
initializer "devise_token_auth.url_helpers" do
|
8
8
|
Devise.helpers << DeviseTokenAuth::Controllers::Helpers
|
9
9
|
end
|
10
|
+
|
11
|
+
initializer "devise_token_auth.omniauth_strategy" do
|
12
|
+
if defined?(::OmniAuth)
|
13
|
+
Devise.with_options model: true do |d|
|
14
|
+
d.add_module(:dta_omniauthable, controller: :omniauth_callbacks, route: :omniauth_callbacks)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
10
18
|
end
|
11
19
|
|
12
20
|
mattr_accessor :change_headers_on_each_request,
|
@@ -1,22 +1,43 @@
|
|
1
1
|
module ActionDispatch::Routing
|
2
2
|
class Mapper
|
3
3
|
def mount_devise_token_auth_for(resource, opts)
|
4
|
+
# ensure objects exist to simplify attr checks
|
5
|
+
opts[:controllers] ||= {}
|
6
|
+
opts[:skip] ||= []
|
7
|
+
|
8
|
+
# check for ctrl overrides, fall back to defaults
|
9
|
+
sessions_ctrl = opts[:controllers][:sessions] || "devise_token_auth/sessions"
|
10
|
+
registrations_ctrl = opts[:controllers][:registrations] || "devise_token_auth/registrations"
|
11
|
+
passwords_ctrl = opts[:controllers][:passwords] || "devise_token_auth/passwords"
|
12
|
+
confirmations_ctrl = opts[:controllers][:confirmations] || "devise_token_auth/confirmations"
|
13
|
+
token_validations_ctrl = opts[:controllers][:token_validations] || "devise_token_auth/token_validations"
|
14
|
+
omniauth_ctrl = opts[:controllers][:omniauth_callbacks] || "devise_token_auth/omniauth_callbacks"
|
15
|
+
|
16
|
+
# define devise controller mappings
|
17
|
+
controllers = {:sessions => sessions_ctrl,
|
18
|
+
:registrations => registrations_ctrl,
|
19
|
+
:passwords => passwords_ctrl,
|
20
|
+
:confirmations => confirmations_ctrl,
|
21
|
+
:omniauth_callbacks => omniauth_ctrl}
|
22
|
+
|
23
|
+
# remove any unwanted devise modules
|
24
|
+
opts[:skip].each{|item| controllers.delete(item)}
|
25
|
+
|
4
26
|
scope opts[:at] do
|
5
27
|
devise_for resource.pluralize.underscore.to_sym,
|
6
28
|
:class_name => resource,
|
7
29
|
:module => :devise,
|
8
30
|
:path => "",
|
9
|
-
:controllers =>
|
10
|
-
:registrations => "devise_token_auth/registrations",
|
11
|
-
:passwords => "devise_token_auth/passwords",
|
12
|
-
:confirmations => "devise_token_auth/confirmations"}
|
31
|
+
:controllers => controllers
|
13
32
|
|
14
33
|
devise_scope resource.underscore.to_sym do
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
34
|
+
# path to verify token validity
|
35
|
+
get "validate_token", to: "#{token_validations_ctrl}#validate_token"
|
36
|
+
|
37
|
+
# omniauth routes. only define if omniauth is installed and not skipped.
|
38
|
+
if defined?(::OmniAuth) and not opts[:skip].include?(:omniauth_callbacks)
|
39
|
+
get "failure", to: "#{omniauth_ctrl}#omniauth_failure"
|
40
|
+
get ":provider/callback", to: "#{omniauth_ctrl}#omniauth_success"
|
20
41
|
|
21
42
|
# preserve the resource class thru oauth authentication by setting name of
|
22
43
|
# resource as "resource_class" param
|
@@ -8,7 +8,6 @@ class DeviseTokenAuthCreate<%= user_class.pluralize %> < ActiveRecord::Migration
|
|
8
8
|
## Recoverable
|
9
9
|
t.string :reset_password_token
|
10
10
|
t.datetime :reset_password_sent_at
|
11
|
-
t.string :reset_password_redirect_url
|
12
11
|
|
13
12
|
## Rememberable
|
14
13
|
t.datetime :remember_created_at
|
@@ -24,7 +23,6 @@ class DeviseTokenAuthCreate<%= user_class.pluralize %> < ActiveRecord::Migration
|
|
24
23
|
t.string :confirmation_token
|
25
24
|
t.datetime :confirmed_at
|
26
25
|
t.datetime :confirmation_sent_at
|
27
|
-
t.string :confirm_success_url
|
28
26
|
t.string :unconfirmed_email # Only if using reconfirmable
|
29
27
|
|
30
28
|
## Lockable
|
@@ -38,11 +38,11 @@ class OmniauthTest < ActionDispatch::IntegrationTest
|
|
38
38
|
end
|
39
39
|
|
40
40
|
test 'request should determine the correct resource_class' do
|
41
|
-
assert_equal 'User',
|
41
|
+
assert_equal 'User', controller.auth_params['resource_class']
|
42
42
|
end
|
43
43
|
|
44
44
|
test 'request should pass correct redirect_url' do
|
45
|
-
assert_equal @redirect_url,
|
45
|
+
assert_equal @redirect_url, controller.auth_params['auth_origin_url']
|
46
46
|
end
|
47
47
|
|
48
48
|
test 'user should have been created' do
|
@@ -116,11 +116,11 @@ class OmniauthTest < ActionDispatch::IntegrationTest
|
|
116
116
|
end
|
117
117
|
|
118
118
|
test 'request should determine the correct resource_class' do
|
119
|
-
assert_equal 'Mang',
|
119
|
+
assert_equal 'Mang', controller.auth_params['resource_class']
|
120
120
|
end
|
121
121
|
|
122
122
|
test 'request should pass correct redirect_url' do
|
123
|
-
assert_equal @redirect_url,
|
123
|
+
assert_equal @redirect_url, controller.auth_params['auth_origin_url']
|
124
124
|
end
|
125
125
|
|
126
126
|
test 'user should have been created' do
|
@@ -10,6 +10,8 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionController::TestCase
|
|
10
10
|
describe DeviseTokenAuth::RegistrationsController do
|
11
11
|
describe "Successful registration" do
|
12
12
|
before do
|
13
|
+
@mails_sent = ActionMailer::Base.deliveries.count
|
14
|
+
|
13
15
|
xhr :post, :create, {
|
14
16
|
email: Faker::Internet.email,
|
15
17
|
password: "secret123",
|
@@ -46,6 +48,10 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionController::TestCase
|
|
46
48
|
test "new user password should not be returned" do
|
47
49
|
assert_nil @data['data']['password']
|
48
50
|
end
|
51
|
+
|
52
|
+
test "only one email was sent" do
|
53
|
+
assert_equal @mails_sent + 1, ActionMailer::Base.deliveries.count
|
54
|
+
end
|
49
55
|
end
|
50
56
|
|
51
57
|
describe "Adding extra params" do
|