Search code examples
node.jskubernetesnginxgoogle-cloud-platformload-balancing

How to Pass UID for Auth service to Other service using Nginx Ingress in GKE


I am creating this architecture. [![Single ingress][1]][1]

SO in this I want to create an auth service which validates the Firebase token and gives the uid in return and then this uid need to be passed in my different micro services S1,S2 and so on.

But the issue is when I create a single ingress then I am getting "500 Internal Service error"

So I tried this architecture and "500 Internal Service error" is gone but I am not getting my uid. I am entering uid hardcoded for testing [![Two ingress][2]][2]

Here is the code: AUTH SERVICE

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

app.use(bodyParser.json());

app.post('/verify-id-token', (req, res) => {
  const hardcodedUid = 'my-hardcoded-uid'; // Replace with your desired UID

  // Add the UserID to the response header
  res.setHeader('UserID', hardcodedUid);
  return res.status(200).json({ message: 'Token verified' });
});

const PORT = 8080;
app.listen(PORT, () => {
  console.log(`Auth service is running on port ${PORT}`);
});

code: S1 SERVICE

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

app.use(bodyParser.json());

app.use((req, res, next) => {
  // Extract 'uid' header from the request
  const uid = req.header('uid');

  console.log('Received request from client with uid:', uid);

  // Set 'uid' as a custom header for micro-service1
  if (uid) {
    req.headers['uid'] = uid;
    console.log('Setting uid header for micro-service1:', uid);
  }

  next();
});

app.get('/', (req, res) => {
  // Access the 'uid' header, if present
  const uid = req.header('uid');

  console.log('Handling request in micro-service1 with uid:', uid);

  res.status(200).json({ message: `Hello from micro-service1 ${uid}`, uid });
});

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Micro-service1 is running on port ${PORT}`);
});

code: ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: service-ingress
  annotations:
    nginx.ingress.kubernetes.io/auth-method: POST
    nginx.ingress.kubernetes.io/auth-url: http://<LB-IP>/verify-id-token
    nginx.ingress.kubernetes.io/auth-response-headers: uid
spec:
  ingressClassName: nginx
  rules:
     - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: test-service1
                port:
                  number: 3000

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: token-ingress
  annotations:
    nginx.ingress.kubernetes.io/auth-response-headers: uid
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /verify-id-token
            pathType: Prefix
            backend:
              service:
                name: auth-service
                port:
                  number: 8080

Can someone please help to figure out whats wrong !!! [1]: https://i.sstatic.net/Eb5ad.png [2]: https://i.sstatic.net/M4sJ1.png


Solution

  • I find out what I was doing wrong.

    1. I have added annotation nginx.ingress.kubernetes.io/auth-url in both ingress resource.
    2. In my Auth Service I am setting the header with the key 'UserID' (res.setHeader('UserID', hardcodedUid);), but in your microservice, I am trying to read it with the key 'uid' (const uid = req.header('uid');). These names should match for the communication to work.

    Here is the correct code.

    Auth Service

    const express = require('express');
    const app = express();
    const bodyParser = require('body-parser');
    
    app.use(bodyParser.json());
    
    app.post('/verify-id-token', (req, res) => {
      // const uid = req.body.uid;
      const uid = 'my-hardcoded-uid-new'; // Replace with your desired UID
    
      if (uid) {
        res.setHeader('uid', uid); // Set the UID in the header
        return res.status(200).json({ message: `Token verified, uid is --> ${uid} `, uid });
      } else {
        return res.status(401).json({ message: 'Token invalid' });
      }
    });
    
    const PORT = 8080;
    app.listen(PORT, () => {
      console.log(`Auth service is running on port ${PORT}`);
    });
    

    S1 SERVICE

    const express = require('express');
    const app = express();
    const bodyParser = require('body-parser');
    
    app.use(bodyParser.json());
    
    app.use((req, res, next) => {
      // Extract 'uid' header from the request
      const uid = req.header('uid');
    
      console.log('Received request from client with uid:', uid);
    
      // Set 'uid' as a custom header for micro-service1
      if (uid) {
        req.headers['uid'] = uid;
        console.log('Setting uid header for micro-service1:', uid);
      }
    
      next();
    });
    
    app.get('/', (req, res) => {
      // Access the 'uid' header, if present
      const uid = req.header('uid');
    
      console.log('Handling request in micro-service1 with uid:', uid);
    
      res.status(200).json({ message: `Hello from micro-service1 ${uid}`, uid });
    });
    
    const PORT = 3000;
    app.listen(PORT, () => {
      console.log(`Micro-service1 is running on port ${PORT}`);
    });
    

    ingress.yaml

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: service-ingress
      annotations:
        nginx.ingress.kubernetes.io/auth-method: POST
        nginx.ingress.kubernetes.io/auth-url: http://<LB-IP>/verify-id-token
        nginx.ingress.kubernetes.io/auth-response-headers: uid
    spec:
      ingressClassName: nginx
      rules:
         - http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: test-service
                    port:
                      number: 3000
    
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: token-ingress
      annotations:
    spec:
      ingressClassName: nginx
      rules:
        - http:
            paths:
              - path: /verify-id-token
                pathType: Prefix
                backend:
                  service:
                    name: jwt-test
                    port:
                      number: 8080