ColdFusion REST API Enable CORS - rest

I am trying to build a REST API using coldfusion components and I can't figure out how to enable CORS. I am using IIS 10 and ColdFusion 2016. I can't find anywhere in IIS to configure CORS following instructions on google and I don't see anywhere under CF admin settings to enable CORS, so I figured I would try to enable CORS in my API instead of fiddling with configuration in each environment I deploy this to (qa, uat, prod).
This is what my application.cfc currently looks like and you can see in the onRequestStart I am attempting to set the headers (two ways I've tried)
<cfscript>
component output="false" {
this.name = ....
public boolean function onApplicationStart() {\
restInitApplication( ... );
return true;
}
public void function onApplicationEnd(ApplicationScope) {
return;
}
public void function onMissingTemplate(targetPage) {
return;
}
public void function onRequestStart(targetPage) {
cfheader(name="Access-Control-Allow-Origin", value="*");
// i've also tried ...
GetPageContext().getResponse().addHeader("Access-Control-Allow-Origin","*");
}
public void function onSessionStart() {
return;
}
public void function onSessionEnd(sessionScope, applicationScope) {
return;
}
}
</cfscript>

I would recommend installing the IIS CORS module - reference. Here is a snippet from that reference:
Functionality Overview
The Microsoft IIS CORS Module is an extension that enables web sites to support the CORS(Cross-Origin Resource Sharing) protocol.
The IIS CORS module provides a way for web server administrators and web site authors to make their applications support the CORS protocol. With this module, developers can move CORS logic out of their applications and rely on the web server. The module's handling of CORS requests is determined by rules defined in the configuration. These CORS rules can be easily defined or configured making it simple to delegate all CORS protocol handling to the module.
IIS CORS module is a server-side CORS component
The CORS protocol governs client/server communication. Usually, web browsers act as the client-side CORS component, while the IIS server works as the server-side CORS component with the help of the IIS CORS module.
A CORS request occurs when a protocol aware client, such as a web browser, makes a request to a domain (origin) that differs from the current domain. This scenario is known as a cross-origin request. When CORS is not used, cross-origin requests will be blocked by the client. When the CORS module is used, IIS will inform clients whether a cross-origin request can be performed based on the IIS configuration.
Don't try implementing this from ColdFusion, let the web server do what it is designed to do. Once you have the module installed you can create the rules you want within the web.config files for any/all IIS sites.
Sample config file:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="*" />
<add origin="https://*.microsoft.com"
allowCredentials="true"
maxAge="120">
<allowHeaders allowAllRequestedHeaders="true">
<add header="header1" />
<add header="header2" />
</allowHeaders>
<allowMethods>
<add method="DELETE" />
</allowMethods>
<exposeHeaders>
<add header="header1" />
<add header="header2" />
</exposeHeaders>
</add>
<add origin="http://*" allowed="false" />
</cors>
</system.webServer>
</configuration>
You can download the IIS CORS module from here.

Related

CORS errors when deploying signalR notification Hub to IIS

My signalR Hub can run fine in VS2019 debug mode on secure port 44311, but as soon as I publish it to my local IIS on my dev box, the ../hub/negotiate fails with a CORS policy exception.
ex. in debug mode, the IIS tray
and signalr Hub starts fine:
Now onto my local Window 10 IIS settings where I deployed the signalR Hub project:
I setup the https bindings
I successfully setup the SSL Cert, and set the Require SSL checkbox:
I Restart my IIS Website, and Browse on 44311 to test
But sure enough, my app cannot connect to the HUB:
Access to XMLHttpRequest at 'https://localhost:44311/hub/negotiate?negotiateVersion=1' from origin 'http://localhost:4200' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
POST https://localhost:44311/hub/negotiate?negotiateVersion=1 net::ERR_FAILED
Yet in my code I injected CORS:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NotificationHub.Hubs;
namespace NotificationHub
{
public class Startup
{
readonly string MyAllowedSpecificOrigins = "_myAllowedSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowedSpecificOrigins,
builder => {
builder.WithOrigins("https://localhost:4200", "localhost:4200")
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => true);
}
);
});
services.AddSignalR(hubOptions => {
hubOptions.EnableDetailedErrors = true;
hubOptions.KeepAliveInterval = System.TimeSpan.FromMinutes(1000);
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(MyAllowedSpecificOrigins);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<Notifications>("/hub", options => {
options.Transports = HttpTransportType.WebSockets | HttpTransportType.LongPolling;
});
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Notification HUB has started!");
});
});
}
}
}
I'm not sure at this point if it's a coding issue (i.e. not setting CORS properly), or a deployment issue.
Help is appreciated.
thanks.
UPDATE
As per the suggested answer below, my CORS issue is resolved when deployed to IIS:
Install cors for IIS: https://www.iis.net/downloads/microsoft/iis-cors-module
Add below <customHeaders> to web.config
However, I still CANNOT connect to the hub successfully in IIS deployment mode (http://localhost:55271/hub/negotiate?negotiateVersion=1 throws 404 not found); however debug works fine.
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost:4200" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Request-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag,XMLHttpRequest,x-requested-with" />
<add name="Access-Control-Allow-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag,XMLHttpRequest,x-requested-with" />
<add name="Access-Control-Request-Method" value="GET,POST,HEAD,OPTIONS" />
</customHeaders>
</httpProtocol>
make sure you enabled iis .net feature. enable directory browsing in iis for the site:
1)Start IIS Manager.
2)In IIS Manager, expand the server name, expand Web sites, and then select the website.
3)In the Features view, double-click Directory Browsing.
4)In the Actions pane, click Enable.
add below code in web.config file:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://my-external-app-domain.com" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Request-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag" />
<add name="Access-Control-Request-Method" value="GET,POST,HEAD,OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
install cors module in iis by using web platform installer or from below link:
https://www.iis.net/downloads/microsoft/iis-cors-module
Update:
Add below to web.config:
HttpRequest,x-requested-with were both needed in "Access-Control-Request-Headers" . In addition, I inserted header name="Access-Control-Allow-Headers" with same values as Request-Headers.

