From 3f8ca715cc6df6133ad9c95361ea30872102814c Mon Sep 17 00:00:00 2001 From: Thor77 Date: Sat, 10 Nov 2018 15:46:02 +0100 Subject: [PATCH] Add devise token authentication --- Gemfile | 4 ++ Gemfile.lock | 20 ++++++- app/controllers/application_controller.rb | 9 +++ app/models/user.rb | 10 ++++ config/environments/development.rb | 5 ++ config/initializers/devise_token_auth.rb | 50 +++++++++++++++++ config/routes.rb | 2 +- ...10141016_devise_token_auth_create_users.rb | 55 +++++++++++++++++++ 8 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 app/models/user.rb create mode 100644 config/initializers/devise_token_auth.rb create mode 100644 db/migrate/20181110141016_devise_token_auth_create_users.rb diff --git a/Gemfile b/Gemfile index f8e25a1..3699c2e 100644 --- a/Gemfile +++ b/Gemfile @@ -26,6 +26,10 @@ gem 'bootsnap', '>= 1.1.0', require: false # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible # gem 'rack-cors' +# Authentication +gem 'devise' +gem 'devise_token_auth' + group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] diff --git a/Gemfile.lock b/Gemfile.lock index 001e501..48254eb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -43,12 +43,22 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) arel (9.0.0) + bcrypt (3.1.12) bootsnap (1.3.2) msgpack (~> 1.0) builder (3.2.3) byebug (10.0.2) concurrent-ruby (1.0.5) crass (1.0.4) + devise (4.5.0) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 4.1.0, < 6.0) + responders + warden (~> 1.2.3) + devise_token_auth (1.0.0) + devise (> 3.5.2, < 4.6) + rails (>= 4.2.0, < 6) erubi (1.7.1) ffi (1.9.25) globalid (0.4.1) @@ -75,6 +85,7 @@ GEM nio4r (2.3.1) nokogiri (1.8.5) mini_portile2 (~> 2.3.0) + orm_adapter (0.5.0) puma (3.12.0) rack (2.0.5) rack-test (1.1.0) @@ -107,6 +118,9 @@ GEM rb-fsevent (0.10.3) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) + responders (2.4.0) + actionpack (>= 4.2.0, < 5.3) + railties (>= 4.2.0, < 5.3) ruby_dep (1.5.0) spring (2.0.2) activesupport (>= 4.2) @@ -125,6 +139,8 @@ GEM thread_safe (0.3.6) tzinfo (1.2.5) thread_safe (~> 0.1) + warden (1.2.7) + rack (>= 1.0) websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) @@ -135,6 +151,8 @@ PLATFORMS DEPENDENCIES bootsnap (>= 1.1.0) byebug + devise + devise_token_auth listen (>= 3.0.5, < 3.2) puma (~> 3.11) rails (~> 5.2.1) @@ -147,4 +165,4 @@ RUBY VERSION ruby 2.5.3p105 BUNDLED WITH - 1.16.6 + 1.17.1 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4ac8823..0c74af7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,11 @@ class ApplicationController < ActionController::API + include DeviseTokenAuth::Concerns::SetUserByToken + + before_action :configure_permitted_parameters, if: :devise_controller? + + protected + + def configure_permitted_parameters + devise_parameter_sanitizer.permit(:sign_up, keys: [:username]) + end end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..41701c1 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class User < ApplicationRecord + devise :database_authenticatable, :registerable, + :recoverable, :rememberable, :trackable + + include DeviseTokenAuth::Concerns::User + + validates :username, presence: true, uniqueness: true +end diff --git a/config/environments/development.rb b/config/environments/development.rb index d52ec9e..c63409b 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -51,4 +51,9 @@ Rails.application.configure do # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. config.file_watcher = ActiveSupport::EventedFileUpdateChecker + + # Mail + config.action_mailer.default_url_options = { host: 'localhost' } + config.action_mailer.delivery_method = :smtp + config.action_mailer.smtp_settings = { address: 'localhost', port: 1025 } end diff --git a/config/initializers/devise_token_auth.rb b/config/initializers/devise_token_auth.rb new file mode 100644 index 0000000..dec712e --- /dev/null +++ b/config/initializers/devise_token_auth.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +DeviseTokenAuth.setup do |config| + # By default the authorization headers will change after each request. The + # client is responsible for keeping track of the changing tokens. Change + # this to false to prevent the Authorization header from changing after + # each request. + # config.change_headers_on_each_request = true + + # By default, users will need to re-authenticate after 2 weeks. This setting + # determines how long tokens will remain valid after they are issued. + # config.token_lifespan = 2.weeks + + # Sets the max number of concurrent devices per user, which is 10 by default. + # After this limit is reached, the oldest tokens will be removed. + # config.max_number_of_devices = 10 + + # Sometimes it's necessary to make several requests to the API at the same + # time. In this case, each request in the batch will need to share the same + # auth token. This setting determines how far apart the requests can be while + # still using the same auth token. + # config.batch_request_buffer_throttle = 5.seconds + + # This route will be the prefix for all oauth2 redirect callbacks. For + # example, using the default '/omniauth', the github oauth2 provider will + # redirect successful authentications to '/omniauth/github/callback' + # config.omniauth_prefix = "/omniauth" + + # By default sending current password is not needed for the password update. + # Uncomment to enforce current_password param to be checked before all + # attribute updates. Set it to :password if you want it to be checked only if + # password is updated. + # config.check_current_password_before_update = :attributes + + # By default we will use callbacks for single omniauth. + # It depends on fields like email, provider and uid. + # config.default_callbacks = true + + # Makes it possible to change the headers names + # config.headers_names = {:'access-token' => 'access-token', + # :'client' => 'client', + # :'expiry' => 'expiry', + # :'uid' => 'uid', + # :'token-type' => 'token-type' } + + # By default, only Bearer Token authentication is implemented out of the box. + # If, however, you wish to integrate with legacy Devise authentication, you can + # do so by enabling this flag. NOTE: This feature is highly experimental! + # config.enable_standard_devise_support = false +end diff --git a/config/routes.rb b/config/routes.rb index 787824f..5bf22d6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,3 @@ Rails.application.routes.draw do - # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + mount_devise_token_auth_for 'User', at: 'users' end diff --git a/db/migrate/20181110141016_devise_token_auth_create_users.rb b/db/migrate/20181110141016_devise_token_auth_create_users.rb new file mode 100644 index 0000000..db21478 --- /dev/null +++ b/db/migrate/20181110141016_devise_token_auth_create_users.rb @@ -0,0 +1,55 @@ +class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[5.2] + def change + + create_table(:users) do |t| + ## Required + t.string :provider, :null => false, :default => "email" + t.string :uid, :null => false, :default => "" + + ## Database authenticatable + t.string :encrypted_password, :null => false, :default => "" + + ## Recoverable + t.string :reset_password_token + t.datetime :reset_password_sent_at + t.boolean :allow_password_change, :default => false + + ## Rememberable + t.datetime :remember_created_at + + ## Trackable + t.integer :sign_in_count, :default => 0, :null => false + t.datetime :current_sign_in_at + t.datetime :last_sign_in_at + t.string :current_sign_in_ip + t.string :last_sign_in_ip + + ## Confirmable + t.string :confirmation_token + t.datetime :confirmed_at + t.datetime :confirmation_sent_at + t.string :unconfirmed_email # Only if using reconfirmable + + ## Lockable + # t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts + # t.string :unlock_token # Only if unlock strategy is :email or :both + # t.datetime :locked_at + + ## User Info + t.string :username + t.string :email + + ## Tokens + t.text :tokens + + t.timestamps + end + + add_index :users, :username, unique: true + add_index :users, :email, unique: true + add_index :users, [:uid, :provider], unique: true + add_index :users, :reset_password_token, unique: true + add_index :users, :confirmation_token, unique: true + # add_index :users, :unlock_token, unique: true + end +end