Implementing WS-Security at the Application Level - java

I'm trying to build a soap service based on JAX-WS (using JBoss AS 7.1.1) and I need to implement security as well. The data is going to be sensitive, so it will be over HTTPS. However, I need to identify the client, and make sure that only they can perform operations for their organization.
From the looks of it, all I have seen on the JBoss documentation (and other JAX-WS providers documentation) indicates that multiple .xml files need to be edited (some at the app server layer).
I'm really looking for a way that I could just have a class in my service called with the SOAP headers, and I could perform the validation/authentication/authorization there. Would really appreciate someone being able to point me in the right direction.

You can always send authentication data explicitly along with the request (user and password, for example, in addition to the normal arguments). You have to make sure that the connection is encrypted.
You can refine this by using public/private keys: So first the server sends its public key, the client encrypts the user/password with that public key, and the server can decrypt it using its private key. As this might be too expensive on a request basis, the server could issue a token for a certain time which the client can send in the following requests (so a token is a means to establish a session).
That being said, and I know how cumbersome JBoss security setup is sometimes, you have to implement and test it very carefully, otherwise you might open some security holes (tokens may leak, sessions might be captured, token invalidation, SSL connection is terminated in web server, clear text passsword remains in RAM and is paged out on the disk etc.).

Related

Authentication mechansim for java game client / mysql db

I need to figure out how to best authenticate users which are connecting from a C++ game client, against a mySQL database on another server, and I plan on writing a java web service to accomplish this.
Security is of primary concern, I need to make sure that the data flowing across the wire is encrypted, so I'll be leveraging SSL (originally I thought about message level encryption using ws-security however I think it's too much overhead).
What I really need to figure out is what kind of authentication mechanism I should provide. These users will be supplying usernames and passwords, and will be issuing a web request to a service.
I haven't decided whether the service should be a traditional SOAP web service or a RESTful one. The whole idea behind rest is to make the server stateless, and since the client will basically be establishing a session with the service, I don't see a point in using REST here.
Having said all that, what I really need to nail down is how exactly to perform the handshake and how to persist the session.
Are there any popular frameworks out there that provide APIs to do this against a mySQL database?
Again the client will offer up a UN / PW to the server, which needs to decrypt them (SSL should take care of that), authenticate them against the account info stored in a mysql DB, and then return some kind of hash or something similar so that the user's session can persist or the user doesn't have to log in anymore to issue additional requests.
Could anyone recommend a framework / some reading material for me to glance over?
Keep things as simple as possible.
HTTP is already stateless, and the idea of a login followed by a continued session is well established (session cookie). Use this paradigm and you won't have any troubles.
You also get the benefit of a very light-weight and open communication protocol and many good libraries for easy serialization / deserialization of common REST payloads like JSON or XML.
REST also means that you can use the same server with other clients quite easily.
I'd take a look at oauth:
http://developers.sun.com/identity/reference/techart/restwebservices.html
A well established pattern is:
1. log in & receive an oauth token
2. store token in db with user's internal id (and any other data such as token expiration time you wish to store).
3. send token to client, client persists token
4. client sends token for all future requests
5. server fetches user info from token
This method should work well with any client language and any backend datastore.
I would recommend to use REST. As authorization framework you can use standard container's jdbc or file realms on JAAS. If login/password pair is successful, store them at client side. After that, you can perform requests with auth credential supplied per request. I used jersey client for this. For [de]serialization from/to XML/json XStream library "do all dat math". Have a nice day.

How to secure a REST web service in Java EE 6

I have made a web application using Java EE 6 (using reference implementations) and I want to expose it as a REST web service.
The background is that I want to be able to retrieve data from the web application to a iOS app I made. The question is how would I secure the application? I only want my application to use the web service. Is that possible and how would I do this? I only need to know what I should search for and read and not the actual code.
Unfortunately, your webservice will never be completely secure but here are few of the basic things you can do:
Use SSL
Wrap all your (app) outbound payloads in POST requests. This will prevent casual snooping to find out how your webservice works (in order to reverse engineer the protocol).
Somehow validate your app's users. Ideally this will involve OAUTH for example using Google credentials, but you get the idea.
Now I'm going to point out why this won't be completely secure:
If someone gets a hold of your app and reverse engineers it, everything you just did is out the window. The only thing that will hold is your user validation.
Embedding a client certificate (as other people have pointed out) does nothing to help you in this scenario. If I just reverse enginneered your app, I also have your client certificate.
What can you do?
Validate the accounts on your backend and monitor them for anomalous usage.
Of course this all goes out the window when someone comes along, reverse engineers your app, builds another one to mimic it, and you wouldn't (generally) know any better. These are all just points to keep in mind.
Edit: Also, if it wasn't already obvious, use POST (or GET) requests for all app queries (to your server). This, combined with the SSL should thwart your casual snoopers.
Edit2: Seems as if I'm wrong re: POST being more secure than GET. This answer was quite useful in pointing that out. So I suppose you can use GET or POST interchangeably here.
Depends on how secure you want to make it.
If you don't really care, just embed a secret word in your application and include in all the requests.
If you care a little more do the above and only expose the service via https.
If you want it to be secure, issue a client certificate to your app and require a
valid client certificate to be present when the service is accessed.
my suggestions are:
use https instead of http. there are free ssl certificate avaliable,
get one and install.
use a complex path such as 4324234AA_fdfsaf/ as the root end point.
due to the nature of http protocol, the path part is encrypted in the https request. therefore it's very safe. there are ways to decrypt the request through man-in-the-middle attack but it requires full control over the client device including install an ilegal ssl certificate. but, i'd spend more time on my app to make it successful.
Create a rule on the machine which hosts your Web Service to only allow your application to access it through some port. In Amazon EC2, this is done creating a rule in the instance Security Group.
We have used RestEasy as a part to securing our exposed RESTful webservices. There should be lot of example out there but here is the one which might get you started.
http://howtodoinjava.com/2013/06/26/jax-rs-resteasy-basic-authentication-and-authorization-tutorial/
You can also use OAUTH:
http://oltu.apache.org/index.html

