MVC5 block Action from all but localhost - c#

I looked for a solution to this problem that seems simple to me without success on the internet.
In a sample project I've made for the test :
I have a Controller NotAuthorizedwith a public ActionResult Index() { return View(); }
The Index view only contain the text This page need to be only available in local.
So, my problem is that, I want that the only way to access NotAuthorized/Index is from IIS himself, anybody from LAN or WAN need to get a 403 error.
I think web.config can do the job but is it secured ? and how to implement it ?
It's for a big project, I need to block an API from internet because only the application need to use it.
In the final project, the application use it by local adress like "127.0.0.1/xxx".
Sorry for my english, not my language.
Edit : (following greatbear302 solution)
Tested on a published application with WebDeploy (what I need).
The site bindings are :
192.168.0.5:9999
testmvc on 192.168.0.5:80
On IIS, I click on my site, and in the Views directory, on my 'NotAuthorized' directory who contain the page I don't want users can access.
On the IP Address and Domain Restrictions, I've set All deny and 192.168.0.5 (IIS) authorized.
running tests :
192.168.0.5:9999/NotAuthorized: I see the page.
testmvc/NotAuthorized : I see the page.
I don't know what to do next.

In IIS
Click on your site
Click IP Address and Domain Restrictions (if this feature is missing, install from Add Remove Windows Components in Control Panel)
Click Allow Entry on right most pane
In Specific IP Address field, enter the IP address of the server hosting your API and click OK
Click Edit Feature Settings, in Access for Unspecified Clients, select Deny and click OK

Without any success with IIS, I go on a basic IP filtering on the application.
My IIS execute the application on 192.168.0.5 so here my code :
public ActionResult Index() {
ViewBag.UserIP = Request.UserHostAddress;
if (Request.UserHostAddress != "192.168.0.5")
throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "Accès non autorisé");
return View();
}
It do the job. I'll see in the future if I can make a better solution for my problem.

Related

How to restrict a website to get access to a specific path through IIS?

I'm looking for a way to restrict a website served by IIS so that the website can get access to the specific folder or drive not more, let me illustrate it.
Imagine I have two websites A and B served by IIS, you can put following code in code-behind of both websites:
string windowsPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows)
string path = windowsPath + #"\Microsoft.NET\Framework";
var directories = Directory.GetDirectories(path);
I need a way through IIS to restrict website A not be able to get access to the mentioned directories and only website B be able to do that. In other words I want to restrict read access.
I suppose it should have a simple solution because it's what hosting servers deal with. It's obvious that you can't put a piece of code in your website in a web hosting server and simply get access to list files name located in drive C of the hosting server.
How can I achieve that?
After researching a lot I found the solution, I thought it might be useful for ones who will stumble upon this matter later, so I documented the solution.
Note:
From IIS 7.5 on, you have more access on user who is running a website.
Every application pool you make, creates an internal user which is hidden and is known as AppPoolIdentity.
The goal:
Imagine We have two websites A and B, we also have a folder named SecurityTest located in D:\Temp, there are 6 folders inside it under the names 1 to 6, we consider to allow website A get the name of the folders inside SecurityTest while we tend to prevent website B to do that.
Step 1:
Firstly, create a website through VisualStudio, I put a server side button in the form, I consider to get name of folders in the specified path (say D:\Temp\SecurityTest), So here's the code I place in code behind to be triggered when the button is clicked:
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = string.Empty;
string path = #"D:\Temp\SecurityTest";
var directories = Directory.GetDirectories(path);
for (int i = 0; i < directories.Length; i++)
{
string fileName = Path.GetFileName(directories[i]);
Label1.Text += fileName + "<br />";
}
}
Step 2: Now let's deal with IIS. Add two websites (or applications) to the IIS, name them A and B, the physical path for both are the same, only change port number, for instance set 81 as port number for website A and 82 for website B. Note that new application pool is created by default with the same name of your website (if you create a new application instead of new website, you should create a new application pool by yourself).
Step 3: Now in the Connections pane, click on website A, from middle pane, double click on Authentication located in the IIS category. Then click on Anonymous Authentication, after that from 'Actions' pane at the right side, click on Edit.
Now select Application pool identity and click on OK. By following these steps you chose AplicationPoolIdentity user as the user who handles website A. Follow these steps for website B.
Step 4: Go to the pathD:\Temp, right click on the folder named SecurityTest, on the Security tab, on the Group or user names category, you can see users listed who have access to the folder, these users are granted permission at the creation time by default. You might see more or less though but the point is that you should add website A ApplicationPoolIdentity user and remove all other users, so remove Users which gives access to all users, after that remove Authenticated users from the list too.
Keep in mind that you can't simply remove these users, you should Disable Inheritance first. here's the steps to achieve that:
Since you tend to allow website A to get directories, you need to add the user corresponding to the website A, now you need to follow the next step.
Step 4-1: On the same dialogue, click on Add to add new user, from here you can't find the user related to the website A since it's a hidden and internal (and virtual) user, I mean the AppPoolIdentity user for website A. You should type the name on the following pattern:
IIS APPPOOL\<app_pool_name>
So for website A I should type IIS APPPOOL\A, click on Check Names to make sure whether the user exists or not, finally press OK button.
Step 4-2: To prevent other users to get access to the webite A, click on Advanced button, click on Disable inheritance, when you encounter the warning message, select the first option (Convert) preferably, then press OK to close the dialogue.
Now in Security tab, click on Edit button to change permissions. Here you can remove users you don't need, like Authenticated Users and Users. From now on both websites A and B won't be able to get folders name.
Now get back to IIS panel and click on website A in the left Pane, then click on Browse *:81 (http) link, you can see the website A on your browser, do the same for website B to open it in the browser. When you click on button in website A you can observe a list of folders from 1 t 6 while you get following error when you click on the button to get directories on the website B.
Access to the path 'D:\Temp\SecurityTest' is denied.
That's all you need to do.
If you understand how pipeline work, you would know that we can only filter permission based by injecting module. So there are few things we can do with IIS configuration.
Asp.net application activated under IIS worker process with Application pool identity. Since Site A and Site B used different managed service account. You could remove IIS apppool\A's permission to prevent site A from reading folder.
Since read permission for application pool identity to access windows\microsoft.net is necessary when activating worker process. It is not recommended to restrict the permission

