Session Problem with Rails 3 - ruby-on-rails

I'm using Authlogic 2.1.6 for Authorization in Rails 3.0.5 and I have a session cookie problem with AJAX requests.
After a POST or PUT AJAX Call I'm getting a 401 Response and a new session key. After that every call will return a 401 response. Before the POST or PUT call every GET call succeeds.
This doesn't happen in test mode, only in development and production mode.
Does anybody know how to avoid that?
EDIT: I think there is a problem with the forgery protection authenticity key, because after disabling forgery protection everything worked fine.
This is a request header which will produce a 401:
Accept:*/*
Cache-Control:max-age=0
Content-Type:application/json; charset=UTF-8
Origin:http://localhost:3000
Referer:http://localhost:3000/
User-Agent:Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; de-de) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4
X-Requested-With:XMLHttpRequest
Rails Log entry is the following:
Started POST "/users.json" for 127.0.0.1 at Tue Apr 12 10:47:33 +0200 2011
Processing by UsersController#create as JSON
Parameters: {"user"=>{"password_confirmation"=>"[FILTERED]", "group_id"=>2, "lastname"=>"test1", "prename"=>"test1", "password"=>"[FILTERED]", "login"=>"test1"}}
Rendered text template (0.0ms)
Completed 401 Unauthorized in 19ms (Views: 0.9ms | ActiveRecord: 3.0ms)
EDIT2:
Next weird thing: I i send a BASIC AUTH Header instead of a cookie with session ID, I'm not getting a 401, very weird

A basic error with the 'forgery protection authenticity' is to forget adding the csrf_meta_tag
In your layout add it in your header tag. Without it no Ajax request is do with the good token.
If it's not with Ajax use the simple_form helper to generate the token in your form

Related

Error when creating tags with Gibbon (Ruby MailChimp client)

I have an issue when trying to create tags/segments with Gibbon, the MailChimp wrapper for Ruby.
I've been using Gibbon successfully for a large production site for 2 years, but need to move away from Merge Fields to tagging subscribers.
I can successfully add tags to a subscriber via Gibbon, but there are over 85,000 users that need to be transitioned and I really don't want to have to make 85,000 individual requests. There are 200+ possible tags, so I wanted to find all the users for each possible tag and then post the email addresses to the segment endpoint... so 200 requests, rather than 85,000.
The issue is that If a tag already exists (i.e. a test tag I created) in the list, then I get 400 error, Tag already exists and if the tag doesn't exist, I get 404 Resource Not Found. This is the same if I supply email addresses within static_segment or not.
I would expect the following to create a tag within MailChimp:
request = Gibbon::Request.lists(<list_id>)
request.tags.create(body: { name: "testing3", static_segment: [] })
However, I recieve the following error (which is the same if I use tags or segmentsin the request):
I, [2019-06-06T10:33:59.711436 #88340] INFO -- request: POST https://us15.api.mailchimp.com/3.0/lists/<list_id>/tags
D, [2019-06-06T10:33:59.711556 #88340] DEBUG -- request: User-Agent: "Faraday v0.15.4"
Authorization: "Basic <key>"
Content-Type: "application/json"
D, [2019-06-06T10:33:59.711605 #88340] DEBUG -- request: {"type":"http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/","title":"Resource Not Found","status":404,"detail":"Invalid path","instance":"<instance_id>"}
I, [2019-06-06T10:33:59.711779 #88340] INFO -- response: Status 404
D, [2019-06-06T10:33:59.711839 #88340] DEBUG -- response: server: "openresty"
content-type: "application/problem+json; charset=utf-8"
x-request-id: "<instance_id>"
link: "<https://us15.api.mailchimp.com/schema/3.0/ProblemDetailDocument.json>; rel=\"describedBy\""
vary: "Accept-Encoding"
date: "Thu, 06 Jun 2019 09:33:59 GMT"
content-length: "204"
connection: "close"
set-cookie: "_AVESTA_ENVIRONMENT=prod; path=/, _mcid=1.b9640bf1122e4a9b277bb19e3d72caf6; expires=Fri, 05-Jun-2020 09:33:59 GMT; Max-Age=31536000; path=/; domain=.mailchimp.com"
D, [2019-06-06T10:33:59.711878 #88340] DEBUG -- response: {"type":"http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/","title":"Resource Not Found","status":404,"detail":"Invalid path","instance":"<instance_id>"}
Gibbon::MailChimpError: the server responded with status 404 #title="Resource Not Found", #detail="Invalid path", #body={:type=>"http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/", :title=>"Resource Not Found", :status=>404, :detail=>"Invalid path", :instance=>"<instance_id>"}, #raw_body="{\"type\":\"http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/\",\"title\":\"Resource Not Found\",\"status\":404,\"detail\":\"Invalid path\",\"instance\":\"<instance_id>\"}", #status_code=404
from /Users/Paul/.rvm/gems/<gemset>/gems/gibbon-3.2.0/lib/gibbon/api_request.rb:134:in `handle_error'
Caused by Faraday::ResourceNotFound: the server responded with status 404
from /Users/Paul/.rvm/gems/<gemset>/gems/faraday-0.15.4/lib/faraday/response/raise_error.rb:8:in `on_complete'
I'm using the latest version of Gibbon 3.2.0.
When I byebug'ed inside of the Gibbon::APIRequest.post to see the path that was being generated I see the following:
(byebug) base_api_url
"https://us15.api.mailchimp.com/3.0/"
# For request.segments
(byebug) api_url
"https://us15.api.mailchimp.com/3.0/lists/<list_id>/segments"
# For request.tags
(byebug) api_url
"https://us15.api.mailchimp.com/3.0/lists/<list_id>/tags"
Any help would be much appreciated, as I'm really not sure what I'm doing wrong.
Thank you in advance.
Paul. :)
So for anyone else that might struggle with this, the Gibbon docs don't talk about Segments at all, but do reference tags, which I think is where some of my confusion make from.
request.tags should have been request.segments.
The other issue is that the request cannot be reused, so because I was performing the action inside a loop, by assigning request1 = Gibbon::Request.lists(<list_id>) and trying to use that for the second iteration, Gibbon forwarded the request to the wrong path and returned a 404 error.
Each request needs to be its own instance of Gibbon Request Gibbon::Request. So the following would work:
request = Gibbon::Request
#loop start
request.lists(<list_id>).segments.create(body: { name: "testing", static_segment: [] })
# loop end
Hope that helps someone else.
Gibbon::Request.lists(LIST_ID).segments.create(body: { name: "NAME", static_segment: [] })

API Endpoint only allows GET when it should take POST

I am building a React.js front-end portion of a web application using an already existing back-end that is built with ASP.NET MVC Framework. The method in the API's controller is named Post (which should default it to a post method) and even has the [HttpPost] decorator. I have recently enabled CORS, but I am not sure if that matters.
The API also has Swagger (it's like postman if you haven't used it before) enabled, and when I call the method as POST from the swagger, it will work and return the correct data.
However, when I try to call the method from my UI component, the API endpoint will give a 405 Method Not Allowed status code.
It says that the method only allows GET, which is baffling since it is supposed to only allow POST and it works that way on swagger or if I manually travel to the URL using a browser. Has anyone had a problem like this using React components or working with ASP.NET MVC/Web API 2?
I am completely stuck...
EDIT:
I am adding the API's method for the post endpoint.
[Route("{id}/merchant/SearchMerchants")]
[HttpPost]
[AuthorizeUserPermissionsToken(Cookie)]
public Response Post(Request rq)
{ // I put a breakpoint here to debug
// some code
}
I had to redact a lot of the code but here is the post method.
But I don't think it has to do with the API endpoint.
This is because when I debug, it will not even reach the breakpoint or call the method at all, when I am using the UI. However, it will reach the breakpoint when I travel to the endpoint on the browser or use swagger.
EDIT 2:
EDIT 3: (removed EDIT 2 and moved the original headers to bottom to reduce confusion)
Pre-flight OPTIONS request headers
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
Host: *redacted domain*
Origin:http://localhost:49702
Pragma:no-cache
Referer:http://localhost:49702/FindMerchants
User-Agent:Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Mobile Safari/537.36
response headers to OPTIONS request:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Origin:http://localhost:49702
Allow:OPTIONS, TRACE, GET, HEAD, POST
Content-Length:0
Date:Mon, 07 Aug 2017 18:41:42 GMT
Public:OPTIONS, TRACE, GET, HEAD, POST
Server:Microsoft-IIS/10.0
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
then the real POST request headers after pre-flight:
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:154
Content-Type:application/json
Cookie: *redacted a bunch of cookies*
Host:a *redacted domain*
Origin:http://localhost:49702
Pragma:no-cache
Referer:http://localhost:49702/FindMerchants
User-Agent:Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Mobile Safari/537.36
The real response headers are like so:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Origin:http://localhost:49702
Allow:GET
Cache-Control:no-cache
Content-Length:73
Content-Type:application/json; charset=utf-8
Date:Mon, 07 Aug 2017 17:58:28 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/10.0
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
EDIT 4:
Request URL:*redacted domain*/380/merchant/SearchMerchant
Request Method:POST
Status Code:405 Method Not Allowed
Remote Address:127.0.0.1:80
Referrer Policy:no-referrer-when-downgrade
EDIT #9999 (jk):
My react component simply calls a custom data service that I wrote, which has a post method like this.
post(relativeUrl, data, apiVersion) {
var url = this.getUrl(relativeUrl, apiVersion);
var res = $.ajax({
type: 'POST',
url: url,
contentType: 'application/json',
xhrFields: {
withCredentials: true
},
crossDomain: true,
data: JSON.stringify(data)
});
return res;
}
I simply pass relativeUrl to fetch a list related to a user account.
Before I make a call that fails (which shows 405), I use this same method to log in and update the global redux state for the app. After updating the global state, I render a different component and use this method again with another relativeUrl to fetch the list. Then I get the error. I also make sure that the login call is finished and returns and updates the state correctly before moving on.
To follow my comment,
in web.config file:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS, HEAD" />
</customHeaders>
</httpProtocol>

