We are now incorporating Restful Web Services in our System and as a result, both Browser and Mobile Clients are able to access our System available in single form (Clients access same code; No different backend code for different clients) successfully via Restful Web Service (i.e.)
REQUEST:
Technically, Restful Web Service API has been built above our existing system (Specifically built above Controller of MVC). Mobile Clients (be it Android (or) iOS (or) Windows) and Browser Client (Web forms) make uses the Restful API built, for ACCESSING our system and transmitting DATA to our system.
RESPONSE:
So, once we get data inside our system (Controller), it gets processed by moving back and forth from DAO and business layer and finally the processed data lands in Controller for it to be get returned to respective client. So, at this place, currently we determine the type of client from where the request is made (Mobile App or Browser) and
RETURN only processed DATA
IF
Client is 'Mobile App' (or)
RETURN both processed DATA + Name of Web View
ELSE
Client is 'Browser'
Note1: We are returning javax.ws.rs.core.Response object in both the cases.
Note2: processed DATA can be PlainText (or) XML (or) JSON (or) String
TO CLARIFY:
Now our question is, whether can we eliminate this IF-ELSE condition for returning the stuff (i.e.) is there a way to have only one RETURN statement returning generic stuff, irrespective of Client to which the stuff is returned? If so, then how does different Clients (in our case, Mobile App and Browser) interpretes the returned stuff and renders view to us?
Related
I have a Java Spring driven REST API server connecting with PostgreSQL database and a Spring Web Server in Java that is serving content from the REST API to the client using JavaScript (now browsers, but in the future also mobile apps).
I've read a number of articles and topics how one can secure a REST API, but I haven't been able to make a final decision yet. I don't want to have Basic Authorization, because it doesn't make sense as I would need to store credentials in JavaScript that can be easily accessed and read by anyone entering the webpage and developer console. I'd like not to show any credentials to the end user so I can't keep them on the client's side.
I've read a lot about JWT and almost decided to implement it, but I've heard it has some drawbacks and haven't been so sure since then if it's the option I would like to choose. I know there is also oAuth 1.0 or oAuth 2.0 but I don't know if I want to have something this complicated. I would also like to store hashed user credentials in my own database in order not to be depended to any other credential providers like social media or Google.
Now I'm making another layer on my web server as a proxy hoping that it will allow me to authenticate user on this proxy level using Spring Security and having some kind or cookies or something to authenticate, but I'm not so sure if its doable this way and it increases the respond time, adds complexity and needs me to write controller methods for these endpoints. My architecture now is of the following:
Client (browser) -> Webserver -> REST API server -> db
I've also denied all external connections and allowed only localhost access to REST API on tomcat level so that I'd have to implement the security level only on the web server allowing free information transit between the webserver and REST API as it is not reachable anyway.
Web server and REST API are on the same server running as Tomcat instances.
I'm also not so sure if this kind of architecture will allow me to authenticate mobile app clients through the web server.
I would be very grateful for any piece of advice you would have for me in this matter. I'm not so experienced in security, so I'm a bit lost what I should do. Does this kind of architecture any sense or should I simply ask REST API directly from any type of clients, be it a webpage or a mobile app from different IPs and secure Rest API only? And if I want to secure some subpages of my webpage or parts of mobile app should that be an completely other layer?
Thank you for your help.
You have already gone through OAuth, JWT tokens etc. If you don't want to use them,then you can create your own token based authentication system.(say 'TokenHandler').
How this TokenHandler will work ?
TokenHandler will be like a gateway server i.e your every REST API request will route through this server application. So you will address your confusion of mobile and web application call with a authToken in header. Main responsibility of this server applciation is to accept the token and validate against the database where all token details are maintain. This DB will have information regarding timestamp when token was last used to validate, to decide your validation rule .
How Token will get generated ?
Token can be any random 64 digit alphanumeric string and will be generated and updated in DB during every single login activity. Login webservice returns this token in response body.
What can be rules for validation ?
It can be depending on your business logic. I preferred to keep active session window of 15 mins. Means if you access the webservice you will get active window of 15 more minutes. If you didn't access any service for 15 consecutive minutes then from 16th Minute you will need to login again to access further calls. This part can change according to requirements.
How client side will handle this ?
Client side will store this token and pass this token with every request call. Token Handler will validate and redirects it's request to the application server . So your one token handler can be used to server authentication of multiple applcation servers. This you can achieve by application end point identifer.
I will like to discuss further if you have any questions or suggestions .
Use API Gateway Architecture Pattern for your use case -
http://microservices.io/patterns/apigateway.html .
The API Gateway (The webserver in your question) can act as single entry point for all desktop/mobile clients. You can use either session cookies or jwts to authenticate clients at gateway.
With respect to authentication between gateway and micro services, and between micro services, i would suggest mutual ssl - https://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication. If you are using spring boot, this might help - http://www.opencodez.com/java/implement-2-way-authentication-using-ssl.htm
The problem with IP white-listing approach is that - it's not well suitable for cloud architecture as the IPs might change with every server reboot. Even if you are using dedicated IPs, you should be careful to secure the communication with SSL/TLS, else attackers can easily sniff your traffic.
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
Say that I'm running an application on WebSphere Application Server and in some Java class, it makes a REST call by providing a client and client secret to receive a refresh token for OAuth2, and then later at some point, it also makes a REST call to by providing the refresh token to receive an access token.
The source code is obviously not going to be visible to debug through and inspect these values, but my question is that can the values being passed in these REST calls (namely the client secret and refresh token) and the response (access token) be viewed by someone who has access to the machine running the server?
The reason I ask is that I am thinking of storing these unchanging values (client id, client secret, refresh token) somewhere where they cannot be viewed by anyone other than through a JDBC connection in the Java code, and I plan to use these values for authentication purposes with some server somewhere. I do not want the person who this application is being used by to be able to view these values because if they can, they can do some damage by accessing other public APIs on the server.
I intend to only let the Java code (backend) interact with the server for authentication and grabbing some resource, but I do not want to allow the person who has access to this machine (but does not have access to where these values are stored) to view the details of the REST request and response.
Thank you.
It's unclear which server you're referring to in various places.
If you make an outbound HTTPS request from a WebSphere server to a 2nd server, you have to assume all details of the request and response are visible to the operators of the software on both sides.
Either side can trace all of its own input and output.
we are trying to develop a web application where controllers(Servlets) should act as restfully services , initially browser will act as client and then in future there could be third party applications which will be consuming services from the same controllers.
All controllers will return JSON data and angular JS will use this and display content in browser for the web application and for the third party application they will directly invoke rest services.
My question are as follows
If i am developing Restful service then should I not use HTTP-session
i.e should my controllers be completely stateless
If my application should be stateless then how will I overcome the
shortage of HTTP-session object ( how do i carry the user specific
data which could be required in different screen)
How will the authentication be handled for the third party
application , should user provide credentials in each request ?
1) Yes, you need a kind of token based authentication, in other words you have to set header with each request. Angular ngResource is your friend. Example:
i. Login (Basic Authentication)
ii. Get Token from Server and store it e.g. in Cookies
iii. Set header with each request (token: whatever)
iv. If token is valid, server answers with data or enables further interaction
2) User specific data will be stored in your $scope (Angular Term) ist is like a data and operation container for your model. You can persist it locally if you want to. Or send it to the server (with a valid token to store it there)
3) Login, get Token, communicate. User rights and Co. has to be set correctly on the server.
I have the following situation:
A backend system which is hidden for outside access
A thin extension, written in Play Framework, which does some external work with the data passed to the backend.
An nginx instance intercepting all public calls, and deciding to which system to proxy
The idea is the following:
If a specific call comes, I want nginx to proxy it to the Play app, and based on the result of the Play app, to decide whether to proxy it to the backend, or to return the result of the Play app to the web client. The result of the Play app could be either some JSON, or directly playing with the response codes, so when it can be poxide further, it will return 200, if not 500, etc.
Is it possible?
In this scenario you use NGIX as a reverse proxy your play app.
You play controller would handle the request and you can then apply your business logic to know whether or not to forward the request to your back end application.
Responses from Play can be standard http responses or JSON (or many other formats).
You can connect to your back end application by making Web Service requests (from WS in Play) or MQ messages (RabbitMQ plugin) or custom protocol.