Error: your connection to this site is not private Asp.Net. MVC5

I'm setting up a new server with windows Azure VM for a asp.net mvc 5 application. I'm able to open every page of the application without a problem with an exception of one controller. i.e. whenever I try to open a page belong to a specific controller, it prompts me for user name & password as below.
I use the same application in a different Windows Server 2016 VM without any issues.
I don't see any errors of the application/IIS logs either. I don't have any https requirements in the application.
What may be causing this behaviour?
namespace App.Controllers
{
public class ReportsController : BaseController
{
private readonly IReportRepository reportRepository;
public ReportsController(): this(new ReportRepository()){
}
public ReportsController(IReportRepository reportRepository){
this.reportRepository = reportRepository;
}
public ViewResult Action()
{
return View(reportRepository.All);
}
}
}
namespace App.Controllers
{
[Authorize]
public class BaseController : Controller
{
}
}
UPDATE: I renamed the ReportsController to AppReportsController and the issue disappeared.
i.e. I get the above prompt when I try to access
http://domain/Reports/Action
but not for
http://domain/AppReports/Action
Could you please someone explain to me what's going on here? Does it mean that "Reports" is reserved by the framework or something?
This is an authentication issue. In my case, it solved by below steps:
1- Go to IIS manager, in the left pane, expand the server root and select your web application from Sites node.
2- In the Home screen, go to IIS section and select Authentication.
3- Enable Anonymous Authentication.
4- Then, select Edit and set Edit Anonymous Authentication Credentials to Application pool identity.
I know this was an old post however I stumble on this one because I encountered the same error as the OP does.
I have solved this one in case there's someone encounters the same as this.
but the solution may vary depends if we have the same applications installed.
check if the web server / server has an installation of sql server.
check if there is reporting services installed.
remove / uninstall the reporting services from the application control panel
follow this link if you don't know how to remove the report service How to remove Report Service
Please check again if you still encounter the same error. Cheers!
The browser will tell you your connection to the site is not private if you don't use transport layer security (i.e. HTTPS) in your web application, and you are being asked to enter data - in this case your credentials. Doing this is dangerous because that data can easily be sniffed by a malicious person.
There is no reason in today's world to not have a secure site, I strongly recommend you get a certificate (they are free and super easy!)
Just don't use "Reports" use "Report" instead. Controller name ReportController not ReportsController. It'll be alright. I've faced the problem and this is the solution I've got.

