Windows authentication with Nodejs and IIS; issue getting username - node.js

I'm trying to setup a NodeJS web app with IIS to first use Windows Authentication, if not found then have the ability to use Anonymous Authentication to access the website.
Following this article https://github.com/tjanczuk/iisnode/issues/87, I promoted "the IIS server variables to X-iisnode-* HTTP request headers" as you can see in the config file below.
The problem is this: when Anonymous Authentication is off in IIS, all domain users get authenticated correctly, but Anonymous users can't access the website at all.
When I turn on Anonymous Authentication, all users access anonymously and the variable auth_user always comes back empty.
Is there a way to tell IIS, enforce Windows Authentication first, if not a domain user then use Anonymous Authentication?
I'm running the NodeJS app in a Windows 2012 server, iisnode, IIS 8
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="app.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="app">
<match url="^/*" />
<action type="Rewrite" url="app.js" logRewrittenUrl="false" />
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="http://website/">
<add key="http://website/" value="192.168.10.1/" />
</rewriteMap>
</rewriteMaps>
</rewrite>
<iisnode promoteServerVars="AUTH_USER,AUTH_TYPE" />
</system.webServer>
</configuration>
I also tried using node-sspi to get the user's information, which worked when I ran the application on stand-alone mode, it failed when I tried to run it behind IIS... has anybody tried this?

Related

Azure Node App (on Windows app service) Failing to Run

