skip to Main Content

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://phpout.com/wp-content/uploads/2023/08/Eb5ad.png
[2]: https://phpout.com/wp-content/uploads/2023/08/M4sJ1.png

2

Answers


  1. Chosen as BEST ANSWER

    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
    

  2. To pass the User ID (UID) from an authentication service to another service using Nginx Ingress in Google Kubernetes Engine (GKE), you can follow these steps:

    Set Up Authentication Service:
    First, you need to have an authentication service in place. This could be something like Keycloak, OAuth2, or any other authentication mechanism that assigns a UID to users upon authentication.

    Deploy Your Services:
    Deploy the services that need to receive the UID and the authentication service itself in your GKE cluster.

    Configure Nginx Ingress:
    Set up an Nginx Ingress controller in your GKE cluster if you haven’t already. You can use Helm to simplify the installation process.

    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo update
    helm install my-ingress-controller ingress-nginx/ingress-nginx

    Ingress Resource Configuration:
    Create an Ingress resource to define how incoming traffic should be routed to your services. In the annotations section, you can set the necessary Nginx annotations to pass the UID.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: my-ingress
    annotations:
    nginx.ingress.kubernetes.io/auth-signin: https://your-auth-service-url/auth
    nginx.ingress.kubernetes.io/auth-response-headers: X-User-ID
    spec:
    rules:
    – host: your-domain.com
    http:
    paths:
    – path: /
    pathType: Prefix
    backend:
    service:
    name: your-service
    port:
    number: 80

    In this example:

    auth-signin specifies the URL where the authentication service is located.
    auth-response-headers tells Nginx Ingress to add a custom response header named X-User-ID.
    Service Updates:
    Update your services to read the X-User-ID header from the incoming requests and utilize it as needed.

    Testing:
    Deploy your Ingress resource and test the setup. When a user accesses your service through the Ingress, the Ingress controller will redirect them to the authentication service. After successful authentication, the UID will be included in the X-User-ID header of subsequent requests to your services.

    Remember to replace placeholders like your-auth-service-url, your-domain.com, your-service, etc., with your actual values.

    Please note that specific configurations might vary depending on your authentication service, your application architecture, and any security considerations you need to address. Always ensure that your authentication and authorization mechanisms are secure and well-tested.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search