SOA Service Design / Authentication - authentication

I'm rather new to SOA and therefore experimenting around.
Currently, the part that creates the biggest problem to me is authentication, my current thought about it involves the following:
The client sends some kind of authentication message to the authentication / user service, this service queries the db and if the user is found and the password is valid, it will respond with a session id, this id will be used in all further requests of this client.
This seems rather ok to me but I don't know how I should handle the requests to other services, I thought of three different approaches.
Every service asks the authentication service if the session is valid and if so, what roles the user is in. The authentication service looks in the db and replies accordingly.
The authentication service keeps all session information in ram and responds without the db roundtrip to the requests.
The authentication service sends an authorized message to an esb, the esb forwards this authorized message to every service and these services cache it. No further requests to the authentication service would be necessary. If the user logs out or his roles change, another message would be send around and processed by all services.
I think the first approach creates too much stress on the authentication service / db but takes the least effort to implement.
The second is still very easy to implement but the stress on the authentication service remains almost the same.
The third is a little more complicated to implement but would has reduced response time as no trips to the authentication service take place. Though, if there are too much session information this approach would just fail and scalability is hardly given.

The best approach should be like this if all the services are internal,
The authentication service issues a token the the service client.
Service client includes the token in the SOA message wrapped in WS-Security or something similar.
The service should validate the token with authentication service before providing the service.
For external services, I suggest you look at federated solutions like SAML.

Don't do premature optimization. Your option no. 3 which you acknowledge will be more complicated to implement is unnecessary. Choose option no. 2 if that's what you can implement fast. You can profile later and change it, but I'd bet money that you won't have a 'bottleneck' when going with option 2.

Related

Microservice Authentication Architecture

I'm starting to write a few microservices that will have independent web clients, a centralized authentication and authorization service, and an organization service. The organization service will keep track of who belongs to what organization and what that organization has paid for. This will tell me who can access which web client and what parts of each individual microservice. I've only developed authentication using Devise in a single Rails monolith, so I'm exploring how to do it in a multi microservice and web client ecosystem. I've come up with this:
Web Client makes a request to a microservice and is denied because lack of session information sent in the request.
Web Client makes a login request to the Authentication service. The Authentication makes a request to the Organization service to see what organizations the user is a part of as well as the services paid for. The session info is stored in the Web Client for future use in requests.
Web Client makes a request to the Microservice. The Microservice validates the session information (from 2) against the Authentication service, which in turn reaches out to the Organization for the user's organizations and the organization's services. The response from Authentication is stored in the Microservice. The response back to the Web Client is granted if the two sets of session information match.
Web Client makes a request to the Microservice, including the session info (from 2). The Microservice validates the session info against the stored session info (from 3). The response back to the Web Client is granted if the two sets of session information match.
Is this the proper way to authenticate? Is there a better way to do it? Are there small tweaks I should make?
Additionally, should I treat Authentication from the Web Client to the Microservices differently than Authentication between Microservices?
Do yourself a huge favor, and don't try to invent this yourself. Many, many people have written a fully functional auth & auth system, and a few of them have done it right. Unless you are a security specialist (which you likely aren't if you are asking this question), use a framework.
Start by looking at OAuth 2.0 and OpenId Connect providers, it is the de-facto standard in distributed authentication. Whichever language/platform you are using, likely has an implementation that you can leverage out-of-the-box. This will dramatically speed you up, and will likely avoid all the things that you will be doing wrong in your implementation.
Here you are, ready out of the box, Identity Server based on Open ID and Auth2.0 that is all what you need.
welcome-to-identityserver4
If you were interested in the topic of Microservices Architecture the following links are a set of articles that published about microservices in code-project, you can read and comment on your questions if you like.
https://www.codeproject.com/Articles/1264113/Dive-into-Microservices-Architecture-Part-I
https://www.codeproject.com/Articles/1264113/Dive-into-Microservices-Architecture-Part-II
https://www.codeproject.com/Articles/1264113/Dive-into-Microservices-Architecture-Part-III

Microservices - how to solve security and user authentication?

