Same Form based authentication for two applications Using Spring Security - java

We have an existing legacy web application(Servlet+jsp+spring+hibernate) and we are going to develop some new features of the application using a new stack (angularjs+Spring mvc). Currently suggested approach is to register a new servlet and develop the new features in the same codebase, so the authenticated users will have access to the new functionality we develop in the system. Is there a better way of doing this as a two different web applications (without SSO) ? Can two web applications be secured under the same form based authentication settings ?

I think architecture and security usability is very important before dive into something.
If both apps use same login, then I assume the newer application is more likely a service oriented application. Ex: RESTful
Authorization may be an issue. Ex: Legacy app is used by user set A, new one is used by both user set A and B.
Otherwise you can use a shared database for example MongoDB to store your login info i.e token.
When you log in, return that token and use for the other service via angular client. When you log out remove any token for that user session. You may also need to concern about token expiration.
However you have to refactor your legacy system in someway to use a token. If it is not possible, you can use session sharing which is handled by the the container if the the both apps are running under same container. Ex: Tomcat. But now it may very hard to integrate with a native mobile app if you are hoping to do so.
Sharing session data between contexts in Tomcat

From the point of Spring security and angularjs, authenticating via form is just an http POST with content type being application/x-www-form-urlencoded. One difference is the response to a non authenticated request, for one response should be a http redirect (jsp, to a login page), one with an unauthorized code (for angularjs). That could be handled with a custom AuthenticationFailureHandler or on the client side. A similar difference may occur for the successful login redirection.

Related

Exposing a web site through web services