Authorized Flash Client to Java Server connection

I'm building a Flash-based Facebook game with a Java backend, and I'm planning to use a RESTful approach to connect the two of them (not a persistent socket connection). I'm using the AS3 library to connect the client to Facebook, so that's where I have my session information stored. However, how do I authorize client connections back to the server? I can't leave the callback URLs open since that'd let people manipulate game state without playing the game. I need to make sure that the calls are coming from a valid client and through a valid session.
At the moment, users have no direct login to the backend server -- it's all handled through the client frontend. Can I pass the Facebook OAuth2 access token to the backend in a way that the backend can verify its validity? Should that be enough to trust a valid frontend connection?
I could do a two legged OAuth signed request or just use a simple shared secret, but the keys would have to be packed in with the flash client, which makes that almost useless for this use case.
Somebody has to have solved this problem, but I can't find it.
If you are using Java as a backend, I would consider using BlazeDS. It is a great library for doing AMF connections (which are async so fit your non-persistent socket requirement). If you are using Spring on the backend at all, I'd highly recommend using Spring-Flex as well. It adds a bunch of goodies that make exposing AMF services a breeze. Also, it adds hooks to allow 'easy' integration of Spring Security.
For the oAuth stuff, I would move the oAuth portion to the web side instead of the flash client (which I think I understand is what you do now). This way you can authenticate the web session on the server side and secure the page that contains the .swf. Then when your user loads the .swf in your code (assuming you're using spring security integrated into BlazeDS) you can call cs.authenticated on your cs:mx.messaging.ChannelSet. This will work, but may be more reword than you want to do.
We had similar problem in one of our project. What we ended up doing was used the following token passing method:
1) Fresh client connects to the server and get a token that's valid for x amount of time.
2) The client has an obfuscated part of code that uses an algorithm to change the token (and this algorithm changes at some frequency in sync with the server). The client uses the algorithm to change the token and includes it in the next request to the server.
3) The server knows the original token and the algorithm so now it can check to see if the new token in valid and it's from a valid client.
4) The cycle continues.
This is no 100% secure, since someone can really spend time and analyze the communication and eventually understand the pattern, but you can play around with the algorithm so much and change it often enough to make it hard for someone to guess it.
Hope this helps.
P.S. The application that I'm talking about that uses this has been in production for past 5 years and gets ~300k unique users a day and no one has broken in yet.

Secure connection between client and server

