I have a SOA which makes heavy use of nonces (i.e, one-time one-use security tokens).
My app takes a nonce from a client, verifies it, then sends a new nonce back to said client as part of every reply. Also included in each reply are the results of business logic operations that executed right after the nonce was authenticated.
The nonce verification and generation are operationally coupled with the business logic, since both occur in response to every client request. However I don't want the two to be coupled in code. What's the right way to partition them in accordance with SOA principles? Is it too much to break the security and business logic into two separate services, with one calling the other as part of each reply to each client request?
Yes it makes sense to separate them. But I don't think they should have awareness of each other at all (Call each other directly).
I'll dive into a specific example and technology of how something similar is implemented.
In the web frame work Struts2 all incoming requests pass through a stack of operations(called interceptors) before arriving at a user defined object (called an action). The action then will access the business tier.
When submitting a web form there is the issue of double submission. So one way to protect against this is with a token that is sent along with the form submission. So we need to create a unique token place it as a hidden field, and then when we receive the request only process it if the token is good. This prevent users from doing something like accidentally buying something more than once.
In Struts2 there is a special server side token tag which creates the hidden field for us. So there is something that needs to be done for each form. The token interceptor if active will enforce that this value always exists and is good when receiving the form and will redirect responses that do not somewhere else.
The idea of implementing a nonces interceptor/filter that checks that the incoming nonce value is good and for responses adds the correct nonces value to the response should be completely independent of the business logic.
The example here is with html forms but adding an interceptor(or whatever you call "that which handles cross cutting concerns at the request/response level" for your appropriate technology) which adds such a value to json or xml messages should be pretty easy and likely produce the most elegant result.
The following is a link to struts2 interceptor reference (it might clarify the idea better):
http://struts.apache.org/2.2.1.1/docs/interceptors.html
The following two links are both interceptors which manage tokens:
http://struts.apache.org/2.2.1.1/docs/token-interceptor.html
http://struts.apache.org/2.2.1.1/docs/token-session-interceptor.html
I expect only the first few paragraphs of each link will be useful but something like it for your technology should be nice.
I think what you outlined above would be in keeping with SOA principles. You're keeping two distinct sets of operations separated - once service has the business logic, the other has the security logic.
This would be especially true if you have (or the potential of having) other services that would rely on nonces.
Related
It is a multi-tenant serverless system.
The system has groups with permissions.
Users derive permissions based on the groups they are in.
If it makes a difference, we are using Cognito for authentication and it is a stateless application.
For example:
GET endpoint for sites (so sites that the logged-in user has access to based on the groups they are in)
GET endpoint for devices (so sites that the logged-in user has access to based on the groups they are in)
In REST APIs. "The idea is that the data returned by an endpoint should depend solely on the parameters passed meaning two different users should receive the same result for the identical request.
"
What should the REST URI look like to ensure the above-stated idea? Since the deciding factor for the list here is "groups" and thus effective permissions, I was thinking we could pass the groups a user in, in the URI in sorted order to leverage caching on GET endpoints as well, Is there a better way to do it?
In REST APIs. "The idea is that the data returned by an endpoint should depend solely on the parameters passed meaning two different users should receive the same result for the identical request. "
No this is not strictly true. It can be a desirable property, but absolutely not needed. In fact, if you build a proper hypermedia REST api, you would likely want to hide links/actions that the current user is not allowed to use.
Furthermore, a cache will never store responses and send to different users if an AUthorization header is present on the request.
Anyway, there could be other reasons to want this.. maybe it's a simpler design for your case, and there is a pretty reasonable solution.
What I'm inferring from your question is that you might have two endpoints:
/sites
/devices
They return different things depending on who's accessing. Instead of using those kind of routes, you could just do:
/user/1234/sites
/user/1234/devices
Now every user has their own separate 'sites' and 'devices' collection. The additional benefit is that if you ever want to let a user find the list of sites or devices from another user, the API is ready to support that.
The idea is that the data returned by an endpoint should depend solely
on the parameters passed
This is called the statelessness constraint, but if you check the parameters always include auth parameters because of this. The idea is keeping the session data on the client side, because managing sessions becomes a problem when you have several million users and multiple servers all around the world. Since the parameters include auth data, the response can depend on this data, so you can use here the exact same endpoints for users with different permissions.
As of the responses you might want to send back hyperlinks, which represent the available operations. The concept is the same here, if the user does not have permission for the actual operation, then they won't get a hyperlink for that operation and in theory they should never get a 403 status either, because you must follow the hyperlinks you got from the service instead of hardcoding URI templates into your client. So you have to handle less errors and junk requests, and another reason here that you can change your URI templates without breaking the clients. This is called hypermedia as the engine of application state, it is part of the uniform interface constraint.
So we were starting a new project from scratch and one of the developers suggested why have any GET API requests as POST API's are better in every which way. (At least when using a mobile client)
On further looking into this it does seem POST can do everything GET can do and it can do it better -
slightly more secure as parameters are not in URL
larger limit than GET request
So is there even a single reason to have a GET API ? (This will only be used from a mobile client so browser specific cacheing doesn't affect us)
Is there ever a need to have GET request API as POST is better in every way?
In general, yes. In your specific circumstances -- maybe no.
GET and POST are method tokens.
The request method token is the primary source of request semantics
They are a form of meta data included in the http request so that general purpose components can be aware of the request semantics and contribute constructively.
POST is, in a sense, the wildcard method - it can mean anything. But one of the consequences of this is - because the method has unconstrained semantics, general purpose components can't do anything useful other than pass the request along.
GET, however, has safe semantics (which includes idempotent semantics). Because the request is idempotent, general purpose components know that they can resend a GET request when the server returns no response (ie messages being lost on unreliable transport); general purpose components can know that representations of the resource can be pre-fetched, reducing perceived latency.
You dismissed caching as a concern earlier, but you may want to rethink that - the cache constraint is an important element that helped the web take over the world.
Reducing everything to POST reduces HTTP from an application for transferring documents over a network to dumb transport.
Using HTTP for transport isn't necessarily wrong: Simple Object Access Protocol (SOAP) works that way, as does gRPC. You still get authorization, and conditional requests; features of HTTP that you might otherwise need to roll your own.
You aren't doing REST at that point, but that's OK; not everybody has to.
That doesn’t mean that I think everyone should design their own systems according to the REST architectural style. REST is intended for long-lived network-based applications that span multiple organizations. If you don’t see a need for the constraints, then don’t use them. (Fielding, 2008)
I am writing a backend for my application that will accept query parameters from the front end, and then query my DB based on these parameters. This sounds to me like it should be a GET request, but since I have a lot of params that I'm passing with some of them being optional I think it would be easiest to do a POST request and send the search params in a request body. I know I can convert my params to a query string and append it to my GET request, but there has to be a better way because I will be passing different data types and will end up having to parse the params on the backend anyways if I do it this way.
This depends heavily on the context, but I would prefer using GET request in your scenario.
What Request Method should I use
According to the widely accepted convention, one uses:
GET to read existing data
POST to create something new
More details can be found here: https://www.restapitutorial.com/lessons/httpmethods.html
How do I pass the parameters
Regarding the way to pass parameters, it is a less obvious thing. Unless there's something sensitive in the request parameters, it is perfectly fine to send them as part of URL.
Parameters may be either part of path:
myapi/customers/123
or a query string:
myapi?customer=123
Both options are feasible, and I'd say a choice depends heavily on the application domain model. One popular rule of thumb is:
use "parameters as a part of a path" for mandatory parameters
use "parameters as a query string" for optional parameters.
I'd recommend using POST in the case where there are a lot of parameters/options. There are a few of reasons why I think it's better than GET:
Your url will be cleaner looking
You hide internal structure from the user (it's still visible if they use the Developer Tools of the browser though)
People can't easily change the options to adjust your query. Having it in the url is simple to just modify and reload with other values. It's more work to do this as a POST.
However, if it's of any use that the URL you end up with can be bookmarked or shared, then you'd want all parameters encoded as part of the query, so using GET would be best in that case.
Another answer stated that POST should be used for creating something new, but I disagree. That might apply to PUT, but it's perfectly fine to use POST to allow more complex structures to be passed even when retrieving existing data.
For example, with POST you can send a JSON body object that has nested structure. This can be very handy and would be difficult to explode into a traditional GET query. You also have to worry about URL-encoding your data then decoding it when receiving it, which is a hassle.
For simple frontend to backend communication you don't really need REST to start with as it targets cases where the server is accessed by a plethora of clients not under your control or a client has to access plenty of different servers and should work with all of them. REST should be aimed for if you see benefit in a server that can evolve freely in future without having to fear breaking clients as they will adept to changes quite easily. Such strong properties however come at its price in terms of development overhead and careful designing. Don't get me wrong, you can still aim for a REST architecture, but for such a simple application-2-backend scenario this sounds like an overkill.
In a REST architecture usually a server will tell clients how it wants to receive input data. Think of HTML forms where the method and enctype attributes specify which HTTP method to use and to which representation format the input to convert to. Which HTTP method to use depends on the use case actually. If a server constantly receives the same request for the same input parameters and calculating the result may be costly, then caching the response once and serving further requests from that cache might take away a lot of unnecessary computation overhead from the server. I.e. the BBC claims that the cache is the single most important technology in keeping sites scalable and fast. I once read that they cache most articles for only a minute but this is sufficient enough to spare them form retrieving the same content thousands and thousands of times again and again, freeing up the resources for other requests or tasks. It is no miracle that caching also belongs to one of the few constraints REST has.
HTTP by default will allow caches to store response representations for requested URIs (including any query, path or matrix parameters) if requested via safe operations, such as HEAD or GET requests. Any unsafe operation invoked, however, will lead to a cache invalidation and therefore the removal of any stored representations for that target URI. Hence, any followup requests of that URI will reach the server in order to process a response for the requesting client.
Unfortunately caching isn't the only factor to consider when to decide between using GET or POST as also the current representation format the client currently processes has an influence on the decision. Think of a client processing the previous HTML response received from a server. The HTML response contains a form that teaches a client what fields the server expects as input as well as the choices a client can make for certain input parameters. HTML is a perfect example where the media-type restricts which HTTP methods are available (GET as default method and POST are supported) and which not (all of the other HTTP methods). Other representation formats might only support POST (i.e. while application/soap+xml would allow for either GET or POST (at least in SOAP 1.2), I have never seen GET requests in reality and so everything is exchanged with POST).
A further point that may prevent you from using GET requests is a de facto limitation on the URI length most HTTP implementations have. If you exceed this limitations some HTTP frameworks might not be able to process the message exchanged. On looking at the Web, however, one might find a little workaround to such a limitation. In most Web shops the checkout area is usually split into different pages where each page consists of a form that collects some input like address information, bank or payment data and further input that as a whole act as kind of wizard to guide the user through the payment process. Such a wizard style could be implemented in this case as well. Parts of the request are sent via POST to a dedicated endpoint that takes care of collecting the data and on the final "page" of the wizard the server will ask for a final confirmation on the collected data and uses that resource as GET target. This way the response remains cacheable even though the input data exceeded the typical URL limitation imposed by some HTTP frameworks.
While the arguments listed by Always Learning aren't wrong, I wouldn't rely on those from a security standpoint. While it may filter out people with little knowledge, it won't hinder the ones for long with knowledge (and there are plenty out there) to modify the request before sending it to your server. So simply recommending using PUT as a way to making user edits harder feels odd to me.
So, in summary, I'd base the decision whether to use POST or GET for sending data to the server mainly on the factor whether the response should be cacheable, as it is often requested, or not. In cases where the URI might get so large that certain HTTP frameworks may fail processing the request you are basically forced to use POST anyway unless you can split the actual request into multiple tinier requests which act as wizard for the data collection until a final confirmation request triggers the actual final HTTP call.
Background
I'm having a trouble with the design and implementation of a REST service which publishes content that some users cannot view (medical information, you know, country's laws), I'm using a ABAC-like/RBAC system to protect them, but what causes me concern is that I may be violating the REST pattern. My services does the following process for each query:
The security middleware reads a token from a session that an app/webpage sends using authorization header or cookies.
ABAC/RBAC Rules are applied to know if user can access the resource.
After authorize the token, my service executes the query and filters the results, hiding content that requesting user cannot see (if needed. POST, PUT and DELETE operations are almost exempt from this step). The filter is done using ABAC/RBAC rules.
An operation report is stored in logs.
I already know that sessions violates REST pattern, but I can replace it using BASIC/DIGEST authorizations. My real question is the following:
Question
Does hiding resources from list/retrieve operations violates REST pattern? As far I know, REST is stateless, so ... What happens if I use some context variables to filter my results (user id)? Am I violating REST? Not at all?
If I do, What are your recommendations? How can I implement this without breaking REST conventions?
First of all, client-side sessions don't violate REST at all. REST says the communication between client and server must be stateless, or in other words, the server should not require any information not available in the request itself to respond it properly. If the client keeps a session and sends all information needed on every request, it's fine.
As to your question, there's nothing wrong with changing the response based on the authenticated user. REST is an architectural style that attempts to apply the successful design decisions behind the web itself to software development. When you log in to Stack Overflow, what you see as your profile is different from what I see, even though we are both using the same URI, right? That's how REST is supposed to work.
I'd recommend returning status codes 401 (Unauthorized) if the user is not authorized to access a resource. And 404 (Not found) if you cannot confirm that the resource even exists.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4
A GET is meant to return a representation of the resource. Nowhere does it say that you must return everything you know about that resource.
Exactly what representation is returned will depend on the request headers. For example of you might return either JSON or XML depending on what the client requested. Extending this line of thinking; it is ok to return different representations of a resource based on the client's authentication without violating REST principals.
I am a bit confused about how XEP-0114 works. Does servicing a domain using a component mean that the server will no longer do anything on behalf of that domain, or does it just mean that the component will ALSO be allowed to service all users on that domain.
More specifically, is it possible to have multiple components servicing the same domain? For example, one component could handle MUC, another could store all messages in a history store, and a third could handle the roster, etc... All while the XMPP server continues handling the user like it normally would - and replying to presence, iq packets, etc... What this means is that components would have to be written so that their realm doesn't intersect with each other.
Answering #dhruvbird's second question in the comments above, if you have delegated a domain to your XEP-114 component, that component is responsible for everything about that domain, including all of the presence states of the users in that domain. That is possible, if tedious, but make sure you've read the new RFC 6121 recently.
Note: most servers have a component that implements all of this presence subscription logic - it's where the real IM business logic is implemented. You'll effectively be writing a replacement for that logic, so make sure there's no other way to solve your problem first.