How to setup local to set and get token for OAuth [duplicate]

Just wanted to know if there is any way I could develop Facebook applications in localhost.
Edit: 2-15-2012 This is how to use FB authentication for a localhost website.
I find it more scalable and convenient to set up a second Facebook app. If I'm building MyApp, then I'll make a second one called MyApp-dev.
Create a new app at https://developers.facebook.com/apps
(New 2/15/2012) Click the Website checkbox under 'Select how your application integrates with Facebook'
(In the recent Facebook version you can find this under Settings > Basic > Add Platform - Then select website)
Set the Site URL field (NOT the App Domains field) to http://www.localhost:3000 (this address is for Ruby on Rails, change as needed)
In your application initializer, put in code to detect the environment
Sample Rails 3 code
if Rails.env == 'development' || Rails.env == 'test'
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'DEV_APP_ID', 'DEV_APP_SECRET'
end
else
# Production
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'PRODUCTION_APP_ID', 'PRODUCTION_APP_SECRET'
end
end
I prefer this method because once it's set up, coworkers and other machines don't have additional setup.
Of course you can, just add the url localhost (without "http") in your app_domain and then add in your site_url http://localhost (with http)
Update
Facebook change the things a little now, just go to the app settings and in the site url just add http: //localhost and leave the App Domain empty
Here is my config and it works fine for PHP API:
app domain
http://localhost
Site URL
http://localhost:8082/
NOTE: As of 2012 Facebook allows registration of "localhost" as return Url. You still may need similar workaround for other providers (i.e. Microsoft one).
If you need real domain name registered with Facebook (like my.really.own.domain.com) you can locally redirect requests to this domain to your machine. Easiest out of box approach on any OS is to change "hosts" file to map the domain to 127.0.0.1 (see http://technet.microsoft.com/en-us/library/bb727005.aspx#EDAA and https://serverfault.com/questions/118290/cname-record-alias-in-windows-hosts-file).
I usually use Fiddler to do it for me (on Windows with local IIS) - see samples on http://www.fiddler2.com/Fiddler/Dev/ScriptSamples.asp.
if (oSession.HostnameIs("my.really.own.domain.com")) {
oSession.host="localhost:80";
}
Hosts file approach of approaches does not work with Visual Studio Development Server as it requires incoming Urls to be localhost/127.0.0.1. If you need to work with it (or possibly with IIS express) to override host - Using Fiddler with IIS7 Express
Facebook no longer allowed a 'localhost' callback URL for FBML Facebook applications
With the new development center it is now easier:
1) Leave app domains blank.
2) Click Add Platform
3) Site URL should equal the full path of your local host.
4) Save Changes
I just discovered a workaround: You can make your local machine accessible by using http://localtunnel.com . You'll need to (temporarily) change some URLs used in your app code / html so links point to the temporary domain, but at least facebook can reach your machine.
In your app's basic settings (https://developers.facebook.com/apps)
under Settings->Basic->Select how your app integrates with Facebook...
Use "Site URL:" and "Mobile Site URL:" to hold your production and development URLs respectively. Both sites will be allowed to authenticate. I'm just using Facebook for authentication so I don't need any of the mobile site redirection features. I usually change the "Mobile Site URL:" to my "localhost:12345" site while I'm testing the authentication, and then set it back to normal when I'm done.
You have to choose Facebook product 'facebook login' and enable
Client OAuth Login , 'Web OAuth Login' and 'Embedded Browser OAuth Login'
then even if you give localhost url It will work
There is ! My solution works when you create an app, but you want to use facebook authentification on your website. This solution below is NOT needed when you want to create an app integrated to FB page.
The thing is that you can't put "localhost" as a domain in the facebook configuration page of your app. Security reasons ?
You need to go to your host file, in OSX / Linux etc/hosts and add the following line :
127.0.0.1 dev.yourdomain.com
The domain you put whatever you want. One mistake is to add this line :
localhost dev.yourdomain.com (at least on osx snow leopard in doesnt work).
Then you have to clear your dns cache. On OSX : type dscacheutil -flushcache in the terminal.
Finally, go back to the online facebook developer website, and in the configuration page of your app, you can add the domain "dev.yourdomain.com".
If you use a program such as Mamp, Easyphp or whatever, make sure the port for Apache is 80.
This solution should work for Windows because it also has a hosts file. Nevertheless, as far as I remember Windows 7 doesnt use this file anymore, but this trick should work if you find a way to force windows to use a hosts file.
this works June 2018, even after the HTTPS requirement. It appears a test app does not require https:
create a test app:
https://developers.facebook.com/docs/apps/test-apps/
then within the test app, follow the simple steps in this video:
https://www.youtube.com/watch?v=7DuRvf7Jtkg
I think you should be able to develop applications using the visual studio development web server: Start a new FaceBook application on: http://www.facebook.com/developers/. Then set the settings for the site Url and the canvas url to the running instance of your website for example:http://localhost:1062/
Here are a couple of links that should help you out on starting with FaceBook:
http://thinkdiff.net/facebook/graph-api-iframe-base-facebook-application-development/,
http://nagbaba.blogspot.com/2010/05/experiencing-facebook-javascript-sdk.html,
http://apps.facebook.com/thinkdiffdemo/
Hope this helps.
Try this ---
https://www.facebook.com/help/community/question/?id=589302607826562
1 - Click Apps and then select your app.
2 - Click the Settings button on the left side of the screen.
3 - In the Basic settings, click the Add Platform button below the
settings configuration.
4 - Select Website in the platform dialog.
5 - Enter your URL (localhost works here).
6 - In the App Domains text input, add your domain that matches the one in the URL.
7 - Save your settings.
Suppose that you have registered your app as:
app.domain.com
You just need to modify the /etc/hosts file by adding
127.0.0.1 dev01.app.domain.com
Then, modify your apache configuration
ServerName dev01.app.domain.com
and restart apache.
You'll need to put your URL in a variable in order to use it as XML parameter on some calls:
<fb:login-button registration-url="http://<?=$URL?>/register" />
Don't have enough cred to comment on the top voted answer, but at least in my rails environment (running 4), rails s is at http://localhost:3000, not http://www.localhost:3000. When I changed it to http://localhost:3000, it worked just fine. No need to edit any hosts file.
app domain : localhost
site URL : http://localhost:4440/
worked for me with the new UI.
Latest update:
You don't have to give any urls if you are testing it in development. You can leave the fields empty. Make sure your app is in development mode. If not turn off status from live.
No need to provide site url, app domains or valid redirect oauth uri.
My Solution works fine in localhost.....
For Site URLS use http://localhost/
and for App domains use localhost/folder_name
Rest everything is same .......it works fine
(though its shows redflag in App Domain..App is working fine)
It's easy go to the app dashboard under the facebook login tab click settings
then select Enforce HTTPs No, save settings
The application will run just fine in localhost: 3000, you just need to specify the https address on which the application will be live when it be in production mode.
Option 2 is provide the url or you heroku website which lets you have sample application in production mode.

