I'm building an API with Rails that is going to receive HTTP requests from other sites.
Every time a new request is issued, I need to know in my app if this site has already sent this request. So, I'm wondering if there is a way to uniquely identify the site sending the request. I'm thinking of using request.remote_ip however if the site is on a shared hosting, it would share the same IP address with other sites.
Is there any other way to identify the remote origin?
If the request is issued from an API client then the IP is all you have that you can (somewhat) rely on.
And as you mentioned this is not really unique (proxy, shared hosting, ...).
Related
i want to use google map api for route between two location. in my IOS application. i try create public key for project and enable uses API in developer console. but i got this error: this ip site or mobile application is not authorized to use this api key IOS. after this error i try create API key for Key restriction for (IP addresses (web servers, cron jobs, etc.)) and set my ip address and then routing is work fine. but when i try this from other device again and again i get this error.
i should use this URL for routing :
let url = "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destination)&mode=driving&key=APIKEY"
how can solve this problem for working my code in all devices.
The API key that you use with Google Maps web service (Directions API) supports an IP restriction as mentioned in the following document:
https://developers.google.com/maps/faq#using-google-maps-apis
The issue is that you cannot know the IP addresses of all devices where your application is installed.
You have the following options:
Use unrestricted API key. Note that API key requires HTTPS connection, so the API key won't be intercepted from the request itself, because the request is encrypted. So, in this case you should procure that the API key is not put directly in your source code. If you can read it from config or the environment, it might be feasible.
Create an intermediate server. Your iOS application should send requests to the intermediate server, intermediate server should send requests to Google and pass responses back to your app. In this case you can restrict an API key by IP address of your intermediate server.
I hope this helps!
We have a web service api running on an EC2 instance on aws. We want to connect to it from external applications managed by us, eg iphone app, other frontend applications on different servers. I can't get my head around how to authenticate these. Do i add the ip to the EC2 security group, or IAM? and then when making JSON requests do i need to send the AWS access keys? are these sent in the headers? So say a sample call would be:
API.post("http://awsserver.com/app_api/v1/request", query: {
customer_name: "John Doe", customer_email: "test#test.com" }, headers:
{"AWS_ACCESS_KEY_ID"=>"exampletoken", "AWS_SECRET_KEY" =>
"secretexample"})
I have tried searching but surprisingly not a lot found. Any help would be great, thanks.
First of, do not send your access key and secret with any POST ever in plain text. The access key and secret key are used to generate unique tokens that expire to access AWS resources at your account level, not your application (API).
There are lots of assumptions I am making, however you will need to have the authentication done at your application level if you intend to have this API accessible from mobile devices as they will have changing IP's.
Look into OAuth where devices request access from some authentication mechanism in your application which will return a token you can send along in subsequent POST requests in the header.
For servers accessing your API you could certainly add those EC2 instance IP's to a security group opening access to your API server and deny all other IP's access, however keep in mind if the EC2 instances do not have Elastic IP's then on any restart they will have a different IP and need to be added to your security group.
That is, want a Rails application that lets me see a customized view of the user's Gmail calendar. But it'll be on shared hosting so don't want to store credentials, or have them in the clear.
Question: Can I securely access Gmail for a Rails app on shared hosting non-SSL without putting credentials at risk? How would I do this? (e.g. does OAuth or OpenID solve this)
Requirements would be:
Rails application will call Google Calendar via API
No credentials stored on shared hosting site (e.g. in database or whatever) - MANDATORY
Rails site is non-SSL - MANDATORY (for the purpose of this question)
Ability to stay logged in whilst browser still open - DESIREABLE (assume using session id...assuming this is secure)
For example exiting approach I've used which wouldn't satisfy my requirements on my non-SSL rails site (on a shared host) would be:
# Get Google Calendar
service = GCal4Ruby::Service.new
service.authenticate("<google account name>", "<password>") # <== requires password
cal = GCal4Ruby::Calendar.find(service, "myCalendar")[0]
# Get Google Events
search_str = "<search str>"
#events = GCal4Ruby::Event.find(cal, search_str, params)
You will get mixed content if you try to include in an http page an https Google calendar view loaded as an iframe.
If you're just doing API calls, as long as the API calls are from your server to an encrypted endpoint, https://calendar.google.com or something similar, then there are no problems.
If you're doing API calls from a non-http page in the browser, then a determined attacker will be able to eavesdrop on any data you serve, including credentials sent to the browser for forwarding to the calendar service.
If you're sending credentials to the browser you should also worry about exfiltration via XSS.
Working on a data collection application using mobile sms.
when a customer send a sms lets say
SMS content
Demo CET 100-50030-2320-1000
when the sms reach the mobile serive provider it send a GET request on my server
http://domainname.com/demo.aspx?mno=9828958745&sms=CET+100-50030-2320-1000
Now the problem is some hackers are sending GET request from there PC browser and all the data is getting missed and server is getting overload
I want to know which request is from a computer(mobile server) and which are from browser.
thanks in advance
Regards
Check if the request for a page is coming from a server not a browser.
If your service is not meant to be accessible publicly you have to protect it instead of publishing it on the internet. Some wasy to protect it:
HTTP Authentication
IP restrictions in firewall.
IP restrictions in the service.
Virtual Private Network.
I want users of my service to be able to add their own custom domains. For example, www.[their domain].com should be able to access their application's index and show pages. My service is implemented in Rails 3.
I've seen apps like Tumblr offer this functionality for their front facing blogs. Although I have seen apps for Rails that implement sub domains in the way that Basecamp does, I have not found a resource for fully custom domains.
They'll need to create an A record in their DNS to point to your app servers IP. You'll need to know what domain they have pointed to your server and log it against their account, and also set your web servers config in such a way as to channel the requests from other domains to your app. You can then use the request object to look up their account in your application_controller.
I just answered a similar question so I decided to chime in here too.
#Codebeef gave a good answer but this won't work anymore in the world where HTTPS is a must in most modern browsers.
This is the full picture of how to handle custom domains for your app.
If your customers just CNAME to your domain or create the A record to your IP and you don't handle TLS termination for these custom domains, your app will not support HTTPS, and without it, your app won't work in modern browsers on these custom domains.
You need to set up a TLS termination reverse proxy in front of your webserver. This proxy can be run on a separate machine but you can run it on the same machine as the webserver.
CNAME vs A record
If your customers want to have your app on their subdomain, e.g. app.customer.com they can create a CNAME app.customer.com pointing to your proxy.
If they want to have your app on their root domain, e.g. customer.com then they'll have to create an A record on customer.com pointing to your proxy's IP. Make sure this IP doesn't change, ever!
How to handle TLS termination?
To make TLS termination work, you'll have to issue TLS certificates for these custom domains. You can use Let's Encrypt for that. Your proxy will see the Host header of the incoming request, e.g. app.customer1.com or customer2.com etc., and then it will decide which TLS certificate to use by checking the SNI.
The proxy can be set up to automatically issue and renew certificates for these custom domains. On the first request from a new custom domain, the proxy will see it doesn't have the appropriate certificate. It will ask Let's Encrypt for a new certificate. Let's Encrypt will first issue a challenge to see if you manage the domain, and since the customer already created a CNAME or A record pointing to your proxy, that tells Let's Encrypt you indeed manage the domain, and it will let you issue a certificate for it.
To issue and renew certificates automatically, I'd recommend using Caddyserver, greenlock.js, OpenResty (Nginx).
tl;dr on what happens here;
Caddyserver listens on 443 and 80, it receives requests, issues, and renews certificates automatically, proxies traffic to your backend.
How to handle it on my backend
Your proxy is terminating TLS and proxying requests to your backend. However, your backend doesn't know who is the original customer behind the request. This is why you need to tell your proxy to include additional headers in proxied requests to identify the customer. Just add X-Serve-For: app.customer.com or X-Serve-For: customer2.com or whatever the Host header is of the original request.
Now when you receive the proxied request on the backend, you can read this custom header and you know who is the customer behind the request. You can implement your logic based on that, show data belonging to this customer, etc.
More
Put a load balancer in front of your fleet of proxies for higher availability. You'll also have to use distributed storage for certificates and Let's Encrypt challenges. Use AWS ECS or EBS for automated recovery if something fails, otherwise, you may be waking up in the middle of the night restarting machines, or your proxy manually.
If you need more detail you can DM me on Twitter #dragocrnjac