I am new to Rails and am trying to figure out where I put my API Token for the external API I am using (one of Google's). I have worked with APIs in the past with Sinatra, but the directory structure of Rails has thrown me off with where I need to place it so I can access it in the controller. After I place my token somewhere, I plan on creating a create method in the controller and parsing the json data there so I can access it in my corresponding view. If someone could help guide me in the right direction as to where I put the token so I can access it (best practices), and if I'm on the right track to use the token in a method in the controller so I can access it in a view.
I know this question might be generic but from what I have Googled, many people new to Rails might benefit from this as to where to put things.
You can add your API Tokens under config/initializers. Although, you'll probably have a gem or directions from corresponding API docs telling you what the best way is to implement them. But if you were implement them via an initializer, it would be something like this -
GoogleApi.config do |config|
config.client_id = "<Your Google API Client Id>"
config.client_secret = "<Your Application Secret>"
config.application_name = "<Your Application Name>"
end
And then you'll be able to use GoogleApi in your controllers.
A good example is this guide from heroku to access AWS
I would suggest loading your API keys via a rails initializer. The rails initializers exist in config/initializers and are plain ruby scripts that run after the servers starts up. Here you can do things like load configuration files etc. For example, config/initializers/google_oauth.rb could contain some plain ruby code to load up a config/.yml file holding your API credentials for non-production environments.
In non-production environments, you could load the API tokens from a yml file and in production you could utilize something like Figaro for Heroku or Dotenv for other environments (AWS, DigitalOcean, etc).
The important thing to ensure is that the local configuration file and your API token stay out of version control so as to avoid compromising your token and the security of your application.
Related
I have deployed an application to Heroku and have used the heroku config:set command to set environmental variables such as keys for certain things (Google Maps API, for example). When I view the page and inspect element, the key shows up in the url in the console. Should this be the case? I was under the impression that keys should be kept hidden to keep others from knowing what they are for security reasons. Please advise. Thank you.
You can't. Anything which is sent to the client is not secret. That includes any values used in javascript.
But don't worry - most API's like Google Maps use a public key. And applications where you use Oauth only allow a whitelist of callback domains.
In fact in the Google Maps Javascript API your API key is used in constructing the URLs used to request resources so attempting to hide it would be a true fools errand.
Some API's do however provide client secrets for calling the API from the server side. These should be kept secret and placed in an ENV var on the server.
I am trying to stream a file from a remote storage service (not s3 :-)) to the client using Ruby on Rails 4.2.
My server needs to stay in the middle of things to authenticate the client request but also to build up the request to the remote storage service since all requests to that service need to be authenticated using a custom header param. This makes it not possible to do a simple redirect_to and let the client download the file directly (but do let me know if this IS in fact possible using rails!). Also I want to keep the url of the file cloaked for the client.
Up until now I am using a gem called ZipLine but this also does not work as it still buffers the remote file before sending it to the client. As I am using unicorn/nginx, this might also be due to a setting in either of those two, that prevents proper streaming.
As per rails doc's instructions I have tried adding
listen 3000, tcp_nopush: false
to config/unicorn.rb but to no avail.
A solution might be to cache the remote file locally for a certain period and just serve that file. This would make some things easier but also creating new headaches like keeping the remote and cached files in sync, setting the right triggers for cache expiration, etc.
So to sum up:
1) How do I accomplish the scenario above?
2) If this is not a intelligent/efficient way of doing things, should I just cache a remote copy?
3) What are your experiences/recommendations in given scenario?
I have come across various solutions scattered around the interweb but none inspire a complete solution.
Thanks!
I am assuming you the third party storage service has an HTTP access. If you did consider using redirect_to, I assume the service also provides a means to allow per download authorization. Like unique key in the header that expires and does not expose your secret api keys or HMAC signed URL with expiration time as a param.
Anyhow, most cloud storage services provide this kind of file access. I would highly recommend let the service stream the file. Your app should simply authorize the user and redirect to the service. Rails allows you to add custom headers while redirecting. It is discussed in Rails guides.
10.2.1 Setting Custom Headers
If you want to set custom headers for a response then response.headers
is the place to do it. The headers attribute is a hash which maps
header names to their values, and Rails will set some of them
automatically. If you want to add or change a header, just assign it
to response.headers
So your action code would end up being something like this:
def download
# do_auth_check
response.headers["Your-API-Auth-Key"] = "SOME-RANDOM-STRING"
redirect_to url
end
Don't use up unnecessary server resources by streaming through them all those downloads. We are paying cloud services to that after all :)
I'm trying to setup my heroku app to have an static IP using QuotaGuard (I know proximo is the other option, but it's pretty expensive).
I added the heroku QuotaGuard Static addon and got the two IPs it generates as well as the proxy url.
What is my next step? (aka how do I tell my Rails app to use the proxy provided by QuotaGuard)
I see they have ruby code samples using REST-client and HTTParty, but do I put that somewhere like in the application.rb??
Most likely a bit too late to answer this question, but still.
Like you said, the first step to configuring QuotaGuard Static is provisioning the addon on Heroku (either via the Web Interface or the Heroku CLI). From there, you are able to get your two outbound IPs, and your proxy URL. The two IPs you were given should be whitelisted on whichever remote service you are trying to access.
As you mentioned, the documentation gives you a couple of samples using Rest Client for Ruby on Rails. This snippet should pretty much go anywhere you want to access whichever resource you need to access via the static IP Addresses. Assuming you want to access a Web Service hosted on an Amazon EC2 instance with elastic IP 1.2.3.4, your would write:
RestClient.proxy = ENV["QUOTAGUARDSTATIC_URL"]
res = RestClient.get("http://1.2.3.4/yourWebService")
And from there process the response stored in res appropriately. This code would go in say whichever controller's method you'll be using to access the remote web service. In this case, you also need to add the Rest Client to your controller, so at the top of that file you shoud also add require "rest-client" . Don't forget to add the rest-client gem to your Gemfile.
Summing up, basically the snippets from the documentation go wherever it is you want to use the proxy to access a remote service requiring a fixed, whitelisted set of IP addresses.
Source: https://devcenter.heroku.com/articles/quotaguardstatic
I would like to integrate my cloud service in Heroku as an add-on. I read the available tutorials on how to do this, but it is still not clear. https://devcenter.heroku.com/articles/building-a-heroku-add-on#provisioning
I couldn't understand the role of the application that we create from a template (Sinatra for example) using kensa.
Is it an intermediate between Heroku and the cloud service?
thanks in advance.
Actually, Heroku needs 2 things:
addon-manifest.json file where described all information needed for Heroku. And this json file contains 2 important urls:
'base_url'
'sso_url'
Application which will server heroku-specific API and responds wit corresponding JSON on provisioning/deprovisioning/planchange requests. These request point to 'base_url'.
So, if you own your Cloud service code, and can add new API endpoints, then you don't need any application based on kensa-template: add necessary API controllers directly in the service.
But if you can't upgrade the cloud service, then you're right, kensa-template is a ready to use with heroku intermediate.
In case of sinatra template, you just need to put necessary API calls to your cloud service in "# provision" method of app.rb file, deploy app somewhere and do 'kensa push' for your addon-manifest.json (don;t forget to update base_url to yours)
Good luck!
Bare minimum API routes for heroku add-on based on your Cloud service:
POST request to '/heroku/resources' - for provisioning
DELETE request to '/heroku/resources' - for deprovisioning
If you really want to sell it to heroku users, then you should do more stuff:
add support for heroku single sign-on
this is one more API route: POST to '/heroku/sso', but you can change it in addon-manifest.json file.
PUT '/heroku/resources/:id' for Plan change request. Note that ':id' is an id which you provided heroku in your response during provisioning.
If you implement SSO, then user can click on your add-on on heroku instance's resources page and redirect directly to your service bypass any login forms.
You can show just short info about user's resource in the page after SSO.
I just got an API key for a database I wish to access and want to start building my Rails app. However I dont know where to begin with the API key. Specifically I want to use the brewerydb data and I am building an app where users can find the closest brewery to their location. Can anyone tell me how to get started? I am new to Rails and have never used an API before. I don't know where to begin. What file should I put it in, etc... I know I should probably update the GEMFILE, where else?
Thanks!
Check the documentation for the API. That's all I can say. (well... not really: )
Most API's rely on REST or SOAP, which is basically making HTTP request to certain URI's. An example may be
http://api.somewebsite.com/beers.json
Which would return, for instance, a JSON array of certain beers and their properties.
Furthermore, more often than not, you can test API's (that do not require certain HTTP headers for authentication, which makes it harder) by manually constructing the URI's and opening them in your browser. This way, you can verify that your request is okay before you try it in your Rails application an cannot figure out why it's not working.
You should use the 'figaro' gem https://github.com/laserlemon/figaro
It creates a "application.yml" file in which you can add your API key.