How do I stop other domains from pointing to my domain?

I recently found out that there are other domain names pointing to my website (that don't belong to me) and I was wondering how people can stop/prevent this from happening. I'm hosting this on peer1 using IIS and I'm using ASP.NET C#.
Can I use an HttpModule or some other code to reject domain names that aren't mine?
Is there a better way?
You should activate name-based virtual hosting and only show your real website for the desired domain names. For all other names, you can display a suitable error message.
Details: Your webserver is contacted by its IP address. There is nothing you can do to stop that. Anyone can say, "connect to that IP address". For instance, anyone can register new domain names to point to your server's IP address. However, inside the request, there is a field Host with a name like www.example.com.
Upon receiving the request, your server may choose to inspect the Host field and deliver different content depending on that value. In the simplest case, the server ignores the field entirely and always prints out the same content. But in a more sophisticated set-up, so called "name-based (virtual) hosting", the server chooses the content depending on the hostname.
This is how shared webhosts work: There's a single server, but depending on the requested hostname it spits out a different website for each name.
Therefore, if you want to tie your server content to your hostname, you have to tell your server to produce your website only for your desired name, and to produce a different (error) website for all other cases.
In Apache this is trivial to configure, just check their documentation; for IIS I wouldn't know but I imagine it's equally simple.
If your hosting environment is IIS and you have admin access to it. Set your default website to show an error page and then create a new site with the host header matching your domain to point to your website.
This is my solution. It really works fast and solved my problem.
Insert this code in your .htacces
RewriteCond %{HTTP_HOST} !^www.higueyrd.com$
RewriteRule ^/?(.*) http://www.higueyrd.com/$1 [QSA,R=301,L]
Just put your domain.
In IIS there is a setting called bindings that allows you to select which hostnames your website will respond to. This feature allows an instance of IIS to host mulitple websites on a single IP address.
If you want your site to only work for http://example.com/ and http://www.example.com/, you should set the bindings to only work for "example.com" and "www.example.com".
The exception here is if you are using SSL. If you are, IIS cannot determine the hostname and you will most likely have to use a dedicated IP address for your site. In that scenario, user608576's solution will work. Although, I would put that code in your Global.asax file:
<%# Application Language="C#" %>
<script runat="server">
void Application_BeginRequest(Object sender, EventArgs args)
{
HttpRequest request = HttpContext.Current.Request;
HttpResponse response = HttpContext.Current.Response;
if( (request.Url.Host != "example.com") && (request.Url.Host != "www.example.com") )
{
response.Clear();
response.Write("Unauthorized domain name: " + request.Url.Host);
response.End();
}
}
</script>
As a temporary fix you can do this . May be on home page load or BeginRequest .
if(!Request.Url.Host.ToLower().contains("mysite.com")){
Response.Redirect("error.html");
}
If i remember right when i last check my sites cpanel i saw a feature that stopped redirections to my domain if checked. I´m using Hostso as my host so check their test cpanel for it.
Hope it helps alittle atleast :)
Fredrik wirth
if you want to handle in code then do it in Global.asax in BeginRequest as below
void Application_BeginRequest(object sender, EventArgs e)
{
if (!context.Request.Url.Host.ToLower().Equals("www.mydomain.com"))
{
context.Rewritepath("/invalidpage.aspx");
}
}
The other simple way is to specify a host headers in IIS for your website.
http://technet.microsoft.com/en-us/library/cc753195(v=ws.10).aspx
Note: I am writing through my mobile so consider spelling mistakes

