vincent15000's avatar

How to share authentication with microservices with NodeJS ?

Hello,

I will soon work on an application made with several microservices and all data will be centralized in a single database.

Each microservice could be developed with its own technology (NodeJS, Laravel, ...), but it's probably better to keep NodeJS because a first version of a microservice is already developed with NodeJS.

Furthermore all microservices will be installed on a laptop a probably often accessed only from this laptop (rarely from other computers). In the future it will probably be installed on a Rasberry Pi. And there will be a unique frontend.

To give some examples, a microservice could be to handle books, another microservice to handle emails, ... for the moment, according to me, that's like if I had several micro Laravel applications instead of a unique one with several modules. All microservices are provided only locally (no externel web service).

To access a microservice, a user has to be authenticated.

So I need to create a new microservice (a new NodeJS application) to manage only the authentication, this authentication service will be available for all other microservices.

What could be the best approach to do that ?

I thought about generating a JWT token and then use this Bearer token accross all "backends".

Do you have any other suggestions for me ?

Thanks for your help.

V

0 likes
4 replies
LaryAI's avatar
Level 58

Hello V,

Your idea of using JWT (JSON Web Tokens) for authentication across your microservices is a solid approach and is commonly used in microservices architectures. Here's a high-level overview of how you can implement this:

  1. Authentication Service: Create a dedicated authentication service that is responsible for user registration, login, and token generation. When a user logs in, this service will authenticate the user credentials and issue a JWT if the credentials are valid.

  2. Token Signing: The JWT should be signed with a secret key or a private key (if using asymmetric encryption). This key must be kept secure and should be known only to the authentication service and other microservices that will validate the token.

  3. Token Verification: Each microservice that requires authentication should verify the incoming JWT. This can be done by implementing middleware that checks for the presence of the JWT in the Authorization header of incoming requests, decodes it, and verifies its signature.

  4. User Identification: The JWT typically contains a payload with user identification information (like user ID), which the microservices can use to identify the user and handle authorization if needed.

  5. Secure Communication: Ensure that all communication between services, especially those containing authentication tokens, is done over a secure channel (e.g., HTTPS).

Here's a simple example of how you might implement the authentication service in Node.js using the jsonwebtoken package:

const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');

const app = express();
const SECRET_KEY = 'your-secret-key'; // This should be a complex and secure key

app.use(bodyParser.json());

// Mock user database
const users = {
  '[email protected]': { password: 'password123', id: 1 }
};

app.post('/login', (req, res) => {
  const { email, password } = req.body;
  const user = users[email];

  if (user && user.password === password) {
    const token = jwt.sign({ userId: user.id }, SECRET_KEY, { expiresIn: '1h' });
    res.json({ token });
  } else {
    res.status(401).send('Credentials are invalid');
  }
});

app.listen(3000, () => {
  console.log('Authentication service running on port 3000');
});

And here's an example of a middleware function that could be used in other microservices to verify the token:

const jwt = require('jsonwebtoken');
const SECRET_KEY = 'your-secret-key'; // This should be the same key used to sign the JWT

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (token == null) return res.sendStatus(401);

  jwt.verify(token, SECRET_KEY, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
}

module.exports = authenticateToken;

You would then use this middleware in your microservices like so:

const express = require('express');
const authenticateToken = require('./authenticateToken');

const app = express();

app.get('/protected-route', authenticateToken, (req, res) => {
  // Access user information from req.user if needed
  res.json({ message: 'This is a protected route' });
});

app.listen(3001, () => {
  console.log('Microservice running on port 3001');
});

Remember to handle token expiration and possibly implement token refresh mechanisms. Also, consider the security implications of your setup, especially since you mentioned that the services will be accessed locally and potentially from a Raspberry Pi in the future.

I hope this helps you get started with your authentication service!

vincent15000's avatar
vincent15000
OP
Best Answer
Level 63

I have another idea.

Develop a Laravel application to use each microservice. So the Laravel backend could easily manage all authorizations to use each microservice.

What do you think about this ?

1 like
Elrayes's avatar

@vincent15000 hello would you kindly give me an explanation about how to do so? like i have 2 or more projects but i wanna make one for authentication as in identity login, register ..etc, and another project for subscription ..etc while each project has its own db? i don't think that sanctum or passport have this kind of auth right?

1 like
t0berius's avatar

@vincent15000 if interested I can share some details about how to decode the laravel session cookie. Using this in many projects where external applications decode the session cookie and get user details about currently signed in user.

1 like

Please or to participate in this conversation.