Issue 10789

Investigate into authentication solutions for web service, client & webapp

10789
Reporter: mdoering
Assignee: mdoering
Type: Task
Summary: Investigate into authentication solutions for web service, client & webapp
Priority: Major
Resolution: Fixed
Status: Closed
Created: 2012-02-07 12:49:37.272
Updated: 2013-12-16 17:50:20.498
Resolved: 2012-04-27 17:46:23.252
        
Description: Administrators not only need to login to the portal, but the portal needs to forward authentication somehow to the web services via the clients.
Ideally we want to use some existing solution. Investigate into common frameworks including oAuth, CAS, WSS4J and others]]>
    


Author: mdoering@gbif.org
Created: 2012-02-07 13:20:55.439
Updated: 2012-02-10 12:42:29.229
        
We need a protocol that enables the portal and ws-clients(known as a service consumer) to access protected resources from the REST web services (known as a service provider) through an API. The API does not require users to disclose their service provider credentials to consumers.



OPTION OAuth:
As described on the open-source protocol OAuth website, OAuth is "an open protocol to allow secure API authorization in a simple and standard method from desktop and web applications." OAuth incorporates common principles employed by several proprietary frameworks, including Google AuthSub, AOL OpenAuth, Yahoo BBAuth, Upcoming API, Flickr API, and Amazon Web Services API.

OAuth seems a good candidate and works with Jersey (server&client):

https://wikis.oracle.com/display/Jersey/OAuth
http://code.google.com/p/oauth4j/
http://developers.sun.com/identity/reference/techart/restwebservices.html

    


Author: mdoering@gbif.org
Created: 2012-02-07 13:22:08.271
Updated: 2012-02-07 13:22:08.271
        
Also interesting, explains HMAC and amazons approach to secure webservices:
http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

Doesn't work for us as we don't want users to store long private keys but manage a "normal" user account with a "simple" personal password
    


Author: mdoering@gbif.org
Created: 2012-02-07 14:53:37.539
Updated: 2012-02-07 14:53:37.539
        
OPTION: Digest authentication

In our initial design and old IPT registry web services we used http basic or digest authentication to secure the services.
This requires the web service client to know and pass in the user credentials for every call. For the portal this means it has to store the user login + password in a session to be able to make web service client calls. This doesn't appear nice and anyone else using our web services would have to do the same.

    


Author: mdoering@gbif.org
Created: 2012-02-07 16:23:11.977
Updated: 2012-02-10 12:33:00.705
        
OPTION Shiro:
Is being used to secure web apps directly and has a convenient API incl user sessions, a remember me function, authorization & encryption:
http://shiro.apache.org/10-minute-tutorial.html

As we are using struts2 it seems better and simpler to use struts2 native mechanisms for this though, namely interceptors and the http session.
    


Author: mdoering@gbif.org
Created: 2012-02-07 16:43:24.05
Updated: 2012-02-10 12:34:43.616
        
Current thinking:

 * portal uses struts2 interceptors to do access control

 * portal needs to remember user credentials in session and implement remember me function if needed

 * user management: to be decided later, probably portal itself? Start with a registry user table?

 * ws authentication: populate standard UserPrincipal in SecurityContext via some filter (oath,basic/digest)

 * ws authorisation: use JSR-250 @RolesAllowed annotation on a jersey resource (method)
   com.sun.jersey.api.container.filter.RolesAllowedResourceFilterFactory
   http://www.jarvana.com/jarvana/view/com/sun/jersey/jersey-server/1.9.1/jersey-server-1.9.1-javadoc.jar!/com/sun/jersey/api/container/filter/RolesAllowedResourceFilterFactory.html


    


Author: mdoering@gbif.org
Created: 2012-02-08 23:22:07.195
Updated: 2012-02-08 23:22:07.195
        
CAS:
although CAS was developed as a central authentication service for (several) webapplications, they recently provide a RESTful API to retrieve tickets: https://wiki.jasig.org/display/CASUM/RESTful+API

This might be a solute to restrict authentication and passwords to one place, but it I don't fully understand the API yet.

Still the simplest approach seems to be the above one with struts2 doing the webapp work with interceptors doing access control and the session to store user credentials for subsequent access to the (digest) secured webservices.
    


Author: mdoering@gbif.org
Created: 2012-02-10 12:04:59.461
Updated: 2012-02-10 12:04:59.461
        
Looking at how our API plays together with authentication I am sensing a fundamental flaw because we have used the same interfaces for both the ws-clients and the primary, "direct" services, e.g. the mybatis one.

The ws-client methods need to know the user credentials, so we can either extend our API with the credentials somehow only on the client. Or we could add them to the regular API which would mean they would also exist in the persistence services. Both solutions don't seem to make sense unless we want access control in various places (which I think we only want on the web services, not the persistence services).

When the persistence services are used by other tools, like the synchronizer, do we want it to authorize every use of a write method? And which account would we then use?

For the ws-clients it would be nice to have a way of instantiating the clients with a fixed credential in case a suer wants to make use of them. The flickr java clients use some central factory for this for example and you only need to give your keys once and then can just use the services.

If our portal would work with the client classes and not with the service interfaces we could apply jersey authentication filters on every call and we won't need to have credentials in our API. See for example the Digest, Basic or OAuth client filter here:
http://jersey.java.net/nonav/apidocs/1.11/jersey/com/sun/jersey/api/client/filter/HTTPBasicAuthFilter.html
http://jersey.java.net/nonav/apidocs/1.11/jersey/com/sun/jersey/api/client/filter/HTTPDigestAuthFilter.html
http://jersey.java.net/nonav/apidocs/1.1.1-ea/contribs/jersey-oauth/oauth-client/com/sun/jersey/oauth/client/OAuthClientFilter.html

That seems the only solution to me right now - needs more thinking...
    


Author: mdoering@gbif.org
Created: 2012-04-27 17:46:23.287
Updated: 2012-04-27 17:46:23.287
        
we use CAS in combination with Basic and shared secret key like Amazon AWS for web service authorization.

See http://dev.gbif.org/wiki/display/POR/Security+Architecture