I'm developing a server component that will serve requests for a embedded client, which is also under my control.
Right now everything is beta and the security works like this:
client sends username / password over https.
server returns access token.
client makes further requests over http with the access token in a custom header.
This is fine for a demo, but it has some problems that need to be fixed before releasing it:
Anyone can copy a login request, re-send it and get an access token back. As some users replied this is not an issue since it goes over https. My mistake.
Anyone can listen and get an access key just by inspecting the request headers.
I can think of a symmetric key encryption, with a timestamp so I can reject duplicate requests, but I was wondering if there are some well known good practices for this scenario (that seems a pretty common).
Thanks a lot for the insight.
PS: I'm using Java for the server and the client is coded in C++, just in case.
I don't get the first part, If the login request is https, how can anyone just copy it?
Regarding the second part, t This is a pretty standard session hijacking scenario. See this question. Of course you don't have the built-in browser options here, but the basic idea is the same - either send the token only over a secure connection when it matters, or in some way associate the token with the sending device.
In a browser, basically all you have is IP address (which isn't very good), but in your case you may be able to express something specific about your device that you validate against the request to ensure the same token isn't being used from somewhere else.
Edit: You could just be lucky here and be able to rule out the IP address changing behind proxies, and actually use it for this purpose.
But at the end of the day, it is much more secure to use https from a well-known and reviewed library rather than trying to roll your own here. I realize that https is an overhead, but rolling your own has big risks around missing obvious things that an attacker can exploit.
First question, just to get it out there: if you're concerned enough about nefarious client-impersonator accesses, why not carry out the entire conversation over HTTPS? Is the minimal performance hit significant enough for this application that it's not worth the added layer of security?
Second, how can someone replay the login request? If I'm not mistaken, that's taking place over HTTPS; if the connection is set up correctly, HTTPS prevents replay attacks using one-time nonces (see here).
One of the common recommendations is - use https
https man in the middle attack aside using https for the entire session should be reliable enough. You do not even need to worry about access tokens - https takes care of this for you.
Using http for further requests seems to introduce some vulnerabilities. Now anybody with a network sniffer can intercept your traffic steal the token and spoof your requests. you can build protection to prevent it - token encryption, use once tokens, etc. but in doing so you will be re-creating https.
Going back to the https man in the middle attack - it is based on somebody's ability to insert himself between your server and your client and funnel your requests through their code. It is all doable i.e. in case the attacker has access to the physical network. The problem such attacker will face is that he will not be able to give you a proper digital certificat - he does not have the private key you used to sign it. When https is accessed through a browser, the browser gives you a warning but still can let you through to the page.
In your case it is your client who will communicate with the server. And you can make sure that all proper validations of the certificate are in place. If you do that you should be fine
Edit
Seconding Yishai - yes some overhead is involved, primarily CPU, but if this additional overhead pushes your server over board, you have bigger problems with your app

Java EE security - application clients

I'm writing on a Java EE project which will have everything from 3-6 different clients. The project is open source, and I wonder what security mechanisms one could/should use. The problem is: Because it is open source, I would believe that it is possible for anyone with a user to write their own client (maybe not realistic, but truly possible) and make contact with the server/database. I've tried to go through all the scenarios of reading/writing different data to the database as different roles, and I conclude with that I have to have some security mechanism on a higher level than that (it is not enough to check if that account type is allowed to persist that entity with that ID and so on...). In some way I have to know that the client making contact is the correct client I wrote. Could signing the Jar files solve this entire problem, or is there other ways to do it?
-Yngve
I really think that if restricting the available activities on the server side (based on role) is not sufficient, than you've got a bigger problem. Even if a user doesn't write their own client, whatever mechanism you are using for your remote calls is likely to be vulnerable to being intercepted and manipulated. The bottom line is that you should limit the possible calls that can be made against the server, and should treat each call to the server as potentially malicious.
Can you think of an example scenario in which there's a server action that a particular authenticated user would be allowed to take that would be fine if they're using your client but dangerous if they're not using your client? If so I'd argue that you're relying too strongly on your client.
However, rather than just criticize I'd like to try to also offer some actual answers to your question as well. I don't think signing your jar file will be sufficient if you're imagining a malicious user; in general, public-key cryptography may not help you much since the hypothetical malicious user who is reverse-engineering your source will have access to your public key and so can spoof whatever authentication you build in.
Ultimately there has to be someone in the system you trust, and so you have to figure out who that is and base your security around them. For example, let's imagine that there may be many users at a particular company who you don't necessarily trust, and one admin who oversees them, who you do trust. In that scenario you could set up your client so that the admin has to enter a special code at startup, and have that code be kept in memory and passed along with any request. This way, even if the user reverse-engineers your code they won't have the admin code. Of course, the calls from your client to your server will still be vulnerable to being intercepted and manipulated (not to mention that this requirement would be a royal pain in the neck to your users).
Bottom line: if your user's machine is calling your server, than your user is calling your server. Don't trust your user. Limit what they can do, no matter what client they're using.
Well the source may be available for anyone, but the configuration of the deployment and the database certainly isn't. When you deploy the application you can add users with roles. The easiest thing to do is to persist them in a database. Of course the contents of the table will only be accessible to the database administrator. The database administrator will configure the application so that it can access the required tables. When a user tries to log in, he/she must supply a username and password. The application will read the table to authenticate/authorize the user.
This type of security is the most common one. To be really secure you must pass the credentials over a secure path (HTTPS). For a greater degree of security you can use HTTPS client authentication. You do this by generating a public key for every client and signing this with the private key of the server. Then the client needs to send this signed key with every request.
EDIT: A user being able to write his/her own client doesn't make the application less secure. He/she will still not be able to access the application, if it is required to log in first. If the log in is successful, then a session (cookie) will be created and it would be passed with every request. Have a look at Spring security. It does have a rather steep learning curve, but if you do it once, then you can add security in any application at a number of minutes.

Categories