As a starting point for an application, I'm trying to get a simple Hello World running on Node in Azure (on a Windows app service). While the goal will be to push from an Azure DevOps pipeline, for now I'm just deploying from VS Code following this guide.
The application runs locally as expected, and the deploy to Azure is successfully moving the expected files (to include node_modules, package.json, app.js, and the various other code files). But the application is somehow failing to run correctly on Azure.
Any request results in a 500 error, whether for the root URL or explicitly for /app.js. (I was testing the latter to see if it just returned the file, but it's a 500 error.) I've enabled as much logging as I can find in Azure, but no more helpful information has surfaced. Just records of HTTP requests with generic 500 responses.
Some research led me to suspect that I need a web.config to tell IIS to use the node application. Following some samples found online, I've ended up with this:
<?xml version="1.0" encoding="utf-8"?>
<!--
This configuration file is required if iisnode is used to run node processes behind
IIS or IIS Express. For more information, visit:
https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->
<configuration>
<system.webServer>
<!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
<webSocket enabled="false" />
<handlers>
<!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
<add name="iisnode" path="app.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- Do not interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^app.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<!-- All other URLs are mapped to the node.js site entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="app.js"/>
</rule>
</rules>
</rewrite>
<!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<!-- Make sure error responses are left untouched -->
<httpErrors existingResponse="PassThrough" />
<!--
You can control how Node is hosted within IIS using the following options:
* watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
* node_env: will be propagated to node as NODE_ENV environment variable
* debuggingEnabled - controls whether the built-in debugger is enabled
See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
-->
<!--<iisnode watchedFiles="web.config;*.js"/>-->
</system.webServer>
</configuration>
Which makes sense to me. It tells IIS to use iisnode, the entry point file, URL mapping to use that entry point, etc. After re-deploy I'm still getting generic 500 responses.
I'm a bit out of ideas on where else to look or what else to try at this time. I suspect it should be straightforward to just build a Hello World app and deploy it and that I must just be missing something. But what?

NodeJS at Azure : systematic 404 error on resource files

we have a nodeJS webapp at Azure which works fine.
When streaming the server logs, any time I load a page, I get a bunch of 404 errors on all resources (images, css, etc..). Yet the page shows up properly.
Detailed errors show the following:
Requested URL https://[myappname]:80/settings.png
Physical Path D:\home\site\wwwroot\settings.png
Logon Method Anonymous
Logon User Anonymous
The requested URL is clearly wrong, it should be https://[myappname].azurewebsites.net/settings.png, which is the public URL for the given resources, and works fine.
This problem loads huge amounts of logs and makes it impossible to use Web Server logs for now.
thank you!
Edit: unlike this problem, my pages load properly and the resource files are well available.
Solved I have added the following handler to my web.config :
<add name="UrlRoutingModule-4.0" path="*" verb="*" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
I believe you need to configure a ruleset in your web.config for static file content.
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
Node.js applications running on Azure Web Apps are hosted on IIS via IISNode. So, a web.config file is required to config your application on IIS. If you deploy your app to Azure App Service via Continuous Deployment, the web.config file will be automatically generated by Azure. Or you can download the file from here.
I am posting default web.config just for your reference"
<?xml version="1.0" encoding="utf-8"?>
<!--
This configuration file is required if iisnode is used to run node processes behind
IIS or IIS Express. For more information, visit:
https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->
<configuration>
<system.webServer>
<!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
<webSocket enabled="false" />
<handlers>
<!-- Indicates that the app.js file is a node.js site to be handled by the iisnode module -->
<add name="iisnode" path="app.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- Do not interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^app.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<!-- All other URLs are mapped to the node.js site entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="app.js"/>
</rule>
</rules>
</rewrite>
<!-- bin directory has no special meaning in node.js and apps can be placed in it -->
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<!-- Make sure error responses are left untouched -->
<httpErrors existingResponse="PassThrough" />
<!--
You can control how Node is hosted within IIS using the following options:
* watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
* node_env: will be propagated to node as NODE_ENV environment variable
* debuggingEnabled - controls whether the built-in debugger is enabled
To debug your node.js application:
* set the debuggingEnabled option to "true"
* enable web sockets from the portal at https://manage.windowsazure.com/#Workspaces/WebsiteExtension/Website/aarontestnode/configure
* browse to https://aarontestnode.azurewebsites.net/app.js/debug/
See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
-->
<iisnode watchedFiles="web.config;*.js" debuggingEnabled="false" />
</system.webServer>
</configuration>
Hope it helps.
thanks for your answer.
I have nearly the same web.config, automatically generated. There is just a slight difference in the rule you pointed :
<rule name="StaticContent">
<action type="Rewrite" url="public{PATH_INFO}"/>
</rule>
My server code includes this:
app.use(express.static(path.join(__dirname, 'public')));

http or https in request path to a node server creates an error

I am trying to make corsanywhere work on Azure, and actually it works if I request something like this:
https://myserver.azurewebsites.net/www.remoteserver.com/query=john
But if I call this, I get a 500 error and I don't know how to track it (no error is produced in the logs in this case):
https://myserver.azurewebsites.net/http://www.remoteserver.com/query=john
This kind of request works well on the corsanywhere demo site or when I run my node app on my dev machine.
Update:
Node on Azure needs a web.config file. Here is mine:
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="DynamicContent">
<match url="/*" />
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I am wondering if this could be the culprit...
Thanks for your help
In Azure App Service (Windows OS), the characters :/ are not allowed in the URL path. This was discussed on SO before: Azure websites throw 500 error when there is a colon in the URL.
You could try a solution in #TimBunting's answer, or host your application on a Linux App Service instead.

Disable Access to Node.js Source Code files in Azure

I'm building a basic website with Node.js, and I don't want anyone to be able to access my server-side source code (it contains login credentials for a database). My main application is in a file called 'app.js' in the root directory where the application is run. If I browse to mysite.com/app.js, the source code file is served. Is there a way to disallow access to certain files with Node.js or just in general? The site is hosted on Microsoft Azure, if that makes a difference (my research seems to indicate that Microsoft and Apache handle this differently).
Basically, Azure uses IIS to serve your Node.js app. So, you'll need to add the IIS configuration file called web.config to app's root folder to restrict access to the server-side source code.
web.config
<?xml version="1.0" encoding="utf-8"?>
<!--
This configuration file is required if iisnode is used to run node processes behind
IIS or IIS Express. For more information, visit:
https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->
<configuration>
<system.webServer>
<!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
<webSocket enabled="false" />
<handlers>
<!-- Indicates that the app.js file is a node.js site to be handled by the iisnode module -->
<add name="iisnode" path="app.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- Do not interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^app.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<!-- All other URLs are mapped to the node.js site entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="app.js"/>
</rule>
</rules>
</rewrite>
<!-- bin directory has no special meaning in node.js and apps can be placed in it -->
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<!-- Make sure error responses are left untouched -->
<httpErrors existingResponse="PassThrough" />
<!--
You can control how Node is hosted within IIS using the following options:
* watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
* node_env: will be propagated to node as NODE_ENV environment variable
* debuggingEnabled - controls whether the built-in debugger is enabled
To debug your node.js application:
* set the debuggingEnabled option to "true"
* enable web sockets from the portal at https://manage.windowsazure.com/#Workspaces/WebsiteExtension/Website/aarontestnode/configure
* browse to https://aarontestnode.azurewebsites.net/app.js/debug/
See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
-->
<iisnode watchedFiles="web.config;*.js" debuggingEnabled="false" />
</system.webServer>
</configuration>
In app service you can declare key value pairs including connection strings in the "Application Settings" blade. The same will be available as environment variables for Java, Node, PHP and Python applications. This way they will be secure. https://learn.microsoft.com/en-us/azure/app-service-web/web-sites-configure
2 problems here:
Restricting Access To Static Files
Protecting Credential Information
Restricting Access To Static Files
Both with Apache and Nginx it is possible to specify how to serve static assets. requests for static assets should map to a specific assets folder. So that requests to yourdomainname.com/myfile.js will map to /path/to/static/assets/myfile.js. Research their docs to see how to to this.
Protecting Credential Information
You need to keep your credential information (API Key, Database password, etc...) outside of your code repo. To do this, you can use .env files with the dotenv package

Blocking access to a url by IP address

I am trying to block all access to the admin url for Umbraco (v7.2.8) for security reasons. I have the below in my web.config file, but it does not work. It is blocking all access to that url, even from the specified IP. I am running this locally on my machine from Visual Studio, so I am not sure what IP the site thinks I am coming in on, but I have tried all of them. Does this web.config look ok?
<rewrite>
<rules>
<rule name="Restrict URL" enabled="true" stopProcessing="true" >
<match url="^umbraco($|/)"/>
<conditions logicalGrouping="MatchAll">
<add input="{REMOTE_ADDR}" pattern="^192\.168\.8\.100$" negate="true" />
</conditions>
<action type="Redirect" url="/no-access/" />
</rule>
</rules>
Any pointers would be greatly appreciated! I will be deploying this to Azure eventually but wanted to get this working first. Perhaps it's because i'm running it locally?
EDIT: I have tried the ipSecurity solution but receive the below error. I have installed the IP Security component for IIS. I am running the site from Visual Studio so I am not sure I can test it from here on the express service that VS uses? I have also changed to 'allow' in the following file;
%windir%\system32\inetsrv\config\applicationHost.config
This is easier to accomplish with system.webServer >> security >> ipSecurity settings in the web.config inside a location element:
<location path="umbraco">
<system.webServer>
<security>
<ipSecurity allowUnlisted="false" denyAction="NotFound">
<add allowed="true" ipAddress="192.168.8.100" />
</ipSecurity>
</security>
</system.webServer>
</location>
See IIS IP Security more more details. IP Security is enabled by defualt on Azure WebApps.

Resources