Microservices authentication

2020-02-17 05:46发布

问题:

Context

I have multiple services like :

  • User (LDAP or active directory etc...)
  • Billing
  • Planning
  • etc...
  • Authentication

I need to connect on my microservices Using OAuth2.0, for beginning, using the standard login / password (I use my own data, and not gettint a third leg server)

Problem

According to these pictures :

Step 1

Step 2

How can I handle access_token control or authorization control, in my other services than authmicroservice ?

回答1:

In order to manage authentication in a microservices architecture, you must have a different point of view.

Remember when you worked on a monolith, you had a single authentication process.

As an example in PHP app, you find your user in a database with it's corresponding credentials, then you created a session a the user is "authenticated".

With microservices, the workflow is kinda the same. The only thing that changes now is that you are not able to open a session in different services. Furthermore, you don't need to get the authenticated user. You only need to be sure that he is authorized to perform the current call on your microservices.

Thanks to oauth2, having a valid access_token gives you this information.

This should answer the frontend part. In the backend part (I mean behind the api gateway), you should not manage access_token because it is not relevant to microservices. You can use a functional key to find any information relevant to the user inside microservices like a uuid for example.

In order to get a uuid while using oauth2 I suggest to use openid connect too. It is user with this protocol to manage specific user information and it gives you access to a specific endpoint "/userinfo".

Hope this schema will make this answer clearer.



回答2:

It is possible to create separate Auth service to provide access_token like you showed in step 1. But in API Gateway each service will needed to call that auth service to validate token. Its best to apply oauth process within API Gateway which I'm using as well for my product and this approach is also explained in many articles. lets look at the image below.

In technical perspective, It could simply a part of code (function) which handles request header to verify the token provided as oauth authentication, which might handled within code or by accessing own database before it forwards requests to service's endpoint.

You can follow one method to provide authentication, security and request dispatching to endpoint either by service of enhanced API Gateway. There's question already asked at stackoverflow here, But what i found easy to follow are 3 or 4 series of tutorials you'll find here

Get clear picture of your API Gateway usage before you focus on microservices to work on.



回答3:

there is a tutorial and description of authentication flow in microservices in our activator, it's in Scala — http://www.typesafe.com/activator/template/reactive-microservices (source: https://github.com/theiterators/reactive-microservices)


The basic idea is: You need to validate authenticity of the auth token for every request. You can either:

— do it in a proxy (the gateway)

— do it inside the billing microservice


What we tend to do is: to validate Auth-Token inside every client-facing microservices.

— We keep the Auth-Token to User information inside Redis instance.

— The client-facing service asks the redis instance if this token is valid

— Redis returns some JSON string that we can use as a user-data for further authorization.

So the server side flow looks like this

get("projects/" / Segment) { projectName =>
  getHeader("Auth-Token") { authToken =>
    Redis.get("auth:token:#{authToken}").map { userJson =>
      if(userJson("projects").include(projectName)) {
        ...processSth...
        Ok
      } else {
        Unauthorized
      }
    }
  }
}


回答4:

Depending on how you're structuring your micro-services, you could also take advantage of composition.

Since you already have an auth service, you could use it within your Billing service to check the authenticity of the request before processing it.

For example, if you're using a platform like StdLib (we use this in-house):

// Billing
const lib = require('lib');

module.exports = function(params, callback) {
  lib.user.isAuthenticated(params, function(err, user) {
    if (err) return callback(err);
    // Do stuff with user, process billing
  });
};

This might not be a great idea for you if you're always using HTTP to communicate between the functions (since this would add probably a good 200-300ms to your request). But StdLib loads up a few services within the same area and you can access them essentially like functions which solves for that problem (at least, so far that we've seen).