As an example, if I have a Post service and have a method to retrieve all posts for the logged in user, is it OK to have a findPosts() method that uses an injected Security service to get the user ID and then pass that user ID to my post DAO to get the records? Or should the findPosts() method explicitly require the user ID as an argument?
- Anybody can ask a question
- Anybody can answer
- The best answers are voted up and rise to the top
There are differing philosophies, but it very much depends on the context and requirements of your work. If multiple asynchronous connections for different service requests are required to share state that the client should not be aware of then you have few options besides some sort of session management (whether the built-in, or your own based on security tokens or other identification mechanisms). Generally speaking, however, sessions are not necessary nearly as often as they are used and often tend to lead to complications later. Session is volatile, not usually inherently thread-safe, and tied to arbitrary client details in the first place (cookies, IPs, etc.) When you don't control the client Sessions can be unreliable. I could, for example, implement a RESTful GET only client with nothing but raw HTTP requests (which someone else has actually done to me before). As a result common implementation details like cookie persistence become a requirement of your service; this isn't all that uncommon, but the less unnecessary requirements you use the more reliable the clients experiences are.
In general, whenever possible, let the state be directly associated with the individual requests. This allows individual clients more flexibility because your design explains itself and does not depend on hidden features the client won't be able to predict. It also more naturally allows multiple concurrent connections from the same client to have entirely different purposes and state. Let's say their website allows individual user logins and they make calls to your service (API) specific to the individual users; if multiple of their users are using the app at the same time you don't want to force them into a single session if they can just provide you a token with each request or something similar. It can be easy to lose track of state mutations when they are in an invisible background space and, even if the service is simple in the beginning, future additions may not realize something was using session a certain way, etc. etc. Really, this is very much the same as web pages. If you rely on session for page specific operations the user cannot use multiple tabs as it will pollute the state, whereas storing state data in a hidden form field or query string allows each tab to maintain its own state.
Generality aside, there are certainly circumstances that call for it. Distributed computing environments like WCF and other RPC system layers leveraging web services make use of service instance tracking, persistent internal fields, shared context, etc. These features either use Session or at least function very similarly from an abstract perspective. Some people disagree with these methods, but the right tool for the right job should always be the aim.
In your specific case, it sounds like you're really just trying to share authentication state between the browser and async backend requests. Authentication state is frequently sustainable in web services. Particular to authentication, it seems like you should be using security checks even if you received a userId (since it shouldn't just hand that information out to anybody) and since you already have the data it sounds perfectly safe to me (less error/hack prone, since you don't give them the option to tell you which user to use). Alternatively you can receive the parameter specifically to verify that they aren't tampering with the requests, though that only goes so far. Again, just like a web page, sharing authentication between browser tabs is not uncommon, even if the tabs have very different pages loaded, but those pages (or associated middleware) are still responsible for determining what the user can see as well as ensuring the user has the right to be on any specific page.
tl;dr - There are merits to both approaches in this context, including the use of both in tandem. Authentication is commonly shared in web services of differing variety. If these are for Ajax requests then it's especially common. In general, however, only use background shared state when necessary (much like with webpages). The same kind of care goes into deciding what will be static, thread-static, etc. Remember kids: only you can prevent forest fires. KISS
Your service should get all the information it needs to do its job in its parameters. If your service is calling something else to get a userID or anything else it needs to generate its return object that is a poor design.
It's fine for one service to utilize another service in order to do it's work. That's not a problem. However, if your PostService.FindPosts() method needs a userId, don't pass it a SecurityService, pass it the userId. In fact, you may want to call it FindPostsByUserId() just to be more explicit.
Now, you may have to get the userId from a SecurityService injected into the PostsService, but that's another issue.