I know what I am asking is somehow weird. There is a web application (which we don't have access to its source code), and we want to expose a few of its features as web services.
I was thinking to use something like Selenium WebDriver, so I simulate web clicks on the application according to the web service request.
I want to know whether this is a better solution or pattern to do this.
I shall mention that the application is written using Java, Spring MVC (it is not SPA) and Spring Security. And there is a CAS server providing SSO.
There are multiple ways to implement it. In my opinion Selenium/PhantomJS is not the best option as if the web is properly designed, you can interact with it only using the provided HTML or even some API rather than needing all the CSS, and execute the javascript async requests. As your page is not SPA it's quite likely that an "API" already exists in form of GET/POST requests and you might be lucky enough that there's no CSRF protection.
First of all, you need to solve the authentication against the CAS. There are multiple types of authentication in oAuth, but you should get an API token that enables you access to the application. This token should be added in form of HTTP Header or Cookie in every single request. Ideally this token shouldn't expire, otherwise you'll need to implement a re-authentication logic in your app.
Once the authentication part is resolved, you'll need quite a lot of patience, open the target website with the web inspector of your preferred web browser and go to the Network panel and execute the actions that you want to run programmatically. There you'll find your request with all the headers and content and the response.
That's what you need to code. There are plenty of libraries to achieve that in Java. You can have a look at Jsop if you need to parse HTML, but to run plain GET/POST requests, go for RestTemplate (in Spring) or JAX-RS/Jersey 2 Client.
You might consider implementing a cache layer to increase performance if the result of the query is maintained over the time, or you can assume that in, let's say 5 minutes, the response will be the same to the same query.
You can create your app in your favourite language/framework. I'd recommend to start with SpringBoot + MVC + DevTools. That'd contain all you need + Jsoup if you need to parse some HTML. Later on you can add the cache provider if needed.
We do something similar to access web banking on behalf of a user, scrape his account data and obtain a credit score. In most cases, we have managed to reverse-engineer mobile apps and sniff traffic to use undocumented APIs. In others, we have to fall back to web scraping.
You can have two other types of applications to scrape:
Data is essentially the same for any user, like product listings in Amazon
Data is specific to each user, like in a banking app.
In the firs case, you could have your scraper running and populating a local database and use your local data to provide the web service. In the later case, you cannot do that and you need to scrape the site on user's request.
I understand from your explanation that you are in this later case.
When web scraping you can find really difficult web apps:
Some may require you to send data from previous requests to the next
Others render most data on the client with JavaScript
If any of these two is your case, Selenium will make your implementation easier though not performant.
Implementing the first without selenium will require you to do lots of trial an error to get the thing working because you will be simulating the requests and you will need to know what data is expected from the client. Whereas if you use selenium you will be executing the same interactions that you do with the browser and hence sending the expected data.
Implementing the second case requires your scraper to support JavaScript. AFAIK best support is provided by selenium. HtmlUnit claims to provide fair support, and I think JSoup provides no support to JavaScript.
Finally, if your solution takes too much time you can mitigate the problem providing your web service with a notification mechanism, similar to Webhooks or Resthooks:
A client of your web service would make a request for data providing a URI they would like to get notified when the results are ready.
Your service would respond immediatly with an id of the request and start scraping the necessary info in the background.
If you use skinny payload model, when the scraping is done, you store the response in your data store with an id identifying the original request. This response will be exposed as a resource.
You would execute an HTTPPOST on the URI provided by the client. In the body of the request you would add the URI of the response resource.
The client can now GET the response resource and because the request and response have the same id, the client can correlate both.
Selenium isn't a best way to consume webservices. Selenium is preferably an automation tool largely used for testing the applications.
Assuming the services are already developed, the first thing we need to do is authenticate user request.
This can be done by adding a HttpHeader with key as "Authorization" and value as "Basic "+ Base64Encode(username+":"+password)
If the user is valid (Users login credentials match with credentials in server) then generate a unique token, store the token in server by mapping with the user Id and
set the same token in the response header or create a cookie containing token.
By doing this we can avoid validating credentials for the following requests form the same user by just looking for the token in the response header or cookie.
If the services are designed to chcek login every time the "Authorization" header needs to be set in request every time when the request is made.
I think it is a lot of overhead using a webdriver but it depends on what you really want to achieve. With the info you provided I would rather go with a restTemplate implementation sending the appropriate http messages to the existing webapp, wrap it with a nice #service layer and build your web service (rest or soap) on top of it.
The authentication is a matter of configuration, you can pack this in a microservice with #EnableOAuth2Sso and your restTemplate bean, thanks to spring boot, will handle the underlining auth part for you.
May be overkill..... But RPA? http://windowsitpro.com/scripting/review-automation-anywhere-enterprise

Token based authentication and authoriozation for Apache Tomcat servlets

Background: Our current technology architecture includes Tomcat Servlets that do backend activities and Codeigniter PHP which handles the presentation layer. So when a particular page is loaded, the Codeigniter View invokes the Controller which constructs the servlet URL with necessary input parameters and invokes the URL and gets the response and passes it back to the View so that the page is rendered.
Issue: User information and login credentials are stored in database and is validated by PHP front end. There is no authentication for the Tomcat servlets and in cases where we need user information in the backend, the user id is passed as a parameter to the backend.
Currently Tomcat and PHP resides on the same server and we have used firewall port based restrictions to ensure that servlets can be invoked only from within the server to secure the servlets.
Help required : We are looking to implement token based authentication and authorization mechanism for the servlets. If we can get some sort of existing library that we can easily plug-in to our servlets, that would be ideal. Otherwise please guide what would be the best solution to implement without too much code changes but would effectively secure the backend servlets.
Cássio Mazzochi Molin have a nice articel about the topic : Token-based authentication with JAX-RS 2.0

Spring security - login architecture

I have been following the example in this tutorial: https://spring.io/blog/2015/01/28/the-api-gateway-pattern-angular-js-and-spring-security-part-iv
In brief:
I have a server called UI that has some html and angular js.
I have a server called resource that has a RestController who is serving the content from a DB. All the calls must be authenticated.
The UI server has a login page which works with spring http basic login and creates a spring session that is stored in a Redis server and it is shared to the resource server. When i have some dummy users in memory authentication everything works fine.
The question is:
I want my UI server to be able to perform a login with real users, that exist in the DB. The UI server should not have any DB related code (not knowing its existence) but it should call a REST service in the resource server. The only way i was thinking (but is sounds wrong to me) is to implement a userDetailsService bean in the UI and the loadUserByUsername method should call a rest service from the resource server (e.g. /getUser). The rest service should return all the user details including credentials and roles for the given username. However, to my understanding, this service cannot be secured (for the call to be successful) which compromises the entire security.
I am open to all suggestions and recommendations. Bare in mind this is my first attempt to work with Spring.
Thank you in advance,
Nicolas
In case that someone is interested how i tackled this..
I decided to do the prudent thing and study spring security.. :)
My answer is to use a custom AuthenicationProvider in my UI server, which will call an unprotected rest login service in the resource server, which in turn validate the user against the DB.
If the response is successful (e.g. a user object could be returned with username, password, roles) then i will create a UsernamePasswordAuthenticationToken object out of it and return it.
If the response is NOT successful (e.g. return object was null or an exception was thrown) then i will either return null or throw an AuthenticationException, it depends on how Spring behaves... I haven't reached that part of studying yet..
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#tech-intro-authentication
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements
Features
Comprehensive and extensible support for both Authentication and Authorization
Protection against attacks like session fixation, clickjacking, cross site request forgery, etc
Servlet API integration
Optional integration with Spring Web MVC

