Expose Web Services to third party applications? - java

I've been asked in tech discussions how do we write an application to use internally in the firm, and also expose it as an API to third party clients?
I am assuming this is in context of Web Services. I am thinking, won't the third party simply call the end point and consume the response?
Clearly, that answer is raw, and I am missing the point.
Is there a known approach, or any Frameworks to do this?
What are the considerations here? And how do we address them?

You would write and expose the RESTful services for internal and external users same way however when you do it for external clients then you have to careful about some of the following points
Security - If your API is secured then how are we going to achieve this ? We can leverage external identity providers to secure our APIs like (Azure AD, Auth0 (https://auth0.com))
Limit call rate - If you want to cap number of call from external Users ? e.g. free tier would only allow 100 req/min etc .
Sign up process - For external users you need to take care how do they have to sign up to your services (acquire token) to access your services.
Scaleable - Your APIs should be scaleable.
HATEOAS - This is very important REST principal. IF you follow this pattern your external users can explore your API in a better way by just following links (https://en.wikipedia.org/wiki/HATEOAS).
Open API Your API should be very well documented and Open API (swagger) is very much a standard now (https://swagger.io/specification/)
You can do all these tasks by your self or you can use Any API manager to do that.

One concrete way to achieve this is with a REST API secured using Json Web Tokens (JWT). On each REST endpoint, you can specify the roles that are allowed to call that endpoint.
For your use case, you could achieve this with a "system" role for internal callers, and unauthorized (i.e. no role) for external callers.
A framework you can use to achieve this is MicroProfile JWT, which might look something like this:
#Path("/rank")
#ApplicationScoped
public class RankingService {
#GET
#Path("/{playerId}")
public long getRank(#PathParam("playerId") String id) {
// get the ranking info for a player
// anyone is allowed to do this
}
#POST
#RolesAllowed({ "system" })
#Path("/{playerId}")
public void recordGame(#PathParam("playerId") String id,
#QueryParam("place") int place,
#HeaderParam("Authorization") String token) {
// update player ranking information
// only internal users are allowed to update ranks!
}
}
Here is a link to a talk that I gave at conference that walks through securing a REST endpoint using MicroProfile JWT.

Related

Is there a point to use method level security in spring if we secured the REST API from the configuration

I would like to ask if there is a point to secure the methods which I call in a REST Controller with Pre and Post annotations. I have configured a security through java configuration like this:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.and()
.formLogin()
(...)
.and()
.authorizeRequests()
.antMatchers("/api/**").hasAuthority("ROLE_USER");
}
So every request under /api should be authorized with ROLE_USER. I tried to find some information about this in the internet but the only thing i could find was this:
https://coderanch.com/t/549265/Spring/method-security-spring-security
However I really can't think of a use case where a hacker would access somehow the methods in the service layer.
URL security and method security in service layer aims at different use cases.
If all you need is control that only users with a certain role can call URL with a given prefix (here API) URL security is what you need full stop.
If you have a complex application where some service methods can be called from different controllers and you want to make sure that you did not fail to restrict an access, method security can come to help by ensuring that only valid users can do certain business actions.
If you have a complex security model, for example several officse with one manager in each that has read and/or write access to his own employees data, method security on service layer directly using business model objects is the way to go.
BTW, using method security in a controller or even worse on a rest controller is generally design smell: if you can do it inside a controller it is generally better to use URL security. If it seems to make sense, you probably have imported business logic into a Fat Ugly Controller. Not speaking about method security being implemented with Spring AOP using by default JDK proxies, when controllers generally do not implement interfaces.
In addition to making it possible to have some kinds of functionality, using both techniques gives an additional layer of security.
Method level security is used to authorize the user. Spring security performs two basic operations before allowing the access.
Authenticate (Who is the user)
Authorize (What authorities the user has)
so for example if the user is having an authority of ROLE_USER and later in the architecture you decide to have rights assigned to some of the roles.
for example let's consider a role 'ROLE_USER'
and following rights has been assigned to the USER
CAN_VIEW_DATA
CAN_ADD_SUB_USERS
and so on.
so when some of the users have the right of CAN_ADD_SUB_USERS and some dont, then the method level security comes in handy.
Of course you have to play with the spring configurations for the rights and authority. But Once configured it provides an extra level of security that the applicaton might need.
Refer to this link for more info http://www.baeldung.com/role-and-privilege-for-spring-security-registration
REST is stateless. You should send something like access token (like Google API) with every request:
https://{server}/api/customers?access_token=BGhznFGDS
You can also send this information via Header-Attribute. The validation layer (Filter) decides whether the controller method may be called or not.
I prefer to implement my own Filters to get 100% of control.

Framework/lib/pattern to secure rest endpoint

Generally all rest based framework provide authenticate.
But are there any framework/lib/pattern that helps to secure rest endpoint with following capability
Only a authenticated user with following roles can access a end point with only particular params.
Basically i am trying to prevent two user(with same roles) to view each other data by passing each other id in request urls
Yeah you should look at Apache Shiro it offers really good support role base/permission based authorization.
An example of how you can annotate an endpoint would be:
#RequiresRoles(value = "admin")
I'd recommend you to check the Instance-Level Access Control of this document.

"Sessions" with Google Cloud Endpoints

This question is only to confirm that I'm clear about this concept.
As far as I understand, Google Cloud Endpoints are kind of Google's implementation of REST services, so that they can't keep any "session" data in memory, therefore:
Users must send authentication data with each request.
All the data I want to use later on must be persisted, namely, with each API request I receive, I have to access the Datastore, do something and store the data again.
Is this correct? And if so, is this actually good in terms of performance?
Yes you can use session, only put another Paramether in your API method with HttpServlet:
#ApiMethod
public MyResponse getResponse( HttpServletRequest req, #Named("infoId") String infoId ) {
// Use 'req' as you would in a servlet, e.g.
String ipAddress = req.getRemoteAddr();
...
}
The datastore is pretty quick especially if you do a key lookup (as apposed to query). if you use NDB then you will have the benefit of auto memache your lookups.
Yes, your Cloud Endpoints API backend code (Java or Python) is still running on App Engine, so you have the same access to all resources you would have on App Engine.
Though you can't set client-side cookies for sessions, you still can obtain a user for a request and store user-specific data in the datastore. As #Shay Erlichmen mentioned, if you couple the datastore with memcache and an in-context cache (as ndb does), you can make these lookups very quick.
To do this in either Python or Java, either allowed_client_ids or audiences will need to be specified in the annotation/decorator on the API and/or on the method(s). See the docs for more info.
Python:
If you want to get a user in Python, call
endpoints.get_current_user()
from within a request that has been annotated with allowed_client_ids or audiences. If this returns None, then there is no valid user (and you should return a 401).
Java:
To get a user, on an annotated method (or method contained in an annotated API), simply specify a user object in the request:
import com.google.appengine.api.users.User;
...
public Model insert(Model model, User user) throws
OAuthRequestException, IOException {
and as in Python, check if user is null to determine if a valid OAuth 2.0 token was sent with the request.

Securing jax-rs with OAuth

I have following problem:
I have JAX-RS service which has a get operation:
#Path("/unsecure/")
#Produces("application/json")
public class MyUnsecureService {
public MyUnsecureService() {
}
#GET
#Path("/get/{id}")
#Produces("application/json")
public User get(#PathParam("id") String id) {
return User.get(id);
}
}
now, I'm going to open this API for mobile devices and I need authentication and authorization mechanism to access the API.
My problem is that I have trusted apps (internal jobs, a website which runs on my hosting) which should be able to expose this API as they want, with no limitation, and mobile devices, which should be able to expose this API only if they have a token, formed using real User's encrypted login/pass, which can be used on service-side to determine:
If the request to that method is allowed.
If the parameters are correct (so, the user can't get other user's info).
Is this possible to do using OAuth1 or OAuth2?
This is a very valid question to raise.
You might want to have a look at Oz (backgroud), which AFAIU will go a long way towards your use cases. Personally, I have interest to solve the issue for Java and track Eran's work with Java implementations ( jiron, hawkj ). To finally do Oz (or something like it) in Java.
Much is not ripe for publishing right now, but get in touch for details if you like.
Specific problem with JAX-RS right now seems to be SecurityContext.
The answer is found:
Using Client Credentials and Resource Owner authorization grants, which are implemented in OAuth2 implementation of Apache CXF.

JAXWS and sessions

I'm fairly new to writing web services. I'm working on a SOAP service using JAXWS. I'd like to be able to have users log-in and in my service know which user is issuing a command. In other words, have some session handling.
One way I've seen to do this is to use cookies and access the HTTP layer from my web service. However, this puts a dependency on using HTTP as the transport layer (I'm aware HTTP is almost always the transport layer but I'm a purist).
Is there a better approach which keeps the service layer unaware of the transport layer? Is there some way I can accomplish this with servlet filters? I'd like the answer to be as framework agnostic as possible.
I'm working on a SOAP service using JAXWS. I'd like to be able to have users log-in and in my service know which user is issuing a command. In other words, have some session handling.
Conventional Web services are stateless in nature, there is no session handling in web services (which has by the say nothing to do with identifying the caller).
If you want to require your users to be authenticated to call a service, the traditional approach is to:
Expose an "authentication" web service (passing user credentials) that returns an authentication token.
Have the users call this authentication first.
Have the users pass the token in a custom header on subsequent calls of "business" web services.
On the server side:
Reject any call that doesn't contain a valid token.
Invalidate tokens after some time of inactivity
You can implement a custom solution for this approach (this is a highly interoperable solution). Or you can use WS-Security/UsernameTokens that provides something similar out of the box. WS-Security is a standard (Metro implements it), it isn't "framework" specific.
As you mention, servlet filters can provide the basis of solution. Use a filter to store the current session details (e.g. the session context Map) in a threadLocal storage. This is implemented as your application class, so is transport agnostic. Your service simply uses a static method to fetch the current context, unaware of where it came from.
E.g.
class ServiceSessionContext
{
static ThreadLocal<Map> local = new ThreadLocal<Map>();
// context set by the transport layer, e.g. servlet filter
static public void setContext(Map map)
{
local.put(map);
}
// called when request is complete
static public void clearContext()
{
local.put(null);
}
// context fetched by the service
static public Map getContext()
{
return local.get();
}
}

Categories