Can I pass a param to the next routed URL? - ruby-on-rails

If a url is localhost:3000/rooms/:token has a key in the params at this point named :token,
in the #show method in the controller I can ```params.merge!({ dev_paramater: 'hello'}) that would be present in the params when calling localhost:3000/rooms/:token, but when I go to localhost:3000/rooms/:token/chats the dev_parameter key disappears from params.
I would like to use data in the dev_parameter, I basically want it to persist if I visit deeper routes.

params is provided by the controller according to the request content when requests are received, they are independent in each requests. (BTW, params should not be modified in most cases.) If you need carry some information between requests, consider using session or cookies instead.
Rails guide:
session - https://guides.rubyonrails.org/action_controller_overview.html#session
cookies - https://guides.rubyonrails.org/action_controller_overview.html#cookies

Related

How param works in rails views

I have an old app running in rails 2.3.5
In customizing, I stuck when i find a param keyword being used in views
i.e in views I can see stuffs like
unless params[:fee_collection].nil?
can someone explain to me in what context is param keyword used in rail views rather than controllers
params is a hash that contains parameters sent with the HTTP request.
You can access to this object as well from your controller or from a view. Although, the convention is to access to an instance variable (defined in your controller, e.g : #fee_collection = params[:fee_collection]) from your view.
The params variable stores a hash which contains the http parameters received in the request to this route (controller#action)
If you have a UserController with the show method, you should receive the param[:id] to identify the resource you're looking for.
If you want to send parameters, it would be either via url in a GET or a data payload on a POST request, on the most common cases.

Get raw parameter data in Ruby on Rails

I have a ruby on rails api where I want to sign my request data by appending a hashed version of all passed in parameters to the request and rebuild this one at the server side as well to validate the integrity of the requests.
When I simply use the params method in the controller I have different parameters (e.g. for an update-method which is specified by this:
put 'login' => 'login#update'
I get as parameters on the server:
{"timestamp"=>"1399562324118", "secured"=>"xxx",
"login"=>{"timestamp"=>"1399562324118", "secured"=>"xxx"}}
although I only send the request from the client with
{"timestamp"=>"1399562324118", "secured"=>"xxx"}
Does any one have an idea how to get rid of this "login" parameter in the params list in a generic way? I do not want to exclude this for every single request of my api.
Thanks a lot!
Per the Rails Edge guide on ActionController:
"If you've turned on config.wrap_parameters in your initializer or calling wrap_parameters in your controller, you can safely omit the root element in the JSON parameter"
See http://guides.rubyonrails.org/action_controller_overview.html#json-parameters

Rails 3 - is link_to with parameters secure?

As a general rule of thumb you aren't supposed to trust any input of data from users. If you had a simple link_to with a parameter:
link_to "Click me", test_path(:my_param => "test")
The route might look like: example.com/test?my_param=test
How do I know if the param, or any injected data for that matter, is being filtered properly? The Rails 3 API doesn't specify that it filters data that is passed to the controller, but I want to make sure that the params[:my_param] is filtered securely in the controller before I utilize the params data.
Any thoughts?
Rails framework doesn't secure things by default for GET request. link_to tag is sending a http get request.
If it is a POST/PUT/DELETE request then the Rails uses protect_from_forgery for verify the data sending url
However in your case, its not hard to write a simple method to verify your data for get requests ,
you could write a before_filter to check the sending parameters for a GET request
HTH

Passing parameters through OmniAuth

I need to pass some parameters to callback action. Judging from the source code, OmniAuth should add query string to callback URL but strangely it does not. When I open
/auth/facebook?from=partner
...and get redirected to Facebook, return_url is just
/auth/facebook/callback
...without any parameters.
After struggling with all the above answers, I figured out what to do regarding Facebook, which by default does not display the params in request.env["omniauth.auth"].
So -- If you are using a query string for the callback, similar to something like this:
"/auth/facebook?website_id=#{#website.id}"
The only way to get that website_id param is by using request.env["omniauth.params"]. NOTE: MAKE SURE YOU USE omniauth.params and not omniauth.auth -- this one tripped me up for a while.
Then, to test this out, you can inspect it within your controller action (notice the RAISE line...):
def create
raise request.env["omniauth.params"].to_yaml
# the rest of your create action code...
end
You should see your parameter there. Great. Now, go back to your controller and remove that RAISE line. Then, you can access the param as follows in your controller action:
params = request.env["omniauth.params"]
website_id = params["website_id"]
NOTE: in params["website_id"] you need to use quotes and NOT a symbol.
I guess the cookie thing works but why do all that when you can use the state variable as documented here: https://github.com/mkdynamic/omniauth-facebook
This is how I used it:
when creating the url you can just add state in the Query String and it will be available in the callback url as well.
user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %>
now the callback url will be
http://localhost:3000/users/auth/facebook/callback?state=123&code=ReallyLongCode#_=_
Now in the callback handler you can process the state
You can use the :params options, as in
omniauth_authorize_path(:user, :facebook, var: 'value', var2: 'value2' )
and later in the callback you can access request.env['omniauth.params'] to get the hash! :)
(copied from this answer)
What you want to do is dynamically set your callback to include the partner name in the url (not the url parameters), on a per authentication transaction basis, depending on which partner was involved. This means setting the callback url dynamically, for each authentication request. See this blog post to get started. The callback url automatically drops the url parameters, as you've noticed, so doing this with parameters won't work.
So, if instead of trying to pass the partner name/id in as a parameter (which is dropped), you structured your routes so that the partner_id and OmniAuth provider were part of the callback url, then you'd have something like:
/auth/:omniauth_provider/callback/:partner_id
...where a valid callback would be something like
/auth/facebook/callback/123456
...then you would know that a given callback came in from facebook, with partner id 123456
OmniAuth already has a built-in way to know where the user was, it's called "origin" as documented here:
https://github.com/intridea/omniauth/wiki/Saving-User-Location
You know, I think I might be trying to solve this the hard way.
Cookies might be the answer. I think you can solve this by having your login action store a cookie, and then redirecting to the proper /auth/:provider path for authentication, and when the callback is triggered (in SessionsController#create), you just read the cookie back to know where to redirect them to.
So, right now, your "login with facebook" link (or whatever you have you in your app) probably goes to /auth/facebook. Instead if you created a custom action like
POST /partner_auth
...and called it with the url...
POST example.com/partner_auth?from=partner&provider=facebook
Then you might have a controller like:
class PartnerAuth < ApplicationController
def create
cookies[:from] = params[:from] # creates a cookie storing the "from" value
redirect_to "auth/#{params[:provider]"
end
end
Then in the SessionsController#create action, you would have...
def create
...
destination = cookies[:from]
cookies[:from].delete
redirect_to destination # or whatever the appropriate thing is for your
# app to do with the "from" information
end
I tried to build a demo app to accomplish what I'd outlined in the other answer, but you're right - it was too complicated to try to dynamically inject a custom callback into the OmniAuth code. There is a configuration option to override the default callback, but it doesn't appear to be easy to set it dynamically.
So, it dawned on me that cookies would be way simpler, user-specific, and since you theoretically only need to store this from information for a very short time (between when the user tries to authenticate, and when the callback is triggered), it's no big deal to create a cookie, and then delete it when the callback gets hit.
Use the 'state' Variable. Facebook allows the user to set a STATE variable.
Here is how I did it, I appended the AUTH URL with ?state=providername
http://localhost/users/auth/facebook?state=providername
This param is returned to me at Callback as params['providername']
I devised the solution from the original Omniauth Path Method
user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %>

Passing random url params to OmniAuth

I'm using omniauth with devise and I'm wondering how to pass url params and access them.
Here's a link example: /accounts/auth/facebook?do_something_after_return=1
Now I want to be able to retrieve this do_something_after_return in the callback. I don't care if it's saved in session or elsewhere. Problem is, I don't know where can I intercept this param.
What is the controller and the action that link /accounts/auth/facebook points to?
Routes tell me nothing, it's simply not there. All I have in the routes is this /accounts/auth/:provider(.:format {:controller=>"accounts/omniauth_callbacks", :action=>"passthru"} which is a callback.
Params are captured in env["omniauth.params"].

Resources