I am using Ruby on Rails 3 and I would like to know how to handle the AuthenticityToken value using a HTTP POST request from a RoR application to another RoR application. In this case I aim to submit a sign in form and return the user information in JSON format if he\she provided correct email
and password
values.
I have a RoR application at this URL
pjtnam.com
and another RoR application at this URL
users.pjtname.com
If I make an HTTP POST request from the application pjtname.com
to the application users.pjtname.com
like this (in this example I use the Typhoeus gem)
response = Typhoeus::Request.post("http://users.pjtname.com/authentications",
:params => {
:new_authentication => {
:email => email,
:password => password
}
}
)
I get this response
<h1>
ActionController::InvalidAuthenticityToken
in AuthenticationsController#create
</h1>
<pre>ActionController::InvalidAuthenticityToken</pre>
So, how to handle the AuthenticityToken value in a safe approach\mode? I would like to know in both when applications are located on the same server and when they aren't.
At http://users.pjtname.com/authentications/new
I have the following form for signing in users:
<%= form_for(:new_authentication) do |f| %>
<%= f.label :email %>
<%= f.label :password %>
<%= f.submit "Sign in" %>
<% end %>
In the authentications_controller.rb I have
def create
# Note ':authentication' symbol is different than ':new_authentication' seen in HTTP POST parameters and in the above form
@authentication = Authentication.new(params[:authentication])
@account = Account.sign_in_account(params[:new_authentication][:email], params[:new_authentication][:password])
...
respond_to do |format|
format.html {
redirect_to @account
}
format.js {
render(:update) { |page|
page.redirect_to @account
}
}
format.json {
render :json => @account
}
end
end
In routes.rb I have
resources :authentications do #, :path => "authentication" do
member do
get 'confirm_authentication'
post 'confirm_authentication'
end
end
UPDATE for the @idlefingers answer
REQUEST
Typhoeus::Request.post("http://users.pjtname.com/authentications/new",
# or
# Typhoeus::Request.post("http://users.pjtname.com/authentications",
:headers => {"Content-Type" => "application/json"},
:params => { ... } # Same parameters as above
}
)
RESPONSE
<h1>
StandardError
</h1>
<pre>Invalid JSON string</pre>
REQUEST
Typhoeus::Request.post("http://users.pjtname.com/authentications/new.json",
:params => { ... } # Same parameters as above
}
)
RESPONSE
<h1>Routing Error</h1>
<p><pre>No route matches "/authentications/new.json"</pre></p>
It looks like it's not sending the request with the correct content type. Rails should skip the authenticity token check if the content-type is application/xml or application/json, so that it plays nice with APIs without having to disable the authenticity token altogether.
I don't know the Typhoeus gem, but it looks like you may need to just add ".json" or ".xml" to the url (depending on the API you've implemented), or may need to pass it in as options in the headers hash.