2

I have a simple web app built with rails using devise for user log in. At the moment a user can sign up, sign in and sign out, and make new posts when signed in. Eventually I plan to make this api consumable via a mobile app and my first step in understanding the process is to use a CURL command to log in. I am having some problems.

Here is the CURL command:

curl -H 'Content-Type: application/json' -X POST http://localhost:3000/users/sign_in -d '{"user": {"email":"test@test.com", "password": "password"}}' -c cookie

Here is the controller code:

class Api::PostsController < ApplicationController

  skip_before_action :verify_authenticity_token
  before_action :authenticate_user!
  # protect_from_forgery with: :null_session

  def index
    render json: Post.all 
  end

  def show
    post = Post.find(params[:id])
    render json: post
  end

  def create
    post = Post.new(post_params)
    if post.save
      render status: 200, json: {
        message: "Successfully created post",
        post: post
        }.to_json
    else
      render status: 422, json: {
        errors: post.errors
      }.to_json
    end
  end

  def destroy
    post = Post.find(params[:id])
    post.destroy
    render status: 200, json: {
      message: 'Successfully deleted post'
    }.to_json
  end

  private

  def post_params
    params.require("post").permit("city", "country", "image", "lon", "lat")
  end

end

Here is the error I am getting from the server:

 Processing by Devise::SessionsController#create as */*
  Parameters: {"user"=>{"email"=>"test@test.com", "password"=>"[FILTERED]"}, "session"=>{"user"=>{"email"=>"test@test.com", "password"=>"[FILTERED]"}}}
Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 20ms (ActiveRecord: 0.0ms)

As you can see I've included the skip_before_action :verify_authenticity_token code to skip the CSRF token check, however this check seems to be taking place in the SessionsController.

Do I need to add this line of code elsewhere? I am still new to Rails/Devise, so please forgive my lack of knowledge.

Phil Brockwell
  • 456
  • 5
  • 22

1 Answers1

0

Devise is a Rails engine, so it has its own set of controllers which do not inherit from ApplicationController. To make the override work, you need to make controllers in your app that inherit from the devise ones, then tell Devise to use those instead of the default ones. This how-to on the Devise wiki might help.

Having said that, the CSRF protection is there for a reason, and if you disable it, the users logging in via the web browser will no longer be protected, which is a really bad idea. A better way to do this would be to have a proper mechanism for logging in via the API which is different from the web GUI. There is a :token_authenticatable module that will help here, and a good guide to using it here.

However... the Platformatec guys who make Devise have removed :token_authenticatable from the core as they say it is not 100% secure (see this blog post). There is a good Stackoverflow question here explaining the issues and suggesting some better ways to implement things.

Hope that throws some light on things.

Matt Gibson
  • 14,616
  • 7
  • 47
  • 79