we will have a website created by an outsourcing company, that website will send some information in JSON payload to our RESTful web service. The user will do login and authentication on that website, so we don't want to know the username and password of the user. And what we need is make sure the JSON where sent from is that trusted website then we will send back another JSON payload with including some info from us.
I am pretty new in the security area so I have googled a bit to find out we can use certification to encrytion/decrytion the message. But what will be the solution if we can identify the hack request in the first place and rejecting that request.
As of your description, there are coming two things in my mind immediately:
Use an SSL certificate. That already ensures that your
site is being transferred encrypted over the internet.
Use a token system. Tokens are widely used in payment solutions for example - as credit card data should never touch your own server. All tokens contain some secret information that are used to prove identity.
Use HTTP request headers eg. Basic Auth
For sure, you should have a SSL certificate. This adds already a lot of security to your site.
But what will be the solution if we can identify the hack request in the first place and rejecting that request.
Well, you have answered it yourself. If you can detect it, reject it.
A simple way to protect your restful service is something like basic auth. The application making the rest call would provide a request header like
Authorization: Basic ZWx1c3VhcmlvOnlsYWNsYXZlde
This would not be a user-based solution, but a webapp to webapp solution. All other requests would be unauthorized.
https://en.wikipedia.org/wiki/Basic_access_authentication
I've generated classes from wsdl with wsimport, wsdl location: https://somehost/wsdl. There was no problem with generation.
But when I tried to send soap request, I've received exception:
com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 403: Client certificate required
I find out, surfing the internet, that I have to add certificate in my keystore. I've done it, but this doesn't help.
And I have no idea what to do or even what to google.
Can anybody help me?(
It sounds like a mutual authentication problem.
The server is requiring that your client use a known digital certificate to sign your messages and send that information within the request. It is like a user/password mechanism, but you and the server agree to use a known key-pair for identification.
This situation usually means that the web service server administrator will generate a key-pair and send the private part of the certificate to you.
But you can send the public certificate for him as well if you created it yourself. The server must have access to the public certificate, and it maybe you will have to publish it to a Certification Authority. In some cases it has to be a commercial certificate (you will have to buy it).
You will then use the private key to digitally sign your messages.
I've found some links that may help:
Authentication Mechanisms
Java client for the X.509 secured web-service
Java HTTPS client certificate authentication
If you already did those steps, then something is wrong with your implementation or the certificate/keys provided are invalid.
I recommend you to use a mock server to make sure you are implementing the client authentication properly before you try to connect to the real service. Making it to work locally will set the knowledge you need to call the real functions. You can also ask the web service administrator to send you debug information.
I have a SOAP webservice made in Java, running on Oracle Weblogic. And I need to get the certificate which is supposed to be provided by the client connecting, and extract some information (IssuerDN). How would I go about this?
Edit: I think the 1st thing I am stuck on, is how do I get the input-stream/connection? Then how would I get the certificate?
This depends what implementation you are running. I some cases the request certificate may be put on the SOAPMessageContext. If that is the case you can implement a SOAPhandler to get hold of the certificate used in the request.
For example, in the IBM Websphere´s Axis2 based implementation of JAX-WS the following code will retrieve the certificate:
public X509Certificate getRequestCertificate(SOAPMessageContext aMessageContext) {
return ((java.security.cert.X509Certificate) aMessageContext.get("com.ibm.xml.soapsec.RequestCert"));
}
Notice, be aware of the following. The code above may not be supported by the vendor of the web service container implementation.
We're using Java 6, JBoss 7.1.1 and Spring 3.1.1.RELEASE. I'm trying to write an application that will request data from a WSDL on a corporate web site and then write that data back to a local database. Our corporate group has asked for the public key of a signed-by-authority client certificate (self-signed is fine for QA) of the machine that will be requesting the data, saying that they will use that to send SSL responses back to us and we should use our private key to send requests up to them.
I'm clueless about how to do this. Normally I would use JAX-WS to create client WSDL code and communicating with the web service, adding the server's public certificate to our trust store. But in this case, I have no idea how to tell the web service client to use the requesting machine's private key to encrypt data for the purposes of making a WSDL request.
Grateful for any example code or other reference material to pull this off. -
I have no idea how to tell the web service client to use the requesting machine's private key to encrypt data for the purposes of making a WSDL request.
That doesn't make sense. There is no such thing as encrypting with a private key. Anybody could decrypt it, the public key being, err, public. Let us hope that's not what they are asking for. It's far from clear but they are most probably asking for one of two things:
Use a client certificate when speaking SSL to them. All you have to do for this is use the keystore containing the private key and its certificate: JSSE will do the rest. OR
Digitally sign the request using your private key. There are APIs for this.
Get them to clarify which it is.
We need to implement two-way SSL on Google App Engine, where we send out web service requests using JAX-WS to a server requring 2-way SSL authentication.
How can we set up 2-way SSL for our outgoing web service requests?
We know that javax.net.ssl* is forbidden in the App Engine environment.
Here's an example of our code:
#WebService(name="ListenerSoap", targetNamespace = "http://example.com/Listener.Wsdl")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface ListenerSoap {
#WebMethod(operationName = "Ping", action="http://example.com/Listener.Wsdl#Ping")
public void ping();
}
#WebServiceClient(name="Listener", targetNamespace="http://example.com/Listener.Wsdl", wsdlLocation = "https://example.com/Listener.asmx?WSDL")
public class Listener extends Service
{
public ListenerSoap getListenerSoap() {
return super.getPort(new QName("http://example.com/Listener.Wsdl",
"ListenerSoap"), ListenerSoap.class);
}
}
And an example of above code in use:
ListenerSoap soap = new Listener().getListenerSoap();
soap.ping();
I figure we can store the keystores or any certs needed in the DataStore as binary objects (though how to upload them is still a lil' vague to me).
How can we go about setting the necessary values needed for this web service to authenticate using 2-way SSL?
Thanks for any help
Update:
Through research I've seen this is how it can be done on a traditional server (one with filesystem access):
ListenerSoap soap = new Listener().getListenerSoap();
((BindingProvider) soap).getRequestContext().put("javax.net.ssl.keyStore", "client_cert.p12"
However, in this approach, client_cert.p12 is expected to be on the filesystem.
Additionally, SSLSocketFactory, SSLContext, KeyManager, and KeyManagerFactory all aren't allowed on GAE.
Update:
As of GAE SDK version 1.7.7. this should now be possible:
Similarly, Java developers can now use the javax.net.ssl package to make outbound SSL connections.
GAE 1.7.7 SDK Release Notes
From my restricted knowledge about SSL authorization, it seems you may be missing something of vital importance here; the certificates. Two-way SSL requires the client and server certificates to be in your keystore, which can be either a self-signed certificate( a pkcs12 or pem file, which you can easily generate with a few commands through shell) or a proprietary certificate issued by an authorized company like Thawte or Verisign.
Although I am not sure if that is the problem you are facing, but its good to check it out.
(Also, I am a newbie so please don't downvote my answer, just trying to suggest possible options.)
ListenerSoap soap = new Listener().getListenerSoap();
Hope it improves
Thanks
I know you might not want to hear this, but using SSL is expensive and problematic for two way communication. Depending on how much control you have over the server/client ends, I prefer a simple bi-directional pipe like web sockets and a data packet protocol that can simply implement AES. It really depends on the problem you are trying to solve.
It sounds like there is confusion over simple connection over SSL (https://...) and what is known as "mutual authentication" or "public key infrastructure (PKI)". You can actually do both or one independent of another. With the latter (what I think the original question is referring to), when you make a request to the server, the server will respond to you asking for a certificate which you must present to authenticate yourself.
To answer the specific question above (loading a keystore from binary data), I don't think that is really possible, since it's the Java runtime that picks up on your keystore. The only think you could do is load the bits from your datastore and temporarily write it to disk. Optionally delete it when the application exists. This I have done before and works fairly well. If you do this, I'd recommend using a location likely to be writable (such as System.getProperty("java.io.tmpdir"));), then after writing the file to disk, set the JVM properties (e.g. System.getProperties().put( "javax.net.ssl.keyStore","...");)
You will need App Engine's Socket API for this. This API is in trusted tester mode, so it's not available for everyone.
You can ask for an access gere : https://docs.google.com/spreadsheet/viewform?formkey=dF9QR3pnQ2pNa0dqalViSTZoenVkcHc6MQ#gid=0
2-way SSL (from app hosted in GAE to outside world) is not supported as far as I know. I tried a sample app few months ago and was frustrated to find GAE does n't even support this basic feature.. and the documentations are n't clear either. You won't be able to present client cert when you contact a web-service.. there is no place to store it, the keystore cannot be accessed.
For what i know about two way SSL, you will have no link with Java EE code: two way SSL is a transport layer security: when your client application will try to create a secured HTTP connection (HTTPS) with the serve, the server will ask for a certificate and will approve or not this certificate. If the client certificate is approved, then a secured connection will be established on parties and they are allow to exchange some messages through this tunnel. But this process is done on the transport layer. Your code (on application layer) will never be informed of this process.
In order to established two way SSL, the setup is done on the application server setup for the SSL port.