Module: ApiGuard::JwtAuth::Authentication
- Defined in:
- lib/api_guard/jwt_auth/authentication.rb
Overview
Common module for API authentication
Instance Method Summary collapse
-
#authenticate_and_set_resources(resource_names) ⇒ Object
Authenticate the JWT token and set resources.
-
#authenticate_token ⇒ Object
Authenticate the resource with the '{resource_name}_id' in the decoded JWT token and also, check for valid issued at time and not blacklisted.
- #current_resource ⇒ Object
-
#decode_token ⇒ Object
Decode the JWT token and don't verify token expiry for refresh token API request.
-
#define_current_resource_accessors(resource) ⇒ Object
Defines “current_{resource_name}” method and “@current_{resource_name}” instance variable that returns “resource” value.
- #find_resource_from_token(resource_class) ⇒ Object
-
#method_missing(name, *args) ⇒ Object
Handle authentication of the resource dynamically.
- #respond_to_missing?(method_name, include_private = false) ⇒ Boolean
- #set_resource_name_from_token(resource_names) ⇒ Object
-
#valid_issued_at?(resource) ⇒ Boolean
Returns whether the JWT token is issued after the last password change Returns true if password hasn't changed by the user.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args) ⇒ Object
Handle authentication of the resource dynamically
8 9 10 11 12 13 14 15 16 17 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 8 def method_missing(name, *args) method_name = name.to_s if method_name.start_with?('authenticate_and_set_') resource_names = method_name.split('authenticate_and_set_')[1].split('_or_') authenticate_and_set_resources(resource_names) else super end end |
Instance Method Details
#authenticate_and_set_resources(resource_names) ⇒ Object
Authenticate the JWT token and set resources
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 24 def authenticate_and_set_resources(resource_names) @resource_names = resource_names @token = request.headers['Authorization']&.split('Bearer ')&.last return render_error(401, message: I18n.t('api_guard.access_token.missing')) unless @token authenticate_token # Render error response only if no resource found and no previous render happened render_error(401, message: I18n.t('api_guard.access_token.invalid')) if !current_resource && !performed? rescue JWT::DecodeError => e if e. == 'Signature has expired' render_error(401, message: I18n.t('api_guard.access_token.expired')) else render_error(401, message: I18n.t('api_guard.access_token.invalid')) end end |
#authenticate_token ⇒ Object
Authenticate the resource with the '{resource_name}_id' in the decoded JWT token and also, check for valid issued at time and not blacklisted
Also, set “current_{resource_name}” method and “@current_{resource_name}” instance variable for accessing the authenticated resource
72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 72 def authenticate_token return unless decode_token @resource_name = set_resource_name_from_token(@resource_names) return if @resource_name.nil? resource = find_resource_from_token(@resource_name.classify.constantize) if resource && valid_issued_at?(resource) && !blacklisted?(resource) define_current_resource_accessors(resource) end end |
#current_resource ⇒ Object
101 102 103 104 105 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 101 def current_resource return unless respond_to?("current_#{@resource_name}") public_send("current_#{@resource_name}") end |
#decode_token ⇒ Object
Decode the JWT token and don't verify token expiry for refresh token API request
44 45 46 47 48 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 44 def decode_token # TODO: Set token refresh controller dynamic verify_token = (controller_name != 'tokens' || action_name != 'create') @decoded_token = decode(@token, verify_token) end |
#define_current_resource_accessors(resource) ⇒ Object
Defines “current_{resource_name}” method and “@current_{resource_name}” instance variable that returns “resource” value
60 61 62 63 64 65 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 60 def define_current_resource_accessors(resource) define_singleton_method("current_#{@resource_name}") do instance_variable_get("@current_#{@resource_name}") || instance_variable_set("@current_#{@resource_name}", resource) end end |
#find_resource_from_token(resource_class) ⇒ Object
94 95 96 97 98 99 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 94 def find_resource_from_token(resource_class) resource_id = @decoded_token[:"#{@resource_name}_id"] return if resource_id.blank? resource_class.find_by(id: resource_id) end |
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
19 20 21 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 19 def respond_to_missing?(method_name, include_private = false) method_name.to_s.start_with?('authenticate_and_set_') || super end |
#set_resource_name_from_token(resource_names) ⇒ Object
85 86 87 88 89 90 91 92 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 85 def set_resource_name_from_token(resource_names) resource_names.each do |name| resource_id = @decoded_token[:"#{name}_id"] return name if resource_id.present? end return nil end |
#valid_issued_at?(resource) ⇒ Boolean
Returns whether the JWT token is issued after the last password change Returns true if password hasn't changed by the user
52 53 54 55 56 |
# File 'lib/api_guard/jwt_auth/authentication.rb', line 52 def valid_issued_at?(resource) return true unless ApiGuard.invalidate_old_tokens_on_password_change !resource.token_issued_at || @decoded_token[:iat] >= resource.token_issued_at.to_i end |