I've been inspired by a number of things I saw at PTW in Athens to look further into the use Web Services in OpenEdge applications - particularly in relation to designing Web Services for use in interactive user interfaces through the Open Client technologies.
One of the overriding non-functional design issues is that of security. There are a number of possibilities when it comes to securing Web Services, from securing the communications channel (SSL), ensuring only validated clients can access the web server (IP address filtering/Web Server user validation/etc), and security within the business logic of the Web Service.
I'm interested in discussing how other people are doing this in their applications today and how they might be designed for the future.
If we think about how we authenticate an GUI client on the AppServer today, we have a number of possibilities including: passing a username/password with each request, using the CLIENT-CONTEXT-ID (okay, but not for Sesssion-Free connection which is the model that most readily fits to Web Services), serialising a CLIENT-PRINCIPAL object and sending it with each request, sending GUID/UUID with each request and using context database to lookup authentication information, etc.
Web Services requests should be independent of each other and ideally there should be no server side context maintained. With these things in mind, of the above mentioned possibilities, we fall back to passing a username/passwrod with each request (non-Progress clients have no concept of how to create a CLIENT-PRINCIPAL).
Another possibilities is to looking into things like WS-Security (www.oasis-open.org/committees/wss/), however I'm thinking that this is a little heavy weight for what we want to do with AJAX in a browser. In addition to that AJAX is all client-side (ie. browser based) and anything we code there is freely available for any user to see and is therefore open to attack.
Other concepts like transforming all incoming and outgoing WebService requests through XSLT can provide a certainly level of "validation", obfiscating internal data structures and helping to ensure that malformed requests don't return unexpected, perhaps unintended, data. However, I'm thinking that this also could lead to unnecessary overheads and could endanger the performance required for user based interfaces. ....and it still doesn't solve the question of how one should implement authentication and authorisation.
Does anybody have any experience or ideas they would like to share in this area, particularly relating to designing secure Web Services for use by multiple different user interface implementations?
You could use HTTP-based security. The web server will take care of this, see http://www.rassoc.com/gregr/weblog/stories/2002/06/09/webServicesSecurity.html for more info.
When you send userid/password with every request, make sure you're using an HTTPS-connection.
When it comes to securing webservices I usually consider two levels of security:
- username/password credentials to make sure only authorized users can make use of the webservice
- secure communications from and to a webservice
Depending on the type of information you are sending or requesting you can use http (unsecured) or you'll need to use https (secured). This you'll have to take care of on the communications level.
As I see it user credential authorisation is a necessary part of any commercial webservice, so chances are you'll need to implement that. There's two approaches that are often used to do this. The first would be to implement a username/password verification in the webservice logic itself. This means embedding the security mechanism in your service logic or if you're using ESB adding user validation to the process that is invoked by the webservice call.
The second approach would be to use a webservice proxy that can deal with this type of security at a more generic level. Think of Actional SoapStation, which delivers the functionality to centrally define users, groups, passwords and so on and enforce security towards your webservices from a top-down perspective, really pushing the security policies down into your services infrastructure. Think of this as putting a garded gate in front of your service that will block unauthorized access using a central user credentials repository. This central user repository could be a user registry like ActiveDirectory, LDAP, Netegrity, RSA, ... Additionally SoapStation offers routing and transformation capabilities so it gives you additional advantages.
Ideally I would design my webservices with a basic embedded security mechanism. That would mean that I can use this embedded security for my webservice if I don't want to pay for the additional licences involved with a webservices management solution like Actional. I would still have to possibility to let a webservices management solution manage everything generically by setting up a general system account for example within my embedded security.
The main point here is I guess that you can add security to your webservices even if you did not design them like that from the beginning. For scalability reasons though I would prepare for user credential validation right from the beginning on though.
So if I get what you're saying, for "public" queries (like getMeAListOfYourProducts), you wouldn't bother with any security - neither username/password nor SSL encryption.
For "private" queries (like getMeTheOpenBalanceForCustomer(custnum) ), you'd probably put a usename and password into the SOAP request, rather than getting some unique identifier or token in one request and using it for future requests. Of course, anytime you're sending username & password, we need to be using SSL so that nobody can just read the message and steal the authentication data. Even if the password is obfiscated, somebody could steal the obfiscated password and use it.
So any secure request basically has to be done over SSL, right?
The next question is: where is the right place to put things like username & password (& potentially login company & response language & ....). Should we be putting stuff like that in the SOAP Header or in the Body? From a OpenEdge AppServer backend perspective, we can handle it in either place, but what if the WebService were to be written in something else, does Java (& ...) care if it's in the Header or the Body? Are there any standards or community best practices?
Incidentally, I've come to my own conclusion that using cookies is probably not the right place to do this kind of thing. If we use a WebSpeed agent to accept WebServices requests, we could access cookies, but the more natural way to do this would be with the AppServer & Web Services Adapter, which don't inherently make it so easy to access cookies. Of course, I welcome comments on this too
No comments on SOAP Header or application content ... When it comes to that stuff I'm a man of theory ;-). I agree on the HTTPS/SSL for secured webservices ...
As you're not familiar with Actional, some extra details on it ...
Actional Soapstation allows the use of both SOAP headers and request content for security I believe, but I'd have to verify this. Additionally WS-Security is supported as well. It creates a new wsdl for you webservice that is called by the clients. After validating the request using either validation protocol it calls your webservice using the original wsdl.
Ofcourse for your public webservices you need to make sure that these can not cause an overload on your server. That too is webservices security. For example getListOfAllProducts might be a potential danger if the list is long. People on the outside could use such a webservice to crash your servers, so make filtering obligated.
Actional LookingGlass allows monitoring and management of your webservices so it can trap and react upon requests that are overloading the system. It is even capable of prioritizing requests on e.g. client categories and giving lead way to requests with higher priorities. Examples could be EnterOrder gets priority over getCatalogue or Gold customers get priority over Silver and Bronze customers.
I also cannot tell you where to put the username/password at least we know we would put it into the header or body, right?
Also, I could imagine that it depends what you're implementing this: Do you 'directly' expose a (4GL/Java/Whatever) function/method giveMeMyProducts(), or do you have a system in place which you can use to wrap this call, like an ESB Process.
If you don't have such a system you would need to add authentication logic to you method which either is probably not what you want or makes you authentication logic more complex - I think.
And yeah, another possibility would be to have some kind of proxy doing this for you (which probably is what the Actional products do (?))
If you don't have such a system you would need to addauthentication logic to you method which either isprobably not what you want or makes youauthentication logic more complex - I think. And yeah, another possibility would be to have somekind of proxy doing this for you (which probably iswhat the Actional products do (?))
If you don't have such a system you would need to add
authentication logic to you method which either is
probably not what you want or makes you
authentication logic more complex - I think.
And yeah, another possibility would be to have some
kind of proxy doing this for you (which probably is
what the Actional products do (?))
In an OpenEdge Reference Architecure/OpenEdge Reference Implementation sense, this is exactly the kind of thing I'd do in my WebServices Service Interface Gateway.
(For those who don't know what I'm talking about, you might want to look at this: (you have to log in to PSDN)
Message was edited by:
i was wondering about releasing Autoedge as complete package because Mike Ormerod expected it for end of October, look here http://www.psdn.com/library/thread.jspa?messageID=5676&tstart=0#5676 .
And, the page you linked is empty.
Schedule changed or mistake ?
In an OpenEdge Reference Architecure/OpenEdgeReference Implementation sense, this is exactly thekind of thing I'd do in my WebServices ServiceInterface Gateway.(For those who don't know what I'm talking about, youmight want to look at this:http://www.psdn.com/library/entry.jspa?categoryID=292&externalID=95)For those wanting a sample implementation that doessomething like this, look out for the AutoEdge (anOpenEdge Reference Implementation) that should beposted to PSDN sometime soon.Well, well, look at that, AutoEdge just got postedhere:http://www.psdn.com/library/kbcategory.jspa?categoryID=434 (you have to log in to PSDN)Message was edited by: Jamie Townsend
In an OpenEdge Reference Architecure/OpenEdge
Reference Implementation sense, this is exactly the
kind of thing I'd do in my WebServices Service
(For those who don't know what I'm talking about, you
might want to look at this:
For those wanting a sample implementation that does
something like this, look out for the AutoEdge (an
OpenEdge Reference Implementation) that should be
posted to PSDN sometime soon.
Well, well, look at that, AutoEdge just got posted
yID=434 (you have to log in to PSDN)
This in some ways is a timely discussion, as one of the areas we're about to embark on is looking at putting together some OERA Reference Implementation work that is not only class based, but also offers guidance on putting together a SOBA. Now of course, security will be one of our considerations as we design this. So I have a question. In your opening thread Jamie, you comment that each webservice call should be distinct and no context should be held server side. Is this strictly true? Does it break all the laws of web services, if you defined a set of web service calls, in which the first call performed some form of authentication and returned a token (whatever form that maybe, a guid for instance), and then every subsequent web service call to your exposed services expected as one of it's parameters, that token. Now I can hear you all shouting that this is just a web browser model, and yes I agree. But my question is whether or not doing such a thing would be a valid web services approach, or is one of the key fundamental rules that define a web service, the fact that each call should be self contained?
Hi Jamie,i was wondering about releasing Autoedge as completepackage because Mike Ormerod expected it for end ofOctober, look herehttp://www.psdn.com/library/thread.jspa?messageID=5676&tstart=0#5676 .And, the page you linked is empty.Schedule changed or mistake ?Message was edited by: Werner Waechter
i was wondering about releasing Autoedge as complete
package because Mike Ormerod expected it for end of
October, look here
What your seeing is preperation work for when the material gets posted. So you may find some category areas that currently have no material, so yes a shceduled changed.
Whoops! My bad.
I saw that the category had been created and due to it's title, I thought it might actually have been populated already. I guess this category might get removed again until the content is finished.
You know it makes sense
I must admit that I'm somewhat of a purist when it comes to standards and best practice, so I would prefer to see all Web Service requests be discreet, individual requests rather than having to start and finish my requests with login and logout requests.
In the simplest form, the need to use a single web service would end up being 3 requests if I have to login and logout. One could argue that if we have a longer running "session" consisting of multiple requests, the overhead of an extra two requests would not be significant and that only the first and last request must be executed in the correct sequence.
If you want to use a "session" in this way, you would indeed be able to authenticate in the first request and then use some kind of token (a single parameter) for subsequent requests instead of a username & password (two parameters).
On the other hand, what if we want to replace one of the services called in this session with a different implementation (what? not use the ABL??). We would have to make sure that these two (or three or ...) different service providers all have access to the same token authentication mechanism. (We could do this with a Web Service, right )
With respect to security, you still have to make sure that the transport is encrypted, otherwise anybody could pick up the token as use it, so a token or a username/password are equally secure. The time required to validate a username/password or a token are of course implementation dependent, however I don't see a major differece here.
Checking where the request came from (IP address, browser id, etc), may be possible, but also might not be what you really want to do as you may end up building something that is implementation (client or server) dependent. In the same vain, using things like cookies is not something I would want to do. Hence my question from above: where is the right place to put a username & password - in the SOAP header or in the body? (I'm leaning towards the header, but I'm interested in how you might be doing this today)
Using a token could in fact be a little more secure in that you could invalidate a token when the logout is called, but in a web services world, you can't be certain that it will ever in fact be called. Of course you could set time limits on the validity of a token, but you probably only want to do that at the start of a "session", updating the validity with each web service request is not something I'd particularly want to do, however I can image a couple of use cases. Using a username/password with each request invalidates the need for this.
Hmmm.... just had a thought. If we're talking about an AJAX client that is calling a bunch of different web services, whatever we use for authentication will probably be embedded in the html (no cookies please and I don't want the user to havew to enter a password each time).
Since we agreed (okay, I agreed with myself) that we should be encrypting the transport, we don't have issues there, but what about the security of the browser cache on the client side. If it were a "rich" client (like ABL, Java, .Net, etc), they could keep things like username and password in memory, but the browser would have to have it in the html which might get cached to disk and saved after the user logs out.
Okay now what do we do? Do we make sure that any web pages that utilise AJAX don't get cached on the client (or any intermediary caches)? If we implemented these clients ourselves, I guess we could enforce that rule, but the whole idea of web services is that we publish the WSDL document and "everybody else" can use our services from whatever client they like.
Jamie (trying to secure my spot here on the fence )
Mh I think you can never guarantee that a client doesn't store user/password somewhere, especially if these are thirdparty clients on systems you don't know.
The only thing you can do is not to trust those requests, but if they can supply a valid username/password (not matter how they got those ), they may request whatever their user is allowed to.
BTW: My browser does not store encrypted (SSL) pages (You can disable caching for SSL pages for IE too)