How to get the called address of a WCF Rest Request? - wcf

I have implemented a REST Webservice which returns (after an authentication via RFC 2617 HTTP Digest Authentication) an XML document with xlink's to the related resources.
Here's an example of a request:
http://172.32.42.53:8080/Service.svc/user/123
A result could look like this:
<?xml version="1.0" encoding="utf-8"?>
<UserList xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<User>
<ID>2</ID>
<UserName>CHI</UserName>
<OutlineLink xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://demo:8080/Service.svc/Users/2/Outline/" cache="no"/>
<SettingsLink xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://demo:8080/Service.svc/Users/2/Settings/" cache="no"/>
<CatalogsLink xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://demo:8080/Service.svc/Users/2/Catalogs/" cache="no"/>
<LastName>Test</LastName>
</User>
</UserList>
So, the problem now is:
If the user calls the webservice via the IP address, the first handshake will be over the ip address and not the DNS name. So the authentication does only work if the second call (to the specified resource) will be over the IP address again. I tried it with following command:
OperationContext.Current.IncomingMessageProperties.Via.ToString();
But my webservice returns always the dns of the server and not the "called address".
Is there a possibility to get the called address? So I can dynamically return the called address (ip or dns). Would be great to get a solution. Relative URLs aren't allowed for xlinks.
Thanks for help!

Can you try to retrieve the called address from the request's server variables? I guess your web service needs to be in asp.Net compatibility mode to access this. Something like "REMOTE_HOST", "HTTP_HOST", "SERVER_NAME", etc...
Check this link for list of server variables

Related

PingAccess issues with proxying target sites with HTTP/HTTPS mix