Is it possible that Request.ServerVariables["HTTP_HOST"].ToString() can return a different host than what I see in the url bar

Say I have a remote page accessed through http://www.mypage.com/test.aspx. On that page I use the code Request.ServerVariables["HTTP_HOST"].ToString(). Is it possible that when I access the page the code can return a different url than that which I see in the url bar which is http://www.mypage.com/test.aspx? Any help would be appreciated. Thanks.
You could see any name that IIS has bound to your web instance. So, if your server is called "server1" and the IP address is 123.123.123.123 and all three of those are bound to your instance of IIS, you could see any of those values.
To look up what names are bound, open "Internet Information Services (IIS) Manager" (start, Administration tools), expand the tree till you see your sites. Find the one you are using. Right-click and choose "Bindings". Edit each of the bindings in the list. If they all say [IP address:] "All Unassigned", then your HTTP_HOST could be 1. the WWW address that you have configured via DNS, 2. the machine name 3. the IP address(es).
try to use:
HttpContext.Current.Request.ServerVariables["SERVER_NAME"]
i hope that this will be work.
I was also facing the issue with HttpContext.Current.Request.ServerVariables["HTTP_HOST"] and figured it out. The best way to retrieve the hostname is "HttpContext.Current.Request.Url.Host". It resovled my issue.
Thanks,
Raj
It is possible, yes. A isapi_rewrite module could modify the value of HTTP_HOST before your own code is able to inspect it.
Someone has already mentioned local rewriters (isapi_rewrite), but there are also remote ones, like an ISA Server publishing your server. It's a configuration thingie to send original host headers (what the client entered), or the ones entered in the publishing settings.

Categories

Resources