Authentication Strategy for GAE

I have an application deployed to Google App Engine. Within the application, there are 2 roles: standard user, and administrator. I have form based authentication setup, and the URL's that require authentication (for example /admin and /account) are setup to require any role (*), just so I can be sure that Google has authenticated them. I have a filter setup for the admin path as well as the account path that talks to backend business logic to see if the user has an account within my application before forwarding them to the page they requested, or redirecting if necessary.
This seems cumbersome, in that for each request, the filter uses the UserService to get the google user in order to determine whether or not the person authenticated by google has an account within the application. I know that within the context of an application deployed to a traditional application server, I could actually define the application level role required to access a url, and since the application server would know about the roles/users for the application, that would be sufficient, but since google is handling the authentication, would I be correct in assuming that I have to handle the access requirements on a per request basis, as I am now with the use of filters? I chose to use filters to try to keep the actual servlet 'cleaner', so that I know that when a client request reaches the servlet, they have been authenticated and are authorized to access those resources.
Would it be wise to carry that data around (whether a user is authenticated and whether or not they are an admin or standard user) in a session? That's the only other alternative I can come up with. I'm not sure how expensive it is to access the UserService for every single request, because that is in turn accessing the datastore. I would imagine there has to be a better way to handle authentication.
Not really sure if it's an optimal solution but what we do now is store a User session (our own implementation, not GAEs) and we cache it aggressively using Objecitfy's cache feature. That way we only hit the datastore on login/logout and most queries after that are virtually free (because of the use standard session time on our app, cache flush is not really a concern)

Securing a stateful web service

We are planning on developing a layer of REST services to expose services hosted on a legacy system. These services will be used by a classic web application and native mobile phone applications.
This legacy system is secured in such a way that an initial username + password authentication is required (a process that can take 5 to 10 seconds). After the initial authentication, a time-constrained token is returned. This token must then be included in all further requests or else requests will be rejected.
Due to a security requirement, the legacy security token cannot be returned outside of the REST service layer. This means that the REST service layer needs to keep this token in some form of user session, or else the expensive username + password authentication process would need to be repeated for every call to the legacy system.
The REST service layer will be implemented using a Java 6 + Spring 3 + Spring Security 3 stack. At first sight, it looks like this setup will run fine: Spring-based REST services will be secured using a rather standard Spring Security configuration, the legacy security token will be stored in the user's HTTP session and every call will retrieve this token using the user's session and send it to the legacy system.
But there lies the question: how will REST clients send the necessary data so that the user's HTTP session is retrieved properly? This is normally done transparently by the web browser using the JSESSIONID cookie, but no browser is involved in this process. Sure, REST clients could add cookie management to their code, but is this an easy task for all Spring RestTemplate, iPhone, BlackBerry and Android clients?
The alternative would be to bypass the HTTP session at the REST service layer and use some other form of user session, maybe using a database, that would be identified using some key that would be sent by REST clients through a HTTP header or simple request query. The question then becomes, how can Spring Security be configured to use this alternative session mechanism instead of the standard Servlet HttpSession?
Surely I am not the first dealing with this situation. What am I missing?
Thanks!
There's nothing magical about cookies. They're just strings in HTTP headers. Any decent client API can handle them, although many require explicit configuration to enable cookie processing.
An alternative to using cookies is to put the JSESSIONID into the URL. I don't know anything about spring-security, but it seems that that's actually the default for at least some types of URL requests, unless disable-url-rewriting is explicitly set to true . This can be considered a security weakness, though.
Unfortunately authentication is highly problematic -- a bit of a blind spot in terms of web standards and browser implementations. You are right that cookies are not considered "RESTful" but purists, but even on fully-featured browsers avoiding takes quite a bit of hackery, as described in this article: Rest based authentication.
Unfortunately I haven't done any mobile development, so I can't suggest what the best compromise is. You might want to start by checking what authentication models each of your targetted platforms does support. In particular, two main options are:
HTTP authentication (ideally "digest", not "basic")
Cookies
One possibility would be to provide both options. Obviously not ideal from a technical or security point of view, but could have merits in terms of usability.

Categories

Resources