JWT validation in rails requests - ruby-on-rails

I have authentication service using
Json Web Token
in my Rails API.
I want to check if Token is valid in every request my API gets.
Problem is that when i write function which checks if Token is valid in main
application_controller.rb
file it is not visible in engines and i can't do before_action for every engine i have. is there any way to validate Token in every request my application gets in every engine?

You can create a .rb file under config/initializers
class ActionController::Base
before_action :validate_jwt_token
def validate_jwt_token
# validate jwt token
end
end
This will make sure validate_jwt_token is executed on every request among all of the mounted engines.
Edit:
You can also put this code under Api engine or Umg's engine.rb
module Api
class Engine < ::Rails::Engine
#...
initializer 'api.jwt_token_validation_helper' do
ActionController::Base.send :include, Api::JwtTokenValidationHelper
end
end
end
module Api
module JwtTokenValidationHelper
extend ActiveSupport::Concern
include do
before_action :validate_jwt_token
def validate_jwt_token
puts 'your code here'
end
end
end
end

Related

Facing the NameError when trying to include concerns in my rails 6 controller

I am trying to create a small project for practising the API Key Authentication using the this tutorial. I have created a concern in following directory of the rails project.
app/controllers/concerns/api_key_authenticable.rb
module ApiKeyAuthenticatable
extend ActiveSupport::Concern
include ActionController::HttpAuthentication::Basic::ControllerMethods
include ActionController::HttpAuthentication::Token::ControllerMethods
attr_reader :current_api_key
attr_reader :current_bearer
# Use this to raise an error and automatically respond with a 401 HTTP status
# code when API key authentication fails
def authenticate_with_api_key!
#current_bearer = authenticate_or_request_with_http_token &method(:authenticator)
end
# Use this for optional API key authentication
def authenticate_with_api_key
#current_bearer = authenticate_with_http_token &method(:authenticator)
end
private
attr_writer :current_api_key
attr_writer :current_bearer
def authenticator(http_token, options)
#current_api_key = ApiKey.find_by token: http_token
current_api_key&.bearer
end
end
In my Controller, I am trying to include the concern like this
app/controllers/ApiKeysController.rb
class ApiKeysController < ApplicationController
include ApiKeyAuthenticatable
# Require token authentication for index
prepend_before_action :authenticate_with_api_key!, only: [:index]
# Optional token authentication for logout
prepend_before_action :authenticate_with_api_key, only: [:destroy]
def index
end
def create
end
def destroy
end
end
But when I run the server and visit the index action of the controller, I get the following error
NameError (uninitialized constant ApiKeysController::ApiKeyAuthenticatable):
app/controllers/ApiKeysController.rb:10:in `<class:ApiKeysController>'
app/controllers/ApiKeysController.rb:2:in `<main>'
Can anybody help me out to fix this issue?
Author here. Your concern’s filename is authenticable but your module is authenticatable. You’ll need to correct the typo in the concern filename.

Globally have access to session in rails

Is it possible to use the session variable inside of an ordinary .rb file except from the controller?
I'm using this facebook messenger rails gem to build a bot. All requests come to app/bot/listen.rb. In that listen.rb file:
require "facebook/messenger"
extend ActionView::Helpers # I need also the session
include Facebook::Messenger
Bot.on :message do |message|
session[:demo] = 1
puts "Your session number is: #{session[:demo]}"
end
Module::DelegationError (ActionView::Helpers::ControllerHelper#session delegated to controller.session, but controller is nil: main)
Is it possible to store data in session from within that listen.rb file?
The UserInfo module encapsulates reading and writing the User object from/to the Thread local. This module can then be mixed in with other objects for easy access.
module UserInfo
def session
Thread.session
end
def self.session=(session)
Thread.session = session
end
end
A before_filter set in the ApplicationController will be called before any action is called in any controller. You can take advantage of this to copy a value out of the HTTP session and set it in the Thread local:
class ApplicationController < ActionController::Base
before_filter :set_user
protected
# Sets the current user into a named Thread location so that it can be accessed by models and observers
def set_user
UserInfo.session = session[:user]
end
end
At any point in a Model class that you need to have access to those values you can just mixin the helper module and then use its methods to access the data. In this final example we mixin the UserInfo module to our model and it will now have access to the current_user method:
class Account < ActiveRecord::Base
include UserInfo
after_update :log_audit_change
private
def log_audit_change
Audit.audit_change(current_user, self.id, self.new_balance)
end
end

How to create api documentation using apipie outside the controller

I am using apipie for API documentation.
The problem I am facing now is that the large amount of information to be provided for documentation is ruining my code structure in the controller.
How can I write the documentation outside the controller file,
so that the code structure will be readable?
You can find nice explanation on how to use apipie outside controller in this document https://ilyabylich.svbtle.com/apipie-amazing-tool-for-documenting-your-rails-api
To sum things up (example from link):
# app/docs/users_doc.rb
module UsersDoc
# we need the DSL, right?
extend Apipie::DSL::Concern
api :GET, '/users', 'List users'
def show
# Nothing here, it's just a stub
end
end
# app/controller/users_controller.rb
class UsersController < ApplicationController
include UsersDoc
def show
# Application code goes here
# and it overrides blank method
# from the module
end
end
super also needs to be included in the stubbed actions in the docs. In my app I created a controller that inherits from an existing controller defined in a gem, and if I don't include super in the stubbed action, I get unexpected behavior.
So:
# app/docs/users_doc.rb
module UsersDoc
# we need the DSL, right?
extend Apipie::DSL::Concern
api :GET, '/users', 'List users'
def show
super
end
end
# app/controller/users_controller.rb
class UsersController < ApplicationController
include UsersDoc
def show
# Application code goes here
end
end

Adding params to redirect_uri in oAuth DoorKeeper

I am using DoorKeeper gem to create API from my Rails app. By default, DoorKeeper will return to my client's url with a param code="123" as follow:
http://localhost:3001/api/callback?code="123"
I would like to pass additional params, i.e., user_id and token as follow:
http://localhost:3001/api/callback?code="123"&user_id="3"&token"abc"
Is it possible with DoorKeeper?
I think you'd be off OAuth2 spec with this. Most consumers would use a lib for OAuth2 and then this wouldn't be supported.
You are supposed to provide those values in an API that the other service can call when it's got the access_tokens
module API
module V1
class UsersController < ApplicationController::Base
respond_to :json
def show
respond_with User.find(doorkeeper_token.resource_owner_id).some_info_as_json
end
end
end
That's the OAuth2 way and we both may not like it too much:) What did you end up doing?

getting comatose working with authlogic

I started using comatose to handle content on my site but am having problems using it with my existing authentication using a generic Authlogic config.
In the readme he sites an example for configuring it with Restful Authentication and I'm wondering how I would do the same within a general Authlogic setup?
#environment.rb
Comatose.configure do |config|
# Includes AuthenticationSystem in the ComatoseController
config.includes << :authenticated_system
end
http://github.com/darthapo/comatose
I think a better way to do it is moving the auth methods out into a module, and include that from both ApplicationController and comatose. Example:
Put your auth methods into user_sessions_helper:
module UserSessionsHelper
module AuthMethods
private
...
def require_user
...
Then include the module in your ApplicationController:
class ApplicationController < ActionController::Base
include UserSessionsHelper::AuthMethods
...
And finally in the comatose config as well (environment.rb):
Comatose.configure do |config|
config.admin_includes << "UserSessionsHelper::AuthMethods"
config.admin_authorization = :require_user
end

Resources