Is there any way to encode the URL at runtime in rails? - ruby-on-rails

In my rails application, I have search functionality. A user may directly enter a search string in the URL. If the user enters a search string as '%', the URL becomes:
http://localhost:3000/search/%
and that produces Bad Request error. Is there any option to encode the URL at runtime?

The question you're asking wouldn't actually solve the problem you're describing. Yes, Rails can encode a URL at runtime, in fact it encodes many URLs at runtime in its normal operation.
But, that won't help you, basically what's happening is that when your users create a URL with a % in it, they're actually creating an invalid URL - not just for Rails, but for any web server, or web application server or framework.
If you look closely at the error that you get returned in the browser, it's not even from Rails, it's from WEBrick (or whatever httpd you're using), same with the error that will be logged to your logs, it's not a normal Rails error in the Routing or elsewhere.
The upshot of all this is that no, you can't handle this in Rails because in many cases it won't even get through to Rails, and it's just a totally invalid URL.

Related

Filtering route parameters

So I have a route in routes.rb like:
get "example/:token" => "example#example"
and even though I have config.filter_parameters += [:token] in production.rb, I still get a log output like:
Started GET "/example/fjiaowevnieninr3"
Parameters: {"token"=>"[FILTERED]"}
where as you can see "token" is filtered in the Parameters, but still appears in the URL path. I'd always assumed filtered_parameters would filter it there as well but I guess not. Is there an official way to filter out named route parameters like this from the logs?
In general it depends on why do you need this kind of behaviour. allenbrkn answer is correct you can send it through query string and it will be filtered from the query string. That said there are more things to consider when you are trying to do this.
There are more type of logs
In the production environment you use some webserver like Apache or Nginx, they have their own access logs, in which they log some headers, paths with query strings and so on (it is configurable).
It means that even if you filter out URL token from the rails log, they will probably appear in the webserver access logs.
Also don't forget these parameters can be sent to external services eg. exception tracking or performance tracking softwares.
Things in the URL are public
Tokens in the URL should not be considered as a secret. Your user can see them manipulate them, send the url to anyone or randomly show it to someone.
I think there two main reasons to put the token into the URL
Hard to guess URL
User authorisation
Hard to guess URL
In this case token is always the same. It is not changed with every access of the URL. It can be usually used as an ID of some resource or something.
For example we are using it as public URLs for invoices so we can send just a link to our clients and they can download the PDF from our site and there are some things to help them with the payments. In the URL is some token so they cannot guess the URL and access invoices of other clients. The token is always the same, so they can access the invoice from the email several times. And the URL is still in the rails log and server access log and we are fine with it because we know the tokens anyway - they are part of the invoice ID.
In these cases it also helps you with the debugging. If some exception kicks in or if there is some issue with the resource it will be really hard to find out why.
User authorisation
This is a bit more complicated. When it comes to authorisation you shouldn't put your tokens into the URL. They should always be in the body and filtered out of the log or in the authorisation headers. Unfortunately sometimes you don't have much of a choice if you need to use it during the GET requests eg:
Single sign on (redirect flow)
Password reset
etc
(Of course you can use request body even with GET requests but you are risking to loose the data eg if the user puts in the URL manually etc)
In these cases you should make possible exposition to valid tokens as short as you can:
Always issue new token on demand never reuse same tokens
Work with very short expiration times
Every token should be invalidated immediately after its use
With these rules it should not matter whether they appear in the logs or not.
For example we have single sign on implemented in our application. The valid token is issued only on demand with 1 minute expiration time and it is invalidated immediately when it is used. In this case it can appear in the log because at the time of appearance it is already invalid and useless.
With password reset it can be a bit more complicated you need token to be valid at least tens of minutes probably and it will appear in the log before it is invalidated. But there are probably not too many things you can do about it - btw if someone has some good ideas I will be very happy to read it.
Conclusion
You can filter the tokens from rails logs but they still probably appear in other logs or even other services if you use them. You should work with your tokens in the URL as if they can appear there and make it as safe as possible for you if they do. Rails log is just one piece of puzzle you have to consider.
As far I know, there is no in-built way of filtering the URL like GET /example/[FILTERED]. But you can create your own method to do that.
After a little examining of https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/filter_parameters.rb file, I found that filtering params will also filter the query_string of the path.
For example: In your case above, if you make a request to /example/fjiaowevnieninr3?token=fjiaowevnieninr3, the result in logs would be:
Started GET "/example/fjiaowevnieninr3?token=[FILTERED]"
Parameters: {"token"=>"[FILTERED]"}
So I would suggest you to send your token as a query parameter and do something like this:
In your routes add:
get "example/auth" => "example#example"
Then you can make a request like /example/auth?token=123456
You can catch this token in controller with params[:token]
This way your logs will show:
Started GET "/example/auth?token=[FILTERED]"
Parameters: {"token"=>"[FILTERED]"}
Also, config.filter_parameters is moved from config/application.rb to it's own file at config/initializers/filter_parameter_logging.rb file.
Add the token symbol to your config/initializers/filter_parameter_logging.rb:
Rails.application.config.filter_parameters += [:password, :token]
Also, don't forget to restart the server.

Rails links in mailer are invalid (Liquid gem)

There are template witch are written by admins. And in mail there possibility to enter link (not the rails way). There is editing menu, what generates following, basic html code:
company’s profile
where user.owner_name - domain.com/user/user_name
I don't talk about localhost because it possible will not work. So I'm talking about production server.
I receive email, with broken link (if I click on it - it's not opening) but if copy link:
x-webdoc://73A3A2DC-F22E-4558-8853-C6A57985EE7C/mydomaine.com/user/
Why this appears?
EDIT
It seems it's realeted to MacOs. It prbolem appears when I view letter thorought Mail App, or Safari browser.
Now, I need any advise how to avoide this prob.
I would argue that example.com/user/user_name is not a useful URI in the context of an email, because it is missing a protocol (like: http://example.com/user/user_name). Without the protocol it could be misunderstood as a relative URL, which may lead to security issues or at least is useless in the context of an email client.
From that point of view, it is not surprising to me that some email clients or web mailers are trying to be smart and protect the user by annotating the URL in some way.
In this example the added x-webdoc: indicates that the user has to make the decision on what application to use to open that link because without a proper protocol it is not obvious what application will be able to handle the URI. See What is x-webdoc?

url encoding for every request and response in ruby on rails?

i did some google to know about url encoding but, i didn't found any exact solution for my problem so i am posting it here.
I need to encode each and every request for my entire rails applications. the reason for this is i am passing some id in the url which needs to be encrypted for the user.
i couldn't get any Gems or common library for that. please guide me with your solution or direct me to the right path.
resource that i feel similar through:
url encode equivalent in ruby on rails

Any relation between emberjs route and rails route

One project based on emberjs and rails.
When redirect to localhost/#lessons/2, the page works
when redirect to localhost/practices/2#/lessons/2,
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
so what's the difference between 'localhost/#lessons/2' and 'localhost/practices/2#/lessons/2'
If want to make 'localhost/practices/2#/lessons/2' works, how to set emberjs route?
so what's the difference between 'localhost/#lessons/2' and 'localhost/practices/2#/lessons/2'
Difference is the /practices/2 part. That's part of the url's path. By default ember will ignore that, it's just paying attention to the hash, which in bot cases is lessons/2.
Like firefox says, seems like the server is redirecting the request.
If want to make 'localhost/practices/2#/lessons/2' works, how to set emberjs route?
Hmmm... that url implies that server/rails is responsible for rendering practices/2 and that you have an ember app on the practices/2 page which should be rendering lessons/2? It's possible but that sounds like a very complicated setup. I'd be surprised if that's what you really want. Probably instead you will want to have localhost/#practices/2/lessons/2. With that setup just use normal ember routing as described here: http://emberjs.com/guides/routing/defining-your-routes/

Rails POST doesnt extract any path, query or request parameters

I want to grant users access to my API (hosted on heroku.com) from their sites.
But a strange problem occurs, when i want them to allow to post to the api:
Data sent from an correct form with the correct action-url (e.g. "http://myapp.com/projects/123/tasks/321/todos") - the params get serialized and send via jQuery - i encounter an "ActionController::MethodNotAllowed" with the additional info: "Only get and post requests are allowed", that re-routes to ApplicationController#index with :method => :options.
Rails doesnt extract the params for project_id (123) and task_id (321) from the url, neither are any further request_parameters, path_parameters or query_parameters available.
This behaviour occurs, when I POST from external sites, but doesn't occur, when posting from an html-page on my local machine. My first thought was about wrong encoding, but how to fix that problem.
Edit:
I am using authlogic (not devise :-D) and for the :create action the protect_from_forgery is already skipped.
Any suggestions appreciated
i guess that happens because rails tries to protect your form CSRF attacks.
you can comment out the protect_from_forgery line in your ApplicationController to test it.
but im not sure if thats the right way of dealing with this issue in the production environment.
Okay. I'll try and answer the right question this time (see other comment).
So I've thought about this, and I'm wondering, is this a case of the jQuery call attempting a PUT request? When you use the local form Rails will POST the data, but add the extra _method field to emulate a PUT.
Don't know if you are using jquery-rails, but this takes care of setting the _method parameter, and the PUT/POST verb translation for you in your AJAX calls.
The problem occured due to the cross domain policy - the request was made from another domain - and because I was using a recent browser that supports CORS, it was sending an OPTIONS-request first to get known from the server, which actions are allowed for this domain.

Resources