Server App on Heroku is not accessibe

Hi we have a Ruby on Rails server application on Heroku, but when I send a post request to it, I always get a 400 Bad Request response. I have searched other 400 errors, but none are related to our issue. The HTTP response that we receive looks like this below:
HTTP/1.1 400 Bad Request
Server: Cowboy
Date: Fri, 14 Aug 2015 21:55:25 GMT
Content-Length: 0
The post request that I am sending looks like this below:
POST http://ourapp.herokuapp.com/api/v1/requests HTTP/1.0
Accept-Language: en-us
Accept: text/plain
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
Connection: Close
request=600&key=&newKey=danasecretkey&
Sorry, I had to put blank lines after each header or it would all show up on one line.
If I create an HTML form to send the data, there is no issue. It's when I then try to send the same request from our file server, that I get the errors. I tried using a preflight request with all of the correct request headings, but received the same 400 Bad Request error.
Does anyone have any suggestions as to what I might be doing wrong?
Well, just guessing from what you've said:
request=600&key=&newKey=danasecretkey&
It's likely that you have something like params.require(:key) in your controller. And your request is missing that parameter.
Rails will respond with 400 status in case you missed some require'd params.
What fixed it was switching from HTTP1.0 to HTTP1.1, adding the host header and changing the uri.
The logs didn't tell us anything, and the params were ok. The problem was not fully grasping the HTTP header requirements.