I'm trying to get PingAccess set up as a proxy (let's call the PA host
pagateway) for a couple of applications that share a Web Session. I want all access to come via the PA pagateway and use HTTPS, but the back end systems are not HTTPS.
I have two sites defined, app1:8080 and app2:8080. Both are set to "secure" = no and "use target host header" = yes.
I have listeners defined on ports 5000 and 5001 that are both set to "secure" = yes.
The first problem I found is that when I access either app in this way (e.g. going to https://pagateway:5000), after successfully authenticating with PingFederate I end up getting redirected to the actual underlying host name (e.g. http://app1:8080), meaning any subsequent interactions with the app are not via PingAccess. For users outside the network they wouldn't even be able to do that because the app1 host wouldn't even be visible or accessible.
I thought maybe I needed to turn off "Use target host header" to false but Chrome prompts me to download a file that contains NAK, ETX, ETX, NUL, STX, STX codes, and in the PA logs I get an SSL error:
2015-11-20 11:13:33,718 DEBUG [6a5KYac2dnnY0ZpIl-3GNA] com.pingidentity.pa.core.transport.http.HttpServerHandler:180 - IOException reading sourceSocket
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at sun.security.ssl.InputRecord.handleUnknownRecord(InputRecord.java:710)
...
I'm unsure exactly which part of the process the SSL error is coming from (between browser and pagateway, or pagateway and app1). I'm guessing maybe app1 is having trouble with the unexpected host header...
In another variation I turned off SSL on the PA listener (I also had to change the PingAccess call-back URL in the PingFederate client settings to be http). But when I accessed it via http://pagateway:5000 I got a generic PingFederate error message in the browser and a different error in the PA logs:
2015-11-20 11:37:25,764 DEBUG [DBxHnFjViCgLYgYb-IrfqQ] com.pingidentity.pa.core.interceptor.flow.InterceptorFlowController:148 - Invoking request handler: Scheme Validation for Request to [pagateway:5000] [/]
2015-11-20 11:37:25,764 DEBUG [DBxHnFjViCgLYgYb-IrfqQ] com.pingidentity.pa.core.interceptor.flow.InterceptorFlowController:200 - Exception caught. Invoking abort handlers
com.pingidentity.pa.sdk.policy.AccessException: Invalid request protocol.
at com.pingidentity.pa.core.interceptor.SchemeValidationInterceptor.handleRequest(SchemeValidationInterceptor.java:61)
Does anyone have any idea what I'm doing wrong? I'm kind of surprised about the redirection to the actual server name, to be honest, but after that I'm stumped about where to go from here.
Any help would be appreciated.
Have you contacted our support on this? It's sounding like something that will need to be dug into a bit deeper - but some high level suggestions I can make:
Take a look at a browser trace to determine when the redirect is happening to the backend site. Usually this is because there's a Location header in a redirect from the backend web server that (by nature) is an absolute URL but pointing to it instead of the externally facing hostname.
A common solution to this is setting Target Host Header to False - so it will receive the request unmodified from the browser, and the backend server should know to represent itself as that (if it behaves nicely behind a proxy).
If the backend server can't do that (which it sounds like it can't) - you should look at assigning rewriting rules to that application. More details on them are available here: https://support.pingidentity.com/s/document-item?bundleId=pingaccess-52&topicId=reference%2Fui%2Fpa_c_Rewrite_Rules_Overview.html. The "Rewrite Response Header Rule" in particular will rewrite Location headers in HTTP redirects.
FYI - The "Invalid request protocol." error you're seeing at bottom of your description could be due to a "Require HTTPS" flag on your defined Application.
Do you have the same issue if you add a trailing slash at the end (https://pagateway:5000/webapp/)? Your application server will rewrite the URL based on what it thinks is the true host. This is to get around some security related issues around directory listing.
Which application server are you using? All app servers are unique, but I'll provide instructions on how to resolve this with Tomcat.
Add a global rule that forces the application server to use the external facing host name. Here is a sample Groovy script:
def header = exc?.request?.header;
header?.setHost("pf.pingdemo.com:443");
anything();
In Tomcat's server.xml, add scheme="https" to the connection:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443" scheme="https" />
Cheers,
Tam

Webservice is not working anymore after changed firewall hardware (Dell sonicwall)

We have built for a customer websiteB in c# asp.net. There is also another website in php which is builded by another company. This is websiteA. The enduser is try to log in on websiteA. Underwater there is a request to a webservice on websiteB with username/password as parameters. WebsiteB try to get authenticate the credentials and return a message. WebsiteA is running on some server of another company. WebsiteB is running on our server in the datacenter. This scenario was always working!
No we have changed the firewall hardware in our datacenter. We have now Dell SonicWall. In the beginning the certificates were not working of our webservice. We have fix this. When you run our webservice in the browser the certifcate is OK (there is no red background in the url).
This is the url of my webservice:
https://service.myCompany.com/PortalService.svc
I ask the other company to give me some logging or an exception from there side. They do not get an exception. They got an empty array. They have printed some logging for me after a request:
We have also enabled the logging on the webservice. This is the logging after trying to login on websiteA.
Request to webservice:
<MessageLogTraceRecord>
<HttpRequest xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<Method>POST</Method>
<QueryString></QueryString>
<WebHeaders>
<Connection>Keep-Alive</Connection>
<Content-Length>574</Content-Length>
<Content-Type>text/xml;charset=UTF-8</Content-Type>
<Accept>*/*</Accept>
<Authorization>Basic bWlqbnNlaF9uZXRieXRlczojbjN0Ynl0MzU=</Authorization>
<Host>service.MyCompany.com</Host>
<User-Agent>Jakarta Commons-HttpClient/3.1</User-Agent>
<SOAPAction>"http://schemas.MyCompany.com/SecurityService/SecurityService/LoginUsernamePassword"</SOAPAction>
</WebHeaders>
</HttpRequest>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="http://schemas.MyCompany.com/SecurityService">
<soapenv:Header>
<To soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">https://mycompanyapp01.dmz.mycompany.local/SecurityService.svc</To>
<Action soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://schemas.MyCompany.com/SecurityService/SecurityService/LoginUsernamePassword</Action>
</soapenv:Header>
<soapenv:Body>
<test:LoginUsernamePassword>
<test:Username><![CDATA[testuser#mycompany.com]]></test:Username>
<test:Password><![CDATA[#test!]]></test:Password>
<test:ReturnToken>true</test:ReturnToken>
<test:ReturnProfile>true</test:ReturnProfile>
<test:ReturnRoles>true</test:ReturnRoles>
</test:LoginUsernamePassword>
</soapenv:Body>
</soapenv:Envelope>
</MessageLogTraceRecord>
Response from webservice:
<MessageLogTraceRecord>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://schemas.MyCompany.com/SecurityService/SecurityService/LoginUsernamePasswordResponse</Action>
</s:Header>
<s:Body>
<LoginUsernamePasswordResponse xmlns="http://schemas.MyCompany.com/SecurityService">
<LoginUsernamePasswordResult xmlns:d4p1="http://schemas.MyCompany.com/datacontracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<d4p1:Token>PJ%2bNtW0Kpy%2frd945r3Q0ziQpoax%2bNIiPNXC8obx%2fl73D2MPTvwFA9TqDtHNzXPq7</d4p1:Token>
<d4p1:UserProfile>
<d4p1:DisplayNameFormal>Test</d4p1:DisplayNameFormal>
<d4p1:DisplayNameInformal>Test</d4p1:DisplayNameInformal>
<d4p1:Email>test#mycompany.com</d4p1:Email>
<d4p1:IsErkendAdviseur>false</d4p1:IsErkendAdviseur>
<d4p1:UserID>testuser#mycompany.com</d4p1:UserID>
</d4p1:UserProfile>
<d4p1:UserRoles xmlns:d5p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d5p1:string>Test Medewerker</d5p1:string>
</d4p1:UserRoles>
</LoginUsernamePasswordResult>
</LoginUsernamePasswordResponse>
</s:Body>
</s:Envelope>
</MessageLogTraceRecord>
I have also started the wcf client tool (wcfTestClient.exe). I add the webservice url (https://service.myCompany.com/PortalService.svc). I got this exception:
Error: Cannot obtain Metadata from https://service.MyCompany.com/SecurityService.svc?wsdl
If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange
Error URI: https://service.MyCompany.com/SecurityService.svc?wsdl Metadata contains a reference that cannot be resolved: 'https://service.MyCompany.com/SecurityService.svc?wsdl'.
The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic realm="service.MyCompany.com"'.
The remote server returned an error: (401) Unauthorized.HTTP GET Error URI: https://service.MyCompany.com/SecurityService.svc?wsdl
The document was understood, but it could not be processed. - The WSDL document contains links that could not be resolved. - There was an error downloading 'https://myCompanyapp01.dmz.myCompany.local/SecurityService.svc?wsdl=wsdl0'. - The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. - The remote certificate is invalid according to the validation procedure.
Why do I see the intern url in the exception while I testing the public url:
intern url: https://myCompanyapp01.dmz.myCompany.local/SecurityService.svc?wsdl
public url: https://service.MyCompany.com/SecurityService.svc?wsdl
The public url has a certificate. The intern url not. When you try the intern url you got a red background in the browser.
I think this whole problem is our firewall. I think there is some restricted option on SOAP outbound messages. Because websiteA which is doing the request dont get an exception. They get also an answer, but it is empty. So it looks like the firewall has make it empty.
What do you think of this problem?
Your WSDL is referencing/including files on the internal app server. Try using a flattened wsdl.

NServiceBus Gateway public url

In my application I have a setup with NServiceBus Gateway on an endpoint and I was able to access it using the url http://localhost/{Endpoint name} from the same machine.
My question is what I have to do to access that endpoint from external machines using the public ip address or domain name.
For e.g. how can I access the gateway endpoint with url http://{My Public ip address}/{Endpoint name}
I found the answer by myself, what you have to do is simply change the channel address to the domain name you want
<GatewayConfig>
<Channels>
<Channel Address="http://{Your domain name}/{Endpoint name}/" ChannelType="Http" Default="true"/>
</Channels>
</GatewayConfig>

Getting request and creating HTTP response using Tomcat

I am currently trying to use embeded Tomcat for my application and am trying to set it up to get the URL of the http request.
Some Background:
I am using the same code as in the first answer for the post here : Howto embed Tomcat 6?
The only change I have made is :
private String catalinaHome = "/home/xyz/tomcat"; // This dir is created and has full access permissions
Also , I am looking at: http://tomcat.apache.org/tomcat-5.5-doc/catalina/docs/api/org/apache/catalina/startup/Embedded.html
There are no server.xml and tomcat-users.xml that I could find, so I created a tomcat-users.xml since I was getting an exception :Memory database file /home/xyz/tomcat/conf/tomcat-users.xml cannot be read .
tomcat-users.xml:
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>
The code uses container.setRealm(new MemoryRealm());
It appears from here : http://tomcat.apache.org/tomcat-4.1-doc/catalina/funcspecs/fs-memory-realm.html that I should have a server.xml file and there should already be one created by default.
1] Do I need to create a server.xml, what should be the default in it ?
I have put a file with default from here : http://www.akadia.com/download/soug/tomcat/html/tomcat_server_xml.html , but just want to know what is the right thing to do ?
2]When I access http://localhost:8089/mywebapp/index.html, all i get is The requested resource () is not available, though I have an index.html page at the "webappDir" in the code
3] My only need from the embedded tomcat is to intercept so as to get the URL passed to tomcat in my code. I can then parse the URL [do my stuff] and then create a http payload and send an http response back.
I would appreciate any pointers, especially for 3] ?
Thanks!
Ok, for your first question, yo do not need server.xml. If you check the code of your initial post they are setting the parameters there. So that is what server.xml would encapsulate. In reality what happens is that Tomcat will parse server.xml for the properties you are defining on your java file where you instanciate the catalina call to start. But since it is embedded you are setting all those parameters on you class instead.
For your second question, check your logs directory and see what is being parsed. Something is happening after your service starts because it should already redirect you once you call the port. either way, just try http://localhost:8089 and see what you get back in return from tomcat. It should give you some kind of response back from the server itself.
if you do it like this "http://localhost:8089/mywebapp/index.html" you are trying to access a created context, and that might not be configured correctly, but that is just a guess right now.
Try this first and tell me what you get back. we can troubleshoot from this point and see if I can help more in that sense.
Quick question, is this windows or linux you are installing on?
If it is linux the configurations filea are located usually on /etc/tomcat6. (at least on ubuntu they are). Reply back with the version you have installed. I might be able to help you out.
I guess I should also elaborate here a little more. Tomcat is a service in linux as well, so in ubuntu you have to start tomcat in order to access it.
$: sudo service tomcat6 start
then it starts tomcat on port 8080 (usually if not changed) of your localhost. hence you type localhost:8080 to access the website for configuration of tomcat that gives you a It works prompt for you.
Let me know if you have more questions, I will try to respond to the best of my knowledge

Restrict access to specific URL (Apache Tomcat)

How can I restrict access to a specific URL (it is a Tomcat Application Server)? e.g. http://localhost:8081/application cannot be accessed by an user except a specified IP (that is the calling service)
Quote:
The Remote Address filter, org.apache.catalina.valves.RemoteAddrValve, allows you to compare the IP address of the requesting client against one or more regular expressions to either allow or prevent the request from continuing based on the results of this comparison. A Remote Address filter can be associated with a Tomcat Engine, Host, or Context container.
org.apache.catalina.valves.RemoteAddrValve.
http://www.oxxus.net/tutorials/tomcat/tomcat-valve.htm
So, you'd need something along the lines of
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="<your-ip-here>"/>
For possible values, see
http://tomcat.apache.org/tomcat-6.0-doc/config/valve.html#Remote_Address_Filter
You should be able to set this in the WEB-INF/web.xml for your application, see
http://oreilly.com/java/archive/tomcat.html
Goto following path: C:\Program Files\Apache Software Foundation\Tomcat 6.0\conf\Catalina\localhost\
Under this path you find "manager.xml" file.
Edit "manager.xml" file, with following content:
<Context path="/manager" debug="0" privileged="true">
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127.0.0.1,10.100.1.2"/>
<!-- Link to the user database we will get roles from
<ResourceLink name="users" global="UserDatabase" type="org.apache.catalina.UserDatabase"/>
-->
</Context>
Save and run server. You got it.
NOTE :
127.0.0.1 MEANS YOUR SYSTEM IP
10.100.1.2 -THIS IS YOUR FRIENDS IP.