Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building authentication with Microservices Architecture

I'm developing an app with microservices and I don't know how to distribute microservices to allow auth.

I've read that each microservice should have its own database to avoid coupling.

The problem is that Authentication (via JWT) and Users Microservices must have access to the same database and table (Users). I suppose this problem has been solved before due to similar applications having to deal with the same issue.

How can I solve this?

like image 399
Javier Manzano Avatar asked Jun 25 '15 09:06

Javier Manzano


2 Answers

JWS (the signed version of a JWT) is a perfect example as it was thought for similar scnearios:

  • you have an authentication app: every login goes through that (signin.domain.com), and once you verify the credentials of a user you issue the token, generated through private keys
  • each service (service1.domain.com, service2.domain.com) can implement a middleware that instead does authorization: all your services will receive the public key and will be able to verify the authenticity of the token through that key. They don't need a DB since what they need to verify is that the token is valid, not that the user exists etc etc.

To clarify my last statement: you should probably issue very short-lived tokens. At that point, say that:

  • user X logs in
  • his token will be valid for ten minutes
  • user X deletes his account but still has a valid token
  • he then hits service.domain.com

On service.domain.com you will still consider him logged in until you, for example, need to interact with an API that actually hits the DB (ie. add a new user address). At that point the service that is responsible for writing into the DB will throw an exception saying the user doesnt exist and you can probably trap it and log the user out. All of this can be tweaked / fine-tuned but you get a rough idea of how it could work.

Getting back to JWTs and their usage, I don't know if you are familiar with PHP but this is a pretty straightforward example.

If you want to get fancy you could use nginx as a middleware and have something like the auth module doing authorization for you.

Last but not least, we've only covered authentication here: to do authorization you will probably either want to, in each service, either read the user's roles from the token (assuming you saved them there once the user logs in -- but this is a bit flawed as if a user loses a role then his token would still list it) or simply call signin.domain.com/users/me from each service to retrieve an up-to-date list of user roles, and then check that he's allowed to perform certain operations on that specific service.

Oh, and remember that you should never put sensitive data in a JWT / JWS as they can be decoded. So yes, you can add user roles to a JWT but, for example, never save passwords or other plaintext tokens there.

Hope this helps!

like image 165
odino Avatar answered Nov 02 '22 17:11

odino


We solve this by using composition of services to protect services that need authentication. A lot like the way you would approach it if it was a monolith.

As @odino mentioned:

  • Use an Auth service to authenticate the user and generate a token (we use an OAuth flow for this)
  • Subsequent services would then use the token to verify if the user exists by passing it through the Auth service ("composition")

Here's an example with StdLib (what we use in-house):

const lib = require('lib');

module.exports = function(params, callback) {
  lib.user.isAuthenticated(params, (err, user) => {
    if (err) return callback(err);

    // We're authenticated – do the rest of the work.
  });
}

The caveat to this is that if you're using HTTP as the protocol to communicate between your services, you're essentially adding a 200-300ms overhead to your authentication. You can solve for this by loading the services that need authentication within the same container (StdLib does this out of the box iirc)

like image 1
Nima Gardideh Avatar answered Nov 02 '22 15:11

Nima Gardideh