JMeter changing my namespace

I'm trying to use JMeter to invoke a RPC/SOAP Web service and when I invoke the service my namespaces are mangled from the actual values to NS1.
<?xml version="1.0" encoding="UTF-8"?>
<wpc:invoke xmlns:wpc="http://wpc.ibm.com">
<wpc:envelope communicationVersion="5.3">
<wpc:WPCResponseType>asynchronous</wpc:WPCResponseType>
<wpc:wpcHeader>
<wpc:companyName>mycompany</wpc:companyName>
<wpc:wpsUserID>me</wpc:wpsUserID>
<wpc:wpcUserID>wpcUsername</wpc:wpcUserID>
<wpc:password />
<wpc:messageIdentifier>9E2FA100-BE54-11E5-8A91-BF48E24665E0</wpc:messageIdentifier>
<wpc:timestamp>2016-01-18</wpc:timestamp>
<wpc:supplierId><![CDATA[0Z188]]></wpc:supplierId>
<wpc:localeForDisplay>en_US</wpc:localeForDisplay>
<wpc:localeRestriction>en_US</wpc:localeRestriction>
</wpc:wpcHeader>
<wpc:wpcBody>
<wpc:wpcCommand mode="ASYNC" type="UPLOAD">
<wpc:wpcCatalogName>Item Transaction Catalog</wpc:wpcCatalogName>
<wpc:wpcFileDocStorePath>test_data/upload/0003_items.csv</wpc:wpcFileDocStorePath>
<wpc:wpcUpdateOnly>false</wpc:wpcUpdateOnly>
</wpc:wpcCommand>
</wpc:wpcBody>
</wpc:envelope>
</wpc:invoke>
Changes to:
<?xml version="1.0" encoding="UTF-8"?>
<ns1:invoke xmlns:ns1="http://wpc.ibm.com">
<ns1:envelope communicationVersion="5.3">
<ns1:WPCResponseType>asynchronous</ns1:WPCResponseType>
<ns1:wpcHeader>
<ns1:companyName>mycompany</ns1:companyName>
<ns1:wpsUserID>me</ns1:wpsUserID>
<ns1:wpcUserID>wpcUsername</ns1:wpcUserID>
<ns1:password/>
<ns1:messageIdentifier>9E2FA100-BE54-11E5-8A91-BF48E24665E0</ns1:messageIdentifier>
<ns1:timestamp>2016-01-18</ns1:timestamp>
<ns1:supplierId><![CDATA[0Z188]]></ns1:supplierId>
<ns1:localeForDisplay>en_US</ns1:localeForDisplay>
<ns1:localeRestriction>en_US</ns1:localeRestriction>
</ns1:wpcHeader>
<ns1:wpcBody>
<ns1:wpcCommand mode="ASYNC" type="UPLOAD">
<ns1:wpcCatalogName>Item Transaction Catalog</ns1:wpcCatalogName>
<ns1:wpcFileDocStorePath>test_data/upload/0003_items.csv</ns1:wpcFileDocStorePath>
<ns1:wpcUpdateOnly>false</ns1:wpcUpdateOnly>
</ns1:wpcCommand>
</ns1:wpcBody>
</ns1:envelope>
</ns1:invoke>
There must be a setting in JMeter to keep the message from being transformed from my original meaningful namespace to this arbitrary namespace called NS1? When the message is received at the target endpoint it cannot parse the request because of this semantic error.
Any/all replies are appreciated!
MG
JMeter should not change anything in the request body, maybe it is an issues with your web service? Double check the request which is being sent by JMeter using a sniffer tool like Wireshark
In any case try switching to HTTP Request sampler, this is recommended way of sending web service requests (just don't forget to add HTTP Header Manager to send Content-Type and SOAPAction headers).
References:
JMeter User's Manual: Building a SOAP WebService Test Plan
Testing SOAP/REST Web Services Using JMeter

Redirect old domain to new domain keeping url

We are releasing a new version of our Web app and in the process doing a branding change with a new domain also.
Both our apps are hosted in Azure.
Current App - Cloud Service
New App - Azure Website
What I want to achieve is redirect any old links from the old domain to the new domain while keeping the url portion.
Example:
User visits
https://my.currentdomain.com/any/link
and will be directed to
https://my.newdomain.io/any/link
Do I do a CNAME from currentdomain to newdomain and then a URL Rewrite in my web.config??
Thanks!
Update - I've test this locally and it does what I'm looking for. I'll just point the cname of the old domain to the new domain and this redirect should pick up the links.
<rule name="Redirect to new domain" stopProcessing="true">
<match url="^(.*)$" />
<conditions>
<add input="{HTTP_HOST}" matchType="Pattern" pattern="^olddomain(:\d+)?$" />
</conditions>
<action type="Redirect" url="https://my.newdomain.io/{R:1}" redirectType="Permanent" />
</rule>
The fact that you host your application in Azure has minimal to no impact on the solution you are going to find.
When you do such things, you usually want to also keep all the credits that you have in the search engines. And you can only achieve that if your https://my.current.domain.com/any/link does a HTTP 301 Redirect Permanent to the new location.
Depending on the size and complexity of your project this can be a trivial task or not so easy.
One option, which is valid only if you want to redirect few (like a dozen) links. You can do that directly in your Web.Config file:
<location path="any/link">
<system.webServer>
<httpRedirect enabled="true" destination="https://my.newdomain.io/any/link" httpResponseStatus="Permanent" />
</system.webServer>
</location>
This of course makes no sense when you have a bunch of links, or even a whole CMS behind the scenes. If this is the case, I would opt-in for writing a custom HTTP Module for IIS. This module will have the sole purpose of inspecting the incoming URI and either let it further, or generate HTTP 301 redirect.
If you are using the latest and the greatest from Microsoft, the same (custom HTTP Module) can be achieved with a custom OWIN Middleware.
If it is just domain change, all paths and query strings are to be kept, check out this good article how can you do this with URL Rewrite under IIS.
add this code to your header file:
<script type="text/javascript">
// Get Current URL
var url = window.location.href;
// Replace domain in URL
var newurl = url.replace("olddomain.com", "newdomain.com");
// Redirect to new URL
document.location = newurl;
</script>

httpOnly cookie

I had done web scan for an application(built in struts and hibernate framework) deployed in jboss 5 which reported "Set-cookie does not use HTTPOnly keyword. The web application does not utilize HTTPOnly cookies". What does it mean. I looked for some post and just added one line in my jboss/deploy/jbossweb.sar/context.xml as
<SessionCookie secure="true" useHttpOnly="true" >
After setting that, I am getting error while running the application. Is there any configuration that I am missing?
try this:
<SessionCookie secure="true" httpOnly="true" />
What does it mean
The HttpOnly flag in a http response header indicates to the browser that client-side access to the JSESSION_ID or other session-cookie type identifier should not be permitted. What this is intended to prevent is a malicious access to the session token via client side scripts in an XSS(or other attack involving session hijacking from the client side). Currently almost all major browsers support this flag(see this list for supporting browsers), but it's simply ignored in browsers that don't support it. See more info on this at the OWASP site
Setting it up is similar for tomcat and forks of it, including Jboss, by including the following in your context file:
<session-config>
<cookie-config>
<http-only>true</http-only>
</cookie-config>
</session-config>
or
<SessionCookie secure="true" httpOnly="true" />

WCF Proxy Using Post Even Though WebGet Attribute is Specified (Only when called from another WCF service) - Causes 405 Error

I have a Restful WCF service sitting on another server configured with the WebGet attribute to respond to the HTTP Get method. I know the service works correctly because I can call the service directly through the browser and manually do a Get with Fiddler and receive a correct response.
I have an Asp.NET project on my local machine that is calling this service with the following code:
Proxy Interface 'IProductService':
using System.ServiceModel;
using System.ServiceModel.Web;
namespace Hugo.Infrastructure.Services.Products
{
[ServiceContract]
[XmlSerializerFormat]
public interface IProductService
{
[OperationContract(Name = "GetProductById")]
[WebGet(UriTemplate = "Products/Titles/{id}",
ResponseFormat = WebMessageFormat.Xml,
RequestFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Bare)]
TitleDto GetTitleById(string id);
}
}
Implementation 'ProductService':
using System.ServiceModel;
namespace Hugo.Infrastructure.Services.Products
{
public class ProductService : ClientBase<IProductService>, IProductService
{
public TitleDto GetTitleById(string id)
{
return Channel.GetTitleById(id);
}
}
}
Related Web.config section:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<baseAddressPrefixFilters>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
...
<client>
<endpoint address="http://server/directory/product.svc" bindingConfiguration="ProductServiceBinding" binding="webHttpBinding" behaviorConfiguration="productService" contract="Project.Infrastructure.Services.Products.IProductService" name="ProductServiceRest" />
</client>
<behaviors>
...
<endpointBehaviors>
<behavior name="productService">
<webHttp />
</behavior>
...
</endpointBehaviors>
</behaviors>
</system.serviceModel>
This works fine when we call the method from a page within the project, however it errors out on this line return Channel.GetTitleById(id); when we call it from within a WCF service from the same project. The error we receive is an HTTP 405 'Method not allowed' error. When we look at the IIS logs on the remote server we see that the ProductService proxy is making an HTTP GET request when the method call is initiated from the page but it is making an HTTP POST request when the method is called from the WCF service. The POST method is not configured on the service, thus the 405 error.
Even when the page and the service are in the same folder and namespace we still receive the same error from the service. If we use a classic asmx soap service instead then a GET call is made and the service executes and responds correctly. If we manually do a get from the WCF service using the System.Net.WebRequest object, the service call succeeds.
Bottom line, the WCF client proxy tries to do a POST instead of a GET when used from within another WCF Rest service but works correctly when used from a page or pretty much anywhere else.
Help please!
This might work:
http://www.rgoarchitects.com/nblog/2008/09/28/AnotherWCFGotchaCallingAnotherServiceresourceWithinACall.aspx