Does any one success add express middleware in theia?

I’m building a web app for multy users with one or more theia-backend behind reverse proxy.
The use case is that user open theia app from web app A, before thiea app loads in browser, I want to intercept the request and make some authentication.I searched the community as well as github, find that BackendApplicationContribution provide hook to acheive this.
When I add my own middleware, the browser apps goes to 404.
Below is my code

import {BackendApplicationContribution} from "@theia/core/lib/node";
import {MaybePromise} from "@theia/core";
import express = require('express');
import {injectable} from "inversify";

@injectable()
export class ThiauuobaAuthContribution implements BackendApplicationContribution {

    configure(app: express.Application): MaybePromise<void> {
        console.log("ThiauuobaAuthContribution.configure");
        const middleware = this.expressMiddleware.bind(this);
        app.use(middleware);
        console.log("after app.use")
        const routerStack = app._router.stack as any[];
        const layer = routerStack.splice(routerStack.findIndex(r => r.handler === middleware), 1);
        routerStack.splice(routerStack.findIndex(r => r.name === "expressInit") + 1, 0, ...layer);
    }

    protected expressMiddleware(req: express.Request, res: express.Response, next: express.NextFunction): void {
        console.log("ThiauuobaAuthContribution.expressMiddleware");
        if (this.validateToken()) {
            next()
        } else {
            console.log("ThiauuobaAuthContribution.expressMiddleware: invalid token");
            res.sendStatus(403);
        }
    }

    validateToken(): boolean {
        return true;
    }
}

I see https://github.com/eclipse-theia/theia/blob/master/packages/core/src/electron-node/token/electron-token-backend-contribution.ts use this hook, but my apps failed on this.
I also read this and this and this, none of them work.
Anyone helps? Thanks.

Hi,

I’ve done something similar, and this worked for me (I simplified the code):

async configure(app: Application): Promise<void> {
  // Checks that the request has a valid access token
  // to access a secured path
  app.use(this.handleSecuredPaths);
  
  // This moves the middleware above to the sweet spot in the stack
  // where it can validate all the secured paths
  const stack = app._router.stack as any[];
  const item = stack.splice(stack.length - 1, 1)[0];
  stack.splice(4, 0, item);

  // register a bunch of paths to handle oauth
}

handleSecuredPaths = async (req: Request, res: Response, next: NextFunction) => {
  // check req has valid access token
  if(valid) {
   next();
  }
  else {
   res.redirect(loginUrl);
   return next("router");
  }
}

I also bind a WsRequestValidatorContribution to allow the web socket upgrade and connection.

Hope it helps!

Hi, Hanksha
Appriciate for your reply, it helps.
My middleware works now, the root cause is that the contribition is not bind correctly.

    bind(ThiauuobaAuthContribution).toSelf().inSingletonScope();
    rebinbind(BackendApplicationContribution).toService(ThiauuobaAuthContribution);

Change the last line rebind to bind just fix this.

1 Like