There is a lot of discussion about microservice architecture. What I am missing - or maybe what I did not yet understand is, how to solve the issue of security and user authentication?
For example: I develop a microservice which provides a Rest Service interface to a workflow engine. The engine is based on JEE and runs on application servers like GlassFish or Wildfly.
One of the core concepts of the workflow engine is, that each call is user centric. This means depending of the role and access level of the current user, the workflow engine produces individual results (e.g. a user-centric tasklist or processing an open task which depends on the users role in the process).
In my eyes, thus a service is not accessible from everywhere. For example if someone plans to implement a modern Ajax based JavaScript application which should use the workflow microservice there are two problems:
1) to avoid the cross-scripting problem from JavaScript/Ajax the JavaScript Web application needs to be deployed under the same domain as the microservice runs
2) if the microservice forces a user authentication (which is the case in my scenario) the application need to provide a transparent authentication mechanism.
The situation becomes more complex if the client need to access more than one user-centric microservices forcing user authentication.
I always end up with an architecture where all services and the client application running on the same application server under the same domain.
How can these problems be solved? What is the best practice for such an architecture?
Short answer: check OAUTH, and manage caches of credentials in each microservice that needs to access other microservices. By "manage" I mean, be careful with security. Specially, mind who can access those credentials and let the network topology be your friend. Create a DMZ layer and other internal layers reflecting the dependency graph of your microservices.
Long answer, keep reading. Your question is a good one because there is no simple silver bullet to do what you need although your problem is quite recurrent.
As with everything related with microservices that I saw so far, nothing is really new. Whenever you need to have a distributed system doing things on behalf of a certain user, you need distributed credentials to enable such solution. This is true since mainframe times. There is no way to violate that.
Auto SSH is, in a sense, such a thing. Perhaps it may sound like a glorified way to describe something simple, but in the end, it enables processes in one machine to use services in another machine.
In the Grid world, the Globus Toolkit, for instance, bases its distributed security using the following:
X.509 certificates;
MyProxy - manages a repository of credentials and helps you define a chain of certificate authorities up to finding the root one, which should be trusted by default;
An extension of OpenSSH, which is the de facto standard SSH implementation for Linux distributions.
OAUTH is perhaps what you need. It is a way provide authorization with extra restrictions. For instance, imagine that a certain user has read and write permission on a certain service. When you issue an OAUTH authorization you do not necessarily give full user powers to the third party. You may only give read access.
CORS, mentioned in another answer, is useful when the end client (typically a web browser) needs single-sign-on across web sites. But it seems that your problem is closer to a cluster in which you have many microservices that are managed by you. Nevertheless, you can take advantage of solutions developed by the Grid field to ensure security in a cluster distributed across sites (for high availability reasons, for instance).
Complete security is something unattainable. So all this is of no use if credentials are valid forever or if you do not take enough care to keep them secret to whatever received them. For such purpose, I would recommend partitioning your network using layers. Each layer with a different degree of secrecy and exposure to the outside world.
If you do not want the burden to have the required infrastructure to allow for OAUTH, you can either use basic HTTP or create your own tokens.
When using basic HTTP authentication, the client needs to send credentials on each request, therefore eliminating the need to keep session state on the server side for the purpose of authorization.
If you want to create your own mechanism, then change your login requests such that a token is returned as the response to a successful login. Subsequent requests having the same token will act as the basic HTTP authentication with the advantage that this takes place at the application level (in contrast with the framework or app server level in basic HTTP authentication).
Your question is about two independent issues.
Making your service accessible from another origin is easily solved by implementing CORS. For non-browser clients, cross-origin is not an issue at all.
The second problem about service authentication is typically solved using token based authentication.
Any caller of one of your microservices would get an access token from the authorization server or STS for that specific service.
Your client authenticates with the authorization server or STS either through an established session (cookies) or by sending a valid token along with the request.

How to use tokens in 3-tier web-app using WCF

