Mar 2nd, 2012, 07:04 AM
Spring HTTP Invoker Authentication Questions
i am writing a Client-Server Application with the following technical background:
Server: Spring 3.1 WebApplicationContext running on Tomcat 7
Client: Swing-"Fat"-Client, using Spring 3.1 ClassPathApplicationContext
As communication Protocol i chose Spring HTTP-Invoker, but i am still open to suggestions, maybe i would be better off with Spring RMI-Invoker?
What i already got is a working communication (even with SSL). But what i don't understand is how do i implement a login? I want to implement a login frame on my client. When the client clicks login, the credentials should be sent to the server, where they are validated as usual with my AuthenticationManager.
First: how do i achieve this? Is Basic Authentication suitable and if so: is there a way to achieve this with Spring-AuthenticationSimpleHttpInvokerRequestExecutor?
Second: even if i got this to work.. what next? Do i need to check this on every access? (will be bad for performance i guess) Or how can make sure that the client was successfully authenticated?
I googled a lot, but found only a few hints and mostly very outdated answers. Any help would be appreciated!
Mar 2nd, 2012, 08:13 AM
You cannot trust anything on the client so you must authenticate every request on the server side. Think of a web browser situation. Typically after login a session is established and a session id is stored in a cookie. Each time a user requests a page it submits the session id and the web application (or in most cases the web container) must lookup the user information associated with that session id. In a sense the user exchanges their username / password credentials for a temporary session id which becomes another way of authenticating the user who submitted the username/password.
Back to your rich client. It is not much different except the application must keep track of some sort of credentials (instead of the browser) and pass them to the web application. The web application (or container) will need to validate the credentials for every request.
One of the more popular implementation choices would be to create a REST service and to secure it using OAuth. The rich application would then use OAuth for making requests to the REST service and the REST service would validate the OAuth token on each request. As it so happens there is a Spring Security OAuth project that may help you with this.
Mar 2nd, 2012, 01:28 PM
Thanks for your fast response! That really sounds completely like what i would do in a webapplication.
Let me see if i get this right:
a) user logs in to the client. The client uses basic authentication (which is ok because the channel is encrypted) to authenticate to the server.
b) server verifies the credentials against AD or whatever and generates a random key/id which he transfers back.
c) on every further request, the client includes this id. Since the channel is TSL encrypted, no one else could possibly have this key. So all i need to do is verify the key on server side.
That sounds nice, still i was hoping for another way. I read somewhere that it should be possible to transparently pass an SecurityContext/Authentication alongside every RMI-Invokation. That would be my favorite, because i wouldn't have to put extra-parameters (vor the key/id) to every invokation method. Any hint on this? Maybe a way to achieve this with AuthenticationSimpleHttpInvokerRequestExecutor? I read so much about it, but still have no real idea.
I will study OAuth know
Mar 2nd, 2012, 02:32 PM
If you pass anything (including a SecurityContext) from the client you will need to validate everything that is passed in. Remember anything coming from the client cannot be trusted. An easy way to realize this is to know that anyone running your code could run it through a debugger and modify the values. They could also use a proxy server to sniff/modify the traffic. Remember SSL protects a client against others but if the client wants to be malicious it does not protect the service.
Originally Posted by Matrium
Mar 3rd, 2012, 07:12 PM
You are right, passing the SecurityContext seems not to be the way. I am asking myself why there is even the possibility to do so, is this ever going to be safe? Even if the client could reliably authenticate the user, the server can't trust that anyway.
I've taken a deeper look into OAuth now and it looks nice, but seems a bit overkill for now. I am now using BASIC Authentication for every request and it seems to work. But the problem is that in productive environment the Authentication-process could be pretty costy (including qeries for AD + 2 different databases). I really don't want to do this every time. So i am thinking about using one AuthenticationProvider for all this stuff and another one which only validates some sort of credentials for every further request. Could this work? What kind of credentials should i use for this? Just a random number?
Thanks for your help!
Last edited by Matrium; Mar 4th, 2012 at 05:10 AM.
Mar 5th, 2012, 03:48 AM
I tried to use 2 different AuthenticationProvider, but it seems like there is no possibility to use different provider for different URLs easily.
I am now trying to implement one AuthenticationProvider which does the following:
a) if the user clicks login basic authentication is used to transfer username/password
b) on server-side my authenticationProvider checks that informationen and (if correct) authenticates the user and returns a generated UUID to the client.
c) on every further request, the client prepends "RETAIN-" in front of the username and sets the UID as credentials and uses basic authentication again.
d) the authenticationProvider checks if the username starts with "RETAIN-" and if so verifies if the UID is correct
To me it seems like this should be secure, it's pretty much the same as using a session-key, right? Maybe that solution is not elegant, my auth.getName() doesn't really return the name of the principal anymore, because of the "RETAIN-" thing?
i couldn't get that to work the way i want to either
i think maybe the problem is that i don't know how to store the SecurityContext between requests. In my webapplications this seems to be done automatically, but how can i persist the Context with HTTP-Invoker?
Last edited by Matrium; Mar 5th, 2012 at 08:24 AM.
Mar 6th, 2012, 06:10 AM
I got it now, using org.springframework.remoting.httpinvoker.HttpCompo nentsHttpInvokerRequestExecutor on client-side.
I finally understand the way HTTP invoker works and how to secure it. Actually it's really elegant, the server-side solution is the same i would use for a webapplication, i like that a lot.
Thanks for your help rwinch!
May 22nd, 2013, 07:21 AM
i facing now the same problem. could you post here or send me your answer to this?