I'm working on a Java REST server serving an iPhone app. Now we have to integrate with third party service exposed by oauth2 protocol. This is new to me so I've been reading and writing some "proof of concept" code but I have a big problem or I fundamentally don't understand something...
I made a simple web page with "log in with XXX" button that the user sees in a web view. When he clicks it, login page of the third party service opens and he can approve my app, at what time they will redirect the user to an URL I've specified with the authorization code as a parameter. This URL points to a REST service on my server.
The problem is that this URL must be absolutely the same as the one I've set up when applying my app for their service. Since I'm running a REST server I have no way of knowing about which user are we talking about when the redirection to my server happens (there is no session). I wanted to do this identification with some query or path param but they are not allowing it.
Does any of this makes sense to you or am I implementing this in a wrong way? The only possible solution I can imagine now will be with the help of cookies but I'm not really fond of that...
Yes, that does make sense. You got a few different options, try one of these:
Store a cookie with some user id and read it out after redirection
Use the state parameter of the authorization request for transmitting some user id. The provider is required to return it back to you in his redirect.
Related
I have a web application that when user click on the a link it will generate security information and log on to an external application if the security information is authenticated.
At this point from security concern I don't want to expose the URL and request information on the web page, so instead I am seeking solutions to handle the process behind the scene
I know Apache Components can easily send post request within POJO, jersey client can do as well through web service. However the requirement here is also including to let browser automatically redirect to the 3rd app's front page if the login process succeeded.
My question is what could be the proper solution to handle the login process and go to the external application from web as well.
Say you have:
publicapp.com
secretapp.com
Set up an API in publicapp.com to POST the initial request to itself. When the user submits the initial login form it goes to say publicapp.com/login. This endpoint will pre-process the information then send a server to server request to secretapp.com/login.
If secretapp.com/login accepts the information it responds to publicapp.com with a success and publicapp.com redirects the client to secretapp.com/home, with a short term auth token encoded in a JWT. secretapp.com, swaps the short term token for a full auth token.
In the above scenario, the actual login endpoint is never made public. secretapp.com should also have IP whitelisting to only accepts login attempts from publicapp.com. You can also do a lot of filtering on publicapp.com to eliminate malicious requests without bothering secretapp.com.
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
I have a web application that provides several rest services (Jersey). Most of the endpoints are secured by BASIC authentification. Further more I use SSL for transport and demand POSTs for every call.
The clients/consumers are android apps.
So far so good. The only service that seems to be vulnerable is the registration. It's the 'first' service to call and a user does not exist yet. So I cannot use OAuth, etc. I also have to keep the endpoint easy accessible to enable the user to regster.
How do I secure this service, so it's not spammed by a bot flooding my database?
How about these?
Use a registration link with a token in the request parameter. Ensure that the tokens expire after sometime. You could create a token endpoint url as well for a client to get a valid token.
Use a custom header or a dynamic custom header in your request. Additionally, you could check for a dynamic custom header to validate the request's authenticity.
Use registration confirmation workflows, such as an email / text verification as soon the registration is done. Run a process every day to delete any user accounts, which are not validated in say x days.
I do not think you can really secure the registration URL in a HTTP way. IMHO, anyone who has the registration url can be a right guy trying to register. So if you ask me, option 3 is better than others.
I'm new to java and I'm trying to understand the way we identify users who uses webservices.
The program will be downloaded from my website. It needs to make a connection to my server side web service program.
I think there are 2 options for identifying the user:
Register on website and download web service. A single user id key is then generated when downloading the program. I don't know if this is possible + verification of registration can only be done by email: not 100% sure of user identity.
Download web service and log in into it.
This seems a better way, but I'm not sure this is the way to do it...
Most services use HTTP authentication because the surrounding HTTP protocol already brings all the necessary features. Actually, your web service framework comes with all the plumbing necessary to easily set this up.
Another solution is to have a method which is called login() that takes a user name and a password. All other methods return errors until login() has been called successfully once.
Note that you must use HTTPS as protocol, otherwise passwords will be transmitted either as plain text or with a trivial encryption that is easy to break. Or to put it another way: Without HTTPS anyone willing to invest a couple of minutes of time will be able to use your service.
To implement single sign off, i would like the user to get logged out of application B additionally when ever the user clicks logout on application A. Is it possible to implement this using some form of a POST request to application B? i.e. when the user clicks on logout:
Generate existing POST request to logout of application A
Generate additional POST request to logout of application B as well.
The cleanest way to do this is to check if your SSO provider has a single-sign-off feature.
Coding this up and deploying it would make your overall IT solution a bit brittle.
Another suggestion is to take this up with your (Enterprise) architect as SSO is usually an enterprise initiative and point her to (very cogent) arguments in this post : http://lists.danga.com/pipermail/yadis/2005-July/001085.html
Yes, how you do it depends on the programming language you are using.
For example under ASP.Net you'd use System.Net.HttpWebRequest within the handling of the Logout event of application A to make a logout request to application B
If you can post what language you're working in I can give a proper example
Depending on the implementation of your authentication system, probably you can/need to send the POST using JavaScript instead of from server-side.
Without specific information, it's hard to give a specific answer, but as you're refering to POST, I'll assume a browser is involved.
POSTs (without using Javascript or similar) occur when a form is submitted. As the form can have only one action, it can only target one server-side page.
One solution is to simply have Application A forward sign-out credentials to Application B once one action is received, which allows for more opportunities to check returns.
If, however, you're set on POST'ing to different pages, see this tutorial for one iframe-related hack - http://www.codeproject.com/KB/scripting/multiact.aspx
If your login session is stored by a cookie, and there are nothing else you need to supply to log out of application B, clearing the cookie in javascript will usually destroy the session and sign the user out.
How about making it a cookie based authentication? A same cookie authenticates a user for various applications (in your case 2 different application.) Once a user sign off from one application (app A), invalidates a cookie (by expiry date) so that whenever a user sends a POST request to rest of the application (app B) the request is not processed. A Servlet that traces each POST request to validate the cookie is required for each application.