Good day. I've looked all over for an example of how to do this, and while I have found all sorts of useful info on how to implement bits of it, the overall solution still eludes me.
I have a 3-tier web-based application (Presentation tier is Web Forms, business/DAL tier is a WCF web service, DB is Oracle) for which I want to implement an Authorization/Authentication mechanism.
My thought was to use the Enterprise Library Securty block to generate a token in the WCF service (and cache it there), and send the token id back to the web-app server. The token id would be sent back to the client browser (via a cookie) and then all subsequent requests back to the WCF service I would pass this token id in the header of the request message. I would then use some of the WCF extensibility interfaces to check for authentication by looking for the id in the cache. I was also going to cache the roles (I'm just using simple role based access) with the token so that I had in-memory access to the roles list for the user and I could avoid a DB round-trip for every access check.
Does this part make sense as to the right way to go? If so, here is the second part.
Now my problem is how to manage role access and session management from the webserver hosting the presentation tier. I'm managing the roles from the business layer, but I also need access to them in the presentation layer because I also wanted to use role-based access to each page via the web.configs. How do I do this? should I also pass the roles back to this layer? There is something smelly about both the service and the webapp having to store versions of this rolelist.
Any assistance would be much appreciated!

"Guarding" WCF service from certain users - application identity

We are using WCF services. Right now, we are using Windows Auth but this is not for long. Some services will sit outside the firewall and use username/password verified in the database.
My tech lead is "scared" at how easy any user can "Add Reference" to the services we have and just party on. He wants to "guard" the services by adding another identity - the application. He wants the service to accept requests from certain applications so the certain users cannot just use the service - add reference to it and call. It’s the notion of the application having an identity + credentials that is the operative principle here, as services on the network may need to authenticate those credentials prior to fulfilling a request, in order to prevent rogue code inside the network (i.e., NOT the application) from accessing services using “Joe User” end-user credentials.
Does this make any sense?
Then he believes the Juval Lowy's book has, in an Appendix that discusses sending more than one identity during a WCF call (Security Interceptor). There is no specific suggestion that all of those have to be end-user identities and if that is the case, one of those could be the identity of the application making the request.
How can this be done?
Thanks,
Sam
The problem with sending an application identity is that the secret used to confirm that identity has to be stored somewhere. If it is visible to one application on a machine then generally it will be visible to other applications running under the same identity.
Would your manager be happy with "it came from an authorised machine"? If that's the case you could simply use Client Certs
Its also worth taking a step back: if the user is authenticated and is authorized to perform the functionality they have requested, why do you care which application they came from - if they are who they say they are and they are allowed to do what they are requesting then why couldn't they use, say, fiddler to make the request - isn't that the point of a service (rather than a closely coupled client server app)?
You might want to look through Common Security Scenarios in the MSDN documentation to see if any of those options fit your needs.
The options that pops to my eye are Transport Security with Certificate Authentication and Message Security with Mutual Certificates. Both rely on X.509 certificates. The latter option is on the message level, so you can handle certificate delivery and security negotiation however you want.
To make it a lot harder for someone to add a reference to your service you could just remove the mex endpoint. This way it would be very difficult for a stranger to create a valid request message.
You can then distribute the WSDL manually, only to people you trust.

WCF sessions or pass username/password per call?

For an enterprise type WCF service, where potentially 10K's of thousands of clients will be authenticating and sending data to central servers, what is 'best' practice when it comes to sessions or authentication?
does WCF support a session, if yes, should I use it?
or should I simply pass username/password on a per call basis?
As blowdart mentioned, WCF Sessions are not the same as ASP.NET Sessions. You can read up on them here: http://msdn.microsoft.com/en-us/library/ms733040.aspx. Before you roll your own security, you'll want to get familiar with what WCF gives you out-of-the-box: http://msdn.microsoft.com/en-us/library/ms734736.aspx. They may get you close to your goal without writing a lot of code. Specifically, check out How to: Create a Secure Session. With secure sessions, the Client and Server cache credentials so you don't have to fully authenticate with each request. By default, you'll lose a secure session if the web server recycles. If you want a secure session that lasts through a recycle, you'll want to look at How to: Create a Stateful Security Context Token for a Secure Session.
WCF does support sessions yes; but they are not like ASP.NET sessions. Sessions are there to deliver messages in order (and other bits and bobs), they are not there to add shared storage between calls.
For authenticated service calls you should send your authentication details every time; security is applied on a per message basis.
If you host the service within IIS, you can still use the session that is from ASP.NET
by enabling aspnetcompatibility for the service behaviour.