Rails Controller Processing as */* (star slash star) rather than JSON

I am sending http post with JSON data from an iphone app to a Rails app. I am sending the password reset email to devises' password controller. I've set my header for content-type as application/json.
The server log says:
Started POST "/users/password" for 192.168.0.11 at 2013-05-13 20:04:27 -0700
Processing by PasswordsController#create as */*
What does it mean when it says "star slash star"? How do I make it process as Json?
*/*

Params variable not getting filled with JSON post data....Why?

I had this service working before, with some other fields, but right now i seem not to get it working, and am not quite getting why.
I'm posting the following json to my Rails app (with RestClient 2.4, for the test) :
{
"camp":{
"total": 100,
"number": "epw1f6e"
},
"machine":{
"serial_number": "1234567",
"token": "fONxDN"
}
}
Camp controller :
def create
if is_it_json?
logger.debug params.inspect
machine = Machine.find_by_serial_number(params[:machine][:serial_number])
...
From the logger, I get that params are : {"action"=>"create", "controller"=>"camp"}
Where is the json information??
My log error :
Started POST "/camps" for 127.0.0.1 at 2012-07-15 00:08:21 +0100
Processing by CampsController#create as JSON
WARNING: Can't verify CSRF token authenticity
{"action"=>"create", "controller"=>"camps"}
Completed 500 Internal Server Error in 2ms
NoMethodError (undefined method `[]' for nil:NilClass):
app/controllers/camps_controller.rb:24:in `create'
What might i be doing wrong?
Thank you
After a lot of reading and questioning, i just found out the solution :
The params weren't getting filled because i was missing Headers (I had the Accept, but was missing the Content-type) :
Accept: application/json
Content-type: application/json
Adding the headers solved this issue.
Can't verify CSRF token authenticity {"action"=>"create", "controller"=>"camps"}
Completed 500 Internal Server Error in 2ms
That error is thrown when an invalid (or nonexistent) CSRF token is posted with your json. The CSRF needs to be attached to the header of any posted data. For testing you can disable CSRF tokens by adding the following to your controller (for Rails 3):
protect_from_forgery :except => :create
Do not leave that in your controller when the site goes into production. CSRF tokens prevent CSRF attacks. Refer to the Ruby on Rails Security Guide for more details.
Let me know if that does the trick!

Resources