Skip to content

Commit

Permalink
api with bearer authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
yshmarov committed Apr 10, 2023
1 parent bd36ab2 commit 24bdf07
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 2 deletions.
22 changes: 22 additions & 0 deletions app/controllers/api/v1/authenticated_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Api::V1::AuthenticatedController < ActionController::Base
before_action :authenticate

attr_reader :current_api_token, :current_user

def authenticate
authenticate_user_with_token || handle_bad_authentication
end

private

def authenticate_user_with_token
authenticate_with_http_token do |token, options|
@current_api_token = ApiToken.where(active: true).find_by(token: token)
@current_user = @current_api_token&.user
end
end

def handle_bad_authentication
render json: { message: "Bad credentials" }, status: :unauthorized
end
end
6 changes: 6 additions & 0 deletions app/controllers/api/v1/home_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Api::V1::HomeController < Api::V1::AuthenticatedController
def index
# render json: { message: "Hello API world!" }
render json: { current_api_token: current_api_token.id, current_user: current_user.email }
end
end
12 changes: 12 additions & 0 deletions app/models/api_token.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class ApiToken < ApplicationRecord
belongs_to :user
validates :token, presence: true, uniqueness: true
before_validation :generate_token, on: :create
encrypts :token, deterministic: true

private

def generate_token
self.token = Digest::MD5.hexdigest(SecureRandom.hex)
end
end
1 change: 1 addition & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ class User < ApplicationRecord
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :api_tokens
end
2 changes: 1 addition & 1 deletion config/credentials.yml.enc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
W2O65qMJnzYqfOEiMoYHTmNK77omMUCwjtn/Cz1f11DSGdEBlAiJd2djWGBXBZdDrfpgcisUI36QyF7jkgPaCnM0r3czLx4t13logfQggl2YLfaiEBMheYPDSAErsWRwYG0aC2BW+9BN0Tq0SkQbxqE5TQMmcpZuT8qmQ+VYv1EzxcubGuZe3LG8MA1bdQk3SZ7zULE6ATqWpZwCRsgEA3+XlNhKccvaomEUlP+dBNHRMCcXfP3VJ3cfgghKUFpht5JuQrkJc0hK0dY2s70t+Fp6gQn1heH0ZPHQFWpCcEFw0jKi5D9zhGxXrcfgcPyqe2HOdCxwJkRqQnq05dQFJEHPor6zbLNtgMt9VMmAPsmLuCt6JuKpjH8V7osOdexA913p7l5G0jMxWhExEJB4PqHRb56Gwg6k6k5f--BJC+yeVsMOjHrS0q--xL3wMVlHE926w267r6aLrA==
U0TSwDrhHbm9tcrnPUicyjXa3suahk3q3sHn7n/0sZDvFe2D9saUb+1DXzHK+1roFjXcfRo0lgtn7OIy4+9OjbVimC5awN1wUYfxlmFvsDOUnz+LfqNCEmmIoZFYG3/34eua2b8sE62bePbowxKlumBkC7DbiQDKjj4ZG3AA2rS7gB3eG858NLNcxzhGi2+Bryp9oM5sRgL+s/j0M9EzPVUtgqfWkhn1yAIaeF91S957t0RCyxqic1dXbE491T5VPHzIWwHMJ9idpBnu2tYkHTTyf4E62FgCtlwh6UaFtSECxqKMIP/yX4JKjeSBvwnkCcZpsBbI8mIpO2RzbSEjKut+qgRHPtL60q0/qpfj0pbqNp9yzrPqbfNVYwHmAxfD+GYrd/0yh/zYxAJ40efLoYAuX6L2Vd4HmVCZlYGxPh9kUWyfPUNDFJTj9rrkQqqi6HR1d2E4Vxk2vvd96djzvN+a5pVP6btWo72L7QaOdPUlcXDERa27AJpBvqwJvbv5Pb9EWxtevdjmg9Ia0ZCIPyeWz4NAvLDJyRi0ifrPhXBWehXHFjJQajYGQpJKVMytHrAWmPbijnQ72rxLj04G57ay6eD/VRhdDgAx+RAY4APSSuLLAh3a2WLZ/B4EKs4XlrCN5zP/r6sg70IkFTs=--xBvZE1HfxfVX6miH--D/Qxe8PsS8JxRBcGvAXKSA==
8 changes: 8 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,12 @@
devise_for :users
root 'static_pages#landing_page'
get 'dashboard', to: 'static_pages#dashboard'

namespace :api do
namespace :v1 do
defaults format: :json do
get "home/index", to: "home#index"
end
end
end
end
11 changes: 11 additions & 0 deletions db/migrate/20230410200135_create_api_tokens.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class CreateApiTokens < ActiveRecord::Migration[7.0]
def change
create_table :api_tokens do |t|
t.references :user, null: false, foreign_key: true
t.text :token, null: false
t.boolean :active, default: true

t.timestamps
end
end
end
12 changes: 11 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions test/fixtures/api_tokens.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

one:
user: one
token: MyText
active: false

two:
user: two
token: MyText
active: false
20 changes: 20 additions & 0 deletions test/integration/api/home_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'test_helper'

class HomeControllerTest < ActionDispatch::IntegrationTest
test 'when auth token is valid' do
user = users(:one)
api_token = user.api_tokens.create!
get api_v1_home_index_path, headers: { HTTP_AUTHORIZATION: "Token token=#{api_token.token}" }
assert_response :success
assert_includes response.body, user.email
end

test 'when auth token is inactive' do
user = users(:one)
api_token = user.api_tokens.create!
api_token.update!(active: false)
get api_v1_home_index_path, headers: { HTTP_AUTHORIZATION: "Token token=#{api_token.token}" }
assert_response :unauthorized
assert_includes response.body, 'Bad credentials'
end
end
7 changes: 7 additions & 0 deletions test/models/api_token_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require "test_helper"

class ApiTokenTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end

0 comments on commit 24bdf07

Please sign in to comment.