I have multiple services which have their own web-server, listening on different ports, for e.g. :
http://127.0.0.1:5000 (service A)
https://127.0.0.1:3000 (service B)
I need a way to restrict access to them without tweaking each of them individually. So, I have an OAuth server hosted as well (port 2333). I have configured the OAuth server to be able to redirect you to a certain URL, if you successfully authenticated through it. So, for e.g. if I access this URL:
https://127.0.0.1:2333/oauth/authorise?service=A&redirect_uri=http://127.0.0.1:5000
It will ask for authentication (or search for cookie) and redirect me to the desired URL. This works OK if I manually access that URL, but I need it automated (every time you try accessing the initial URL, get redirected to the OAuth).
I need the following scenario:
Insert URL http://127.0.0.1:5000 in browser
Get redirected to https://127.0.0.1:2333/oauth/authorise?service=A&redirect_uri=http://127.0.0.1:5000
The OAuth server takes care of the rest
For this, I was thinking of using nginx to redirect, but I don't know how to configure it. Any ideas?
How are those services hosted? You have a couple of options:
Doing a redirect to (https://127.0.0.1:2333) on the / path for A service (on the source code).
Doing a redirect on the server configuration (which is more low level and should be faster)
The first option gives you more control, and you can do other things easily (like checking if the user is logged in). The second option is faster, but some things are harder to implement, as you will modify the server configuration)
Related
I have a complex web app at example-app.com, hosting fully on AWS using ELB and Route 53 for DNS. It's a Rails app.
I'm running an experiment that I'm using in the rails app, at example-app.com/test. I want to set up new-domain-app.com, to point at example-app.com/test, and have the URL cloacked to always be new-domain-app.com. It's a single page site, so it shouldn't require any navigation.
I'm having a lot of trouble figuring out how to set up my DNS on Route 53 to accomplish this. Does anyone have good ideas on what this Route 53 configuration should look like?
AWS offers a very simple way to implement this -- with CloudFront. Forget about the fact that it's marketed as a CDN. It's also a reverse proxy that can prepend a fixed value onto the path, and send a different hostname to the back-end server than the one typed into the browser, which sounds like what you need.
Create a CloudFront web distribution.
Configure the new domain name as an alternate domain name for the distribution.
For the origin server, put your existing hostname.
For the origin path, put /test -- or whatever string you want prefixed onto the path sent by the browser.
Configure the cache behavior as needed -- enable forwarding of the query string or cookies if needed and any headers your app wants to see, but not Host.
Point your new domain name at CloudFront... But before you do that, note that your CloudFront distribution has a dxxxexample.cloudfront.net hostname. After the distribution finishes setting up (the "In Progress" status goes away, usually in 5 to 20 minutes) your site should be accessible at the cloudfront.net hostname.
How this works: When you type http://example.com into the browser, CloudFront will add the origin path onto the path the browser sends, so GET / HTTP/1.1 becomes GET /test/ HTTP/1.1. This configuration just prefixes every request's path with the string you specified as the origin path, and sends it on to the server. The browser address bar does not change, because this is not a redirect. The host header sent by the browser is replaced with the hostname of the origin server when the request is sent to the origin.
What you are trying to do is not possible. Route53 is a DNS system, and you can not configure a hostname (e.g. new-domain-app.com) to point to URL (e.g. http://example-app.com/test) using DNS.
However, you are probably using a wrong tool for the job. If example-app.com/test is indeed a simple, static, single page site, then you do not need to host it inside Rails app. Instead, you can host it on AWS S3 bucket, and then you can point new-domain-app.com to that bucket using Route53.
See the following for details:
http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html
http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/RoutingToS3Bucket.html
DNS knows about Domains, not url's. DNS simply converts names to IP addresses.
You can't do what you are asking for just using DNS and ELB, however, what you can do is have a seperate VHOST for new-domain-app.com that points to your example-app.com site and accomplishes what you want using some sort of redirection rule that only fires for new-domain-app.com.
I'm not sure that this qualifies as an SO question, and more likely is a serverfault question. Specifics about your webserver and OS platform would be helpful in getting more specific advice.
So here's some details:
You already have example-app.com setup and working
You create a CNAME entry pointing new-domain-app.com to example-app.com or you can make an A record pointing to the same IP. If you already have example-app.com pointing to a different IP address, then use a subdomain (test.example-app.com) to isolate it.
Setup a new vhost on your server that basically duplicates the existing vhost for new-domain-app.com. The only thing you need to change is the server name configuration.
Why does this work? Because HTTP 1.1 included the HOST header that browsers send along, and web servers use in vhosting to determine which virtual host to route an incoming request to. When it sees that the client browser wanted "example-app.com" it routes the request to the appropriate vhost.
Rather than having to do some fancy proxying, which certainly can be used to get to a similar result, you can just add a redirection rule that looks for requests for the host example-app.com and redirects those to example-app.com. In apache that uses mod_rewrite which people often utilize by putting rules in the ubiquitous .htacess file, but can also be done in nginx and other common web servers. The specifics are slightly different for each.
When I test my ASP.Net app locally, I use a DNS tool called DNSSpeeder which takes over the DNS process for my machine. In effect, I can setup www.mysite.com locally and enter an IP address like 192.168.178.200 and in my browser just enter www.mysite.com and it launches from my local IIS web server. When I'm ready for production, I just disable DNSSpeeder so that an Internet's DNS is used to lookup my site.
The problem I am facing is when I use Google OAuth to exchange my code for a token. It returns with an error of redirect_uri_mismatch. It isn't clear to me what is actually going out on the wire to Google's server and what URI Google is seeing. The URI redirect does match what is in the API console, although that doesn't say anything about what is actually sent to Google's server after it leaves DNSSpeeder. I tried Wireshark but it shows nothing. Probably encrypted with https. Instead of using http://localhost:8080, I tried http://localhost:80 as well as http://192.168.178.200 for the Javascript origins but that didn't help.
Is it possible to use an IP address other than localhost when testing locally to get a successful token?
"Is it possible to use an IP address other than localhost when testing locally to get a successful token?"
Yes it is possible. My setup is that I have configured two redirect URLs in the Cloud Console, (http://www.mydomain.com/redirect and http://dev.mydomain.com/redirect).
I then edit /etc/hosts (on linux, the Windose equivalent is under system32\drivers somewhere) to map dev.mydomain.com to 127.0.0.1.
And it works just fine. You may need to tweak your app so the redirect URL is not hardcoded, but is in fact varied based on whether your app senses it's in dev or production.
One thing to be aware of is that the confiured redirect URL must be a character for character match to the actual URL. So be careful that you have both http and https variants, and also watch for a trailing slash. If necessary configure both with and without the trailing slash.
I have a website that is 100% https and will only work as https. My site is an asp.net mvc application running on IIS 7.5.
It is on multiple servers with traffic distributed via a load balancer.
I am not in control of the hardware.
For http requests, I was hoping that it could be stopped at the load balancer and a redirect to https at this point.
However the hardware company wont do this for me, and instead I need to do the redirect from http to https within IIS on the server. Therefore unencrypted traffice can enter the inner network with redirect being at the server level. I would feel more comfortable with such a transfer happening at the load balancer.
Do I have valid concerns?
Threat model:
HTTP request:
Attacker
| Security Boundary
V V
Client -- http request --> Load Balancer
|
Client <-- redirect -----------+
Threats which occur from allowing HTTP redirects regardless of methodology:
Spoofing: Client could connect to MITM spoofed HTTP server which does not pass through the redirect, but instead proxies connections to the actual HTTPS server
Tampering: Client could receive redirect URL from MITM spoofed server which directs them to another action (E.g.: client receives redirect to https://yoursite.com/login.aspx?redirect=/deleteAllDocuments)
Information Disclosure: Initial HTTP request is disclosed, any information in POST or GET is available unencrypted to eavesdroppers.
Arguments for performing redirect on server other than target server:
Firewall can be limited to HTTPS data, limiting risk of unencrypted data due to misconfiguration
Configuration and liability could become "Someone else's problem", from at least a political perspective
Vulnerabilities in HTTP server would be isolated and could not be used to attack HTTPS server or underlying application
Arguments for performing redirect on something other than the load balancer:
Load balancers are not servers
Load balancers are not servers, and therefore might have lightly used code paths when used as servers, which could be more prone to undiscovered bugs or performance problems
Configuration is not available to you, but you (or your company) is still probably liable for any misconfigurations which occur (from a legal perspective)
In light of the above analysis, for highest security with lowest risk:
I would not put the redirect on the target server, nor the load balancer, but instead on a VM which only serves to redirect pages. A minimal Linux or windows box should be able to be tightly locked down to limit exposure.
I would not allow redirects with a query-string or POST data (E.g.: show 404 for any non GET / HTTP/1.1 request)
I would call the possibility of spoofing and tampering an acceptable risk, or show a page to the user explaining that the site must be accessed using HTTPS instead of using a redirect
But, if you can assume the following conditions are met, placing the HTTP server co-resident with the HTTPS server should not reduce security.
Any bug in the HTTP server is present in the HTTPS server
The HTTP server is correctly configured to disallow access to protected resources (set up as a separate site in IIS, for example. Secure site still has no HTTP binding)
No other application is able to create a server on HTTP (netsh urlacl only has IIS, for example)
Configuration is audited to ensure the above configurations are properly maintained (Periodic pen tests, manual configuration review, configuration change management, and an IDS or IPS system)
In some cases, the reduced complexity may even be easier to secure than a separate server. Additionally, if the administrator is unfamiliar with the load balancer's configuration, they may be more prone to make a critical error in configuration than if they were to make the same configuration in a product they know well.
Do I have valid concerns?
Do you have a valid concern about the initial connection being over HTTP? Sure. The initial request can be intercepted and the response spoofed in a MitM attack. The attacker can then either prevent the user from using HTTP (adding ssl/tls between the attacker and your server and relaying to the victim in the clear) or can create an imposter SSL session with the client that terminates at the attacker before being re-encrypted on it's way to you (using various spoofing techniques to make the attack less obvious to the casual user).
However, if such an attack were launched, I would be far more worried about the transit from the client to your load balancer, not between your load balancer and IIS. If you suspect that you have malicious systems behind your load balancer, you have an entirely different set of problems.
See my answer over on security.so for some relevant information regarding redirects from HTTP to HTTPS.
I am trying to test OAuth buttons, but they all (Facebook, Twitter, LinkedIn) come back with errors that seem to signal that I can not test or use them from a local URL.
How do people usually work in development with OAuth stuff if they all seem to require a non-dev and non-local connections environments?
Update October 2016: Easiest now: use lvh.me which always points to 127.0.0.1, but make sure to verify that this is still true every time you need to invoke it (because domains can expire or get taken over, and DNS poisoning is always a concern)
Previous Answer:
Since the callback request is issued by the browser, as a HTTP redirect response, you can set up your .hosts file or equivalent to point a domain that is not localhost to 127.0.0.1.
Say for example you register the following callback with Twitter: http://www.publicdomain.com/callback/. Make sure that www.publicdomain.com points to 127.0.0.1 in your hosts file, AND that twitter can do a successful DNS lookup on www.publicdomain.com, i.e the domain needs to exist and the specific callback should probably return a 200 status message if requested.
EDIT:
I just read the following article: http://www.tonyamoyal.com/2009/08/17/how-to-quickly-set-up-a-test-for-twitter-oauth-authentication-from-your-local-machine, which was linked to from this question: Twitter oAuth callbackUrl - localhost development.
To quote the article:
You can use bit.ly, a URL shortening service. Just shorten the [localhost URL such as http//localhost:8080/twitter_callback] and register the shortened URL as the callback in your Twitter app.
This should be easier than fiddling around in the .hosts file.
Note that now (Aug '14) bit.ly is not allowing link forwarding to localhost; however Google link shortener works.
PS edit: (Nov '18): Google link shortener stopped giving support for localhost or 127.0.0.1.
You can also use ngrok: https://ngrok.com/. I use it all the time to have a public server running on my localhost. Hope this helps.
Another options which even provides your own custom domain for free are serveo.net and https://localtunnel.github.io/www/
Or you can use https://tolocalhost.com/ and configure how it should redirect a callback to your local site. You can specify the hostname (if different from localhost, i.e. yourapp.local and the port number). For development purposes only.
For Mac users, edit the /etc/hosts file. You have to use sudo vi /etc/hosts if its read-only. After authorization, the oauth server sends the callback URL, and since that callback URL is rendered on your local browser, the local DNS setting will work:
127.0.0.1 mylocal.com
Set your local domain to mywebsite.example.com (and redirect it to localhost) -- even though the usual is to use mywebsite.dev. This will allow robust automatic testing.
Although authorizing .test and .dev is not allowed, authorizing example.com is allowed in google oauth2.
(You can redirect any domain to localhost in your hosts file (unix/linux: /etc/hosts))
Why mywebsite.example.com?
Because example.com is a reserved domain name. So
there would be no naming conflicts on your machine.
no data-risk if your test system exposes data
to not-redirected-by-mistake.example.com.
You can edit the hosts file on windows or linux
Windows : C:\Windows\System32\Drivers\etc\hosts
Linux : /etc/hosts
localhost name resolution is handled within DNS itself.
127.0.0.1 mywebsite.com
after you finish your tests you just comment the line you add to disable it
127.0.0.1 mywebsite.com
Google doesn't allow test auth api on localhost using http://webporject.dev or .loc and .etc and google short link that shortened your local url(http://webporject.dev) also bit.ly :). Google accepts only url which starts http://localhost/...
if you want to test google auth api you should follow these steps ...
if you use openserver go to settings panel and click on aliases tab and click on dropdown then find localhost and choose it.
now you should choose your local web project root folder by clicking the next dropdown that is next to first dropdown.
and click on a button called add and restart opensever.
now your local project available on this link http://localhost/
also you can paste this local url to google auth api to redirect url field...
This answer applies only to Google OAuth
It is actually very simple and I am surprised it worked for me (I am still sceptical of what my eyes are seeing).
Apparently you can add localhost as a trusted domain on the Google Developer Console, since localhost is an exception for most rules as you can see here.
This can be done on this page under OAuth 2.0 Client IDs. Click edit and then add http://localhost:8000 or similar ports, and hit save.
It is crucial that you include http or https in the input box.
HTTP or HTTPS?
I am once again surprised that Google allows http, although do note that there is a minor security risk if your application has been released to production.
If you want to be extra cautious, you can choose to stick with https. This will require you to set up an SSL certificate on your localhost server.
This is easier than you think, since the SSL certificate needs not be valid. Many http servers should give you this option. You will have to click the "proceed anyway" button anyway in your browser to bypass the big red warning.
This is more secure than http since either a) users will see a big red warning if hackers are trying something phishy, or b) the only time they won't see this warning is if the user intentionally set up a self-hosted SSL certificate, in which case they probably know what they are doing (I suppose a virus could technically do this as well, but at that stage they've already gotten enough control of a user's system to do anything they want).
I ran into some issues with the tools mentioned in other answers such as http://tolocalhost.com not forwarding query parameters (not to mention you have to visit the page and configure it first, same case with https://thomasmcdonald.github.io/Localhost-uri-Redirector/) and http://lvh.me not being useful to me because I run a proxy on my local machine and need the public URL to point to a private URL like http://mywebsite.dev.
So I made my own tool that filled my needs and may fill yours:
https://redirectmeto.com
Examples:
https://redirectmeto.com/https://www.google.com/search?q=puppies
http://redirectmeto.com/http://localhost:4000/oauth/authorize
http://redirectmeto.com/http://client.dev/page
Another valuable option would be https://github.com/ThomasMcDonald/Localhost-uri-Redirector. It's a very simple html page that redirects to whatever host and port you configure in the UI.
The page is hosted on Github https://thomasmcdonald.github.io/Localhost-uri-Redirector, so you can use that as your OAuth2 redirect url and configure you target host and port in the UI and it will just redirect to your app
If you have a domain, you can create a subdomain that redirects to your local entry point, it works for me
I created a public subdomain : oauth-test-local.alexisgatuingt.fr that redirects you to http:127.0.0.1:8000/oauth/callback/google with the returned data
Taking Google OAuth as reference
In your OAuth client Tab
Add your App URI example(http://localhost:3000) to Authorized JavaScript origins URIs
In your OAuth consent screen
Add mywebsite.com to Authorized domains
Edit the hosts file on windows or linux Windows C:\Windows\System32\Drivers\etc\hosts Linux : /etc/hosts to add 127.0.0.1 mywebsite.com (N.B. Comment out any if there is any other 127.0.0.1)
One of my rails apps (using passenger and apache) is changing server hosts. I've got the app running on both servers (the new one in testing) and the DNS TTL to 5 minutes. I've been told (and experienced something like this myself) by a colleague that sometimes DNS resolvers slightly ignore the TTL and may have the old IP cached for some time after I update DNS to the new server.
So, after I've thrown the switch on DNS, what I'd like to do is hack the old server to issue a forced redirect to the IP address of the new server for all visitors. Obviously I can do a number of redirects (301, 302) in either Apache or the app itself. I'd like to avoid the app method since I don't want to do a checkin and deploy of code just for this one instance so I was thinking a basic http url redirect would work. Buuttt, there are SEO implications should google visit the old site etc. etc.
How best to achieve the re-direct whilst maintaining search engine niceness?
I guess the question is - where would you redirect to? If you are redirecting to the domain name, the browser (or bot) would just get the same old IP address and end up in a redirect loop.
If you redirect to an IP address.. well, that's not going to look very user friendly in someone's browser.
Personally, I wouldn't do anything. There may be some short period where bots get errors trying to access your site, but it should all work itself out in a couple days without any "SEO damage"
One solution might be to use Mod_Proxy instead of a rewrite to proxy traffic to the new host. This way you shouldn't see any "SEO damage".
I used rinetd to redirect the IP traffic from the old server to the new one on IP level. No web server or virtual hosts config needed. Runs very smoothly and absolutely transparent to any client.