Skip to content

Commit 43951d2

Browse files
Token from header (#3)
* Adding JWT gem, and fetching user from that JWT token * Adding empty test * Make rubocop happy * More rubocop * Only run tests on push * Raise an exception if the JWT is missing, or the user is missing We catch the exception in user_signed_in?, since that should just be a boolean * Throw our own raise when JWT errors out * jwt_user_id should return nil in the case of being unauthorized * current_user should return nil if Unauthorized is thrown * Delete authable_test.rb
1 parent e73a352 commit 43951d2

File tree

4 files changed

+45
-3
lines changed

4 files changed

+45
-3
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Ruby
22

3-
on: [push, pull_request]
3+
on: push
44

55
jobs:
66
test:

lib/tokenable.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
# frozen_string_literal: true
22

33
require_relative 'tokenable/version'
4+
require_relative 'tokenable/authable'
45
require_relative 'tokenable/railtie' if defined?(Rails)
56

67
module Tokenable
78
class Error < StandardError; end
9+
class Unauthorized < Error; end
10+
811
# Your code goes here...
912
end

lib/tokenable/authable.rb

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# frozen_string_literal: true
22

33
# The main controller concern that will be injected to the application
4+
5+
require 'jwt'
6+
require 'active_support/concern'
7+
48
module Tokenable
59
module Authable
610
extend ActiveSupport::Concern
@@ -9,11 +13,45 @@ module Authable
913
end
1014

1115
def user_signed_in?
12-
true
16+
current_user.present?
17+
rescue Tokenable::Unauthorized
18+
false
1319
end
1420

1521
def current_user
16-
User.first
22+
@current_user ||= user_class.find(jwt_user_id)
23+
rescue Tokenable::Unauthorized
24+
nil
25+
end
26+
27+
def require_tokenable_user!
28+
raise Tokenable::Unauthorized unless user_signed_in?
29+
end
30+
31+
private
32+
33+
def user_class
34+
User
35+
end
36+
37+
def token_from_header
38+
headers['Authorization'].to_s.split(' ').last
39+
end
40+
41+
def jwt_user_id
42+
jwt['data']['user_id']
43+
end
44+
45+
def jwt
46+
raise Tokenable::Unauthorized unless token_from_header.present?
47+
48+
@jwt ||= JWT.decode(token_from_header, jwt_secret, true, { algorithm: 'HS256' }).first
49+
rescue JWT::ExpiredSignature, JWT::DecodeError
50+
raise Tokenable::Unauthorized
51+
end
52+
53+
def jwt_secret
54+
Rails.application.secret_key_base
1755
end
1856
end
1957
end

tokenable.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ Gem::Specification.new do |spec|
2727
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
2828
spec.require_paths = ['lib']
2929

30+
spec.add_dependency 'jwt', '~> 2.2', '< 3'
3031
spec.add_dependency 'rails', '~> 6.0', '< 6.2'
3132
end

0 commit comments

Comments
 (0)