62

I'm trying to design a green-field project that will have several services (serving data) and web-applications (serving HTML). I've read about microservices and they look like good fit.

The problem I still have is how to implement SSO. I want the user to authenticate once and have access to all the different services and applications.

I can think of several approaches:

  1. Add Identity service and application. Any service that has protected resources will talk to the Identity service to make sure the credentials it has are valid. If they are not it will redirect the user for authentication.

  2. Use a web-standard such as OpenID and have each service handle it own identities. This means the user will have to authorize individually each service/application but after that it will be SSO.

I'll be happy to hear other ideas. If a specific PaaS (such as Heroku) has a proprietary solution that would also be acceptable.

Matthew Murdoch
  • 30,874
  • 30
  • 96
  • 127
Ido Ran
  • 10,584
  • 17
  • 80
  • 143
  • So by reading this, I'm guessing there is no official standard way to tackle this kind of issue? – Augustin Riedinger Apr 14 '15 at 09:41
  • 1
    You are right. I'm using my own OAuth provider to get a SSO result but it is not the only way. – Ido Ran Apr 18 '15 at 05:15
  • 1
    I stumbled on this thread (and many more sites). I found these 2 sites to be very useful in this regards: https://medium.facilelogin.com/securing-microservices-with-oauth-2-0-jwt-and-xacml-d03770a9a838 http://nordicapis.com/how-to-control-user-identity-within-microservices/ – Yogi Mar 23 '17 at 14:19

2 Answers2

51

While implementing a microservice architecture at my previous job we decided the best approach was in alignment with #1, Add identity service and authorize service access through it. In our case this was done with tokens. If a request came with an authorization token then we could verify that token with the identity service if it was the first call in the user's session with the service. Once the token had been validated then it was saved in the session so subsequent calls in the user's session did not have to make the additional call. You can also create a scheduled job if tokens need to be refreshed in that session.

In this situation we were authenticating with an OAuth 2.0 endpoint and the token was added to the HTTP header for calls to our domain. All of the services were routed from that domain so we could get the token from the HTTP header. Since we were all part of the same application ecosystem, the initial OAuth 2.0 authorization would list the application services that the user would be giving permission to for their account.

An addition to this approach was that the identity service would provide the proxy client library which would be added to the HTTP request filter chain and handle the authorization process to the service. The service would be configured to consume the proxy client library from the identity service. Since we were using Dropwizard this proxy would become a Dropwizard Module bootstrapping the filter into the running service process. This allowed for updates to the identity service that also had a complimentary client side update to be easily consumed by dependent services as long as the interface did not change significantly.

Our deployment architecture was spread across AWS Virtual Private Cloud (VPC) and our own company's data centers. The OAuth 2.0 authentication service was located in the company's data center while all of our application services were deployed to AWS VPC.

I hope the approach we took is helpful to your decision. Let me know if you have any other questions.

Chris Sterling
  • 526
  • 6
  • 5
  • Even I have ended up with same situation but in my case I have many micro services but I don't want user to grand permission(assuming if I use Oauth) for other microservices explicitly eg:in a e-commerce site if user is authenticated in main app, I don't want user to authorize cart app,suggestion app explicitly(this should be seamless for end user) is there any way we can achieve this using Oauth or SAML? – Lohith MV Jul 19 '15 at 14:23
  • 1
    what's the meaning of "All of the services were routed from that domain"? – wonder Oct 17 '16 at 10:53
  • Thanks for the tip; I implemented my sso based on your tip. Here's a video of my interpretation to the approach outlined in your comment: https://www.youtube.com/watch?v=r7FAuAlKIqY&t=36s – Cokorda Raka May 03 '17 at 00:58
  • Thanks for the great write up. How can the session invalidation be handled on each service in this case? – Ankit Kumar Jul 11 '17 at 04:08
  • I would argue the service should use it's own session cookie after initial validation with the auth server. Reusung the token from the auth server adds some undesirable dependcy. What if the auth server changes the format of it's tokens and they don't fit in the services session store anymore. – xuma202 Mar 05 '22 at 10:55
41

Chris Sterling explained standard authentication practice above and it makes absolute sense. I just want to put another thought here for some practical reasons.

We implemented authentication services and multiple other micro services relying on auth server in order to authorize resources. At some point we ran in to performance issues due to too many round trips to authentication server, we also had scalability issues for auth server as number of micro services increased. We changed the architecture little bit to avoid too many round trips.

Auth server will be contacted only once with credentials and it will generate the token based on a private key. Corresponding public key will be installed in each client (micro service server) which will be able to validate the authentication key with out contacting auth server. Key contain time generated and a client utility installed in micro service will validity as well. Even though it was not standard implementation we have pretty good success with this model especially when all the micro services are internally hosted.

kamoor
  • 2,909
  • 2
  • 19
  • 34
  • 3
    I think what you are describing is already done by Chris, as he says > *it was saved in the session so subsequent calls in the user's session did not have to make the additional call.* Maybe I'm wrong. – Augustin Riedinger Apr 14 '15 at 09:38
  • 7
    Saving in session may not be scalable or not recommended due to stateless nature of end points. In my approach it will never save anything, just use public key cryptography to avoid round trips to auth server. – kamoor Apr 15 '15 at 19:10
  • 1
    > *Even though it was not standard implementation*. What do you call standard implementation? – Augustin Riedinger Apr 16 '15 at 07:23
  • This sounds very interesting - is it fully stateless though? How does each microservice validate a token received in a request? – Constantinos Feb 24 '16 at 11:29
  • 1
    It is stateless because key can be validated at any resource server. We are making use power of asymmetric encryption to avoid network calls. – kamoor Feb 24 '16 at 16:12
  • 6
    so how would you handle session expiry? – Constantinos Feb 24 '16 at 18:17
  • 3
    or token revocation? – neverfox Feb 28 '17 at 18:45
  • 1
    I don't understand how would the session expiration/revocation be handled with this approach as asked earlier. – Ankit Kumar Jul 11 '17 at 03:59
  • I think the best practice is to use JWT tokens. To track token revocation based on user logout you can use redis :) There is also an https://redis.io/commands/expire feature. You can use it to delete expired tokens automatically (also these token expiration data should be injected into JWT's content) – Marat Mkhitaryan Sep 26 '19 at 06:58
  • 1
    You’re doing authentication wrong by the sounds of it.. Issue a token, pass that to every service on every call and validate at the service level - that completely removes the need to store tokens and call the auth service for anything other than issuing a token – Robert Perry Dec 14 '21 at 09:24
  • @MaratMkhitaryan when you query redis for every request anyways there is no benefit from JWT. It's better to use Session Cookies and a stateful service. The above solution has some downsides too. How to sync the public keys and more imoirtantly how to determine the user for a session without making assumtions on the token from the auth server – xuma202 Mar 05 '22 at 10:52