Rails API Devise JWT disable sessions store - ruby-on-rails

I'm using Rails 7 API only and gem devise-jwt to authentication. Firstly, this is tutorial to setup: https://dakotaleemartinez.com/tutorials/devise-jwt-api-only-mode-for-authentication/
It has a trouble, when i call API register new account, it shows a error: Your application has sessions disabled. To write to the session you must first configure a session store
I try to fix this issue (Add session store configuration into the application config)
config.session_store :cookie_store, key: '_rails7_api_session'
config.middleware.use ActionDispatch::Cookies
config.middleware.use config.session_store, config.session_options
=> It worked, but i faced with the second trouble. I defined a "/me" route to get current user. In theory, I need to pass the Authorization parameter on the header to be able to get the current user data (I'm using Postman). But somehow (Probably because of session) I get the user data without the Authorization parameter on the header.
I want to fix this issue. Somebody can help me, please?

In the related /me controller, have you put
before_action :authenticate_user! in the controller?

Related

Using token from Simple authentication Token in controller

I am using Simple Authentication token for my APIs in Rails.
As given in the documentation: https://github.com/gonzalo-bulnes/simple_token_authentication:
In my User model, I have added the following line:
acts_as_token_authenticatable
Whenever I login or logout, I am able to get and change the athentication tokens as expected.
What I don't understand is, what is the use of the below line.
acts_as_token_authentication_handler_for User
I have a controller called ProfilesController in which I have added this line. Whether or not I add this line in the controller makes no difference. I am able to call methods in the similar way as I use without adding it.
Can you please explain me what this does?
That is because that gem says this behaviour of incorrect or no credentials is configurable.
What happens when a request is provided with no credentials or
incorrect credentials is highly configurable
For denying access you have to set the fallback
If you have devise set it to fallback: :devise or fallback: :exception in your app/controllers/application_controller.rb

Apartment current_tenant resets to 'public' after failed devise login

I use Devise for authentication and Apartment for multi-tenancy support on a SAAS app.
After a failed login, devise "redirects" to the login page (Users::SessionsController#new) and the value of Apartment::Tenant.current which was previously set in a TenantElevator middleware goes back to its default value of "public".
This is happening because Devise isn't actally redirecting to the login page but calling the FailureApp (which renders the login page) with a new rack env and returning its response. The new rack app doesn't have TenantElevator middleware so the tenant isn't set within the rack app.
Does anyone have any idea how to fix this? Maybe a way I can add the TenantElevator middleware to the Failure app?
Just stumbled on this and figured providing an answer may be useful for someone.
Haven't encountered this issue in a while, but looking through the sourcecode of the app I was working on, I fixed this issue by simply modifying where the apartment's middleware is inserted i.e modifying the order of the middleware.
Add the following snippet at the very bottom of your apartment.rb initializer file which should be located at app/config/initializers/apartment.rb
Rails.application.config.middleware.insert_before ActionDispatch::ShowExceptions, Apartment::Elevators::Domain
Essentially, insert your middleware before the ShowExceptions middleware, this ensures Devise, and ShowExceptions middleware, always runs under/within the context of the tenant set by whatever TenantElevator your app uses.
There may currently be a better way to handle this -- I am not sure, but this was the best option I found back when I had this issue.

Using devise_token_auth with jsonapi-resources

I am trying to use devise_token_auth with jsonapi-resources. I have it set up where I can create users and sign in, but I cannot figure out how to access a controller that has needs to authenticate a user first. Here is my controller that I am trying to require authentication:
class FriendsController < JSONAPI::ResourceController
include DeviseTokenAuth::Concerns::SetUserByToken
before_action :authenticate_user!
end
When I try localhost:3000/friends, I get a 401 "Authorized users only." error, so I think it works. I think my main problem is Im not sure what to do with the access-token I get when I sign in. I have tried setting it in the header in my request, but still get the same "Authorized users only" error.
Better a late answer than none... devise_token_auth and jsonapi_resources work pretty well for me in a test setup. But, you need to set the request header correctly. It is not enough to transmit the "auth-token" header, you also heave to transmit the "client" token, the "uid" and the "token-type" header as well. Although I'm not entirely sure if the latter is actually required.
Devise token authentication is quite independent of jsonapi-resources. If you can get token authentication working (as explained in this answer, for example: Custom devise api token auth) you can simply extend your controller (or your ApplicationController) with the authentication concern and it should behave as a normal Rails controller would.

Turn on request forgery protection with or witout Rails's protect_from_forgery?

I building a REST API based on Rails 4.
To prevent from cross-site request forgery attacks, I added a CSRF token inside a custom HTTP header that is needed to perform requests such as POST, DELETE, etc.
I know Rails 4 also provides a protect_from_forgery method with a special option for APIs: with: :null_session.
So I think that, given it's a best practice, this new Rails method should be present at the top of my ApplicationController.
But in the same time, I'm also wondering why I should add it... if it is not necessary. Because as I said, my requiring a CSRF token inside a custom HTTP header.
Could you give me the benefits of adding this Rails feature? Thanks a lot.
protect_form_forgery just adds a before action to the controller which checks if the authenticity_token is valid.
The :with parameter specifies how the controller should behave if the token is invalid.
with: :exception: raises an exception in the controller which can by catched.
with: :null_session: resets the session itself. This means the complete session will be deleted. In other words the session cookie will be reset. For example an user_id stored in the session won't be available anymore (puts session[:user_id] # => nil). So you always have to provide a token or any other authentication, which is perfectly fine for an API.
You can also remove protect_from_forgery if you don't use session.

Devise throwing HTTP auth on XHR and logging out

I'm having a ton of issues with Devise, using OmniAuth, to authenticate my Rails app. I relaunch my server and open up a new tab in Incognito mode (so that the cookies are cleared) and load my app. I log in, and then go through to the app.
When I get to a page that calls an authenticated action via AJAX, it asks for a username and password via HTTP Basic Authentication. I've disabled this in my devise.rb.
config.http_authenticatable = false
config.http_authenticatable_on_xhr = false
When I then go back to a previous page, it redirects me to the login page and asks for a login. This also happens when I visit a page that doesn't require authentication and then go back to an authenticated page.
This is getting immensely frustrating. I've unpacked Devise and Warden to my vendor/gems directory so that I can try to debug it, but I honestly can't figure out where to begin. Any help would be hugely appreciated.
Your AJAX call probably isn't setting the CSRF token. You might need to update your UJS gem (jquery-rails probably) or manually set the X-CSRF-Token HTTP header to the value of the tag. See this question: Devise session immediately expiring on .js call [AJAX]. You can test if this is the problem by disabling CSRF protection temporarily by chucking config.allow_forgery_protection = false in config/application.rb.
If you go the manual route, you should probably grab the value of the 'authenticity_token' meta tag first, and use that as the name of the actual token meta tag, rather than hard coding the reference to 'csrf-token'.
I would recommend updating to Rails 3.0.10 or 3.1 if you can. I was still having problems on 3.0.7.

Resources