FlowFuse / FlowFuse/node-red-dashboard

Infinite loop when express-openid-connect middleware is used

Open
#1,750 0 comments 0 reactions 0 assignees View on GitHub
needs-triage type:bug
Dominant language
HTML
Stars
355
Forks
82
Avg merge
4d 23h
Merged PRs (30d)
24

Description

### Current Behavior

When a custom middleware based on "express-openid-connect" is used during the time of the first session everything operates normally but once it expires and new one needs to be established an infinite loop is created. This is because "callback" route critical for this middleware is served by PWA's service worker from its cache instead of the middleware itself which needs to return a session in form of a cookie. A simple solution for this particular case is provided by below patch, more generic one could consist of configuration variable for excluded routes for example.

```diff
--- a/ui/src/sw.js
+++ b/ui/src/sw.js
@@ -22,6 +22,8 @@ if (import.meta.env.DEV) {
// this permits the request to be handled by the server which will do a redirect as required
const configPath = self.location.pathname.split('/')[1]
denylist.push(new RegExp(`/${configPath}/[^?]*/(\\?.*)*$`))
+ // don't precache the callback route which is handled by express-openid-connect middleware
+ denylist.push(new RegExp(`/${configPath}/callback\\?`))
}

// to allow work offline for allowed routes only
```

### Expected Behavior

_No response_

### Steps To Reproduce

1. Configure custom OIDC middleware in settings.js, example configuration used with Hashicorp Vault:
```javascript
dashboard: {
middleware: (req, res, next) => {
const issuerBaseURL = "";
const baseURL = "";
const clientID = "";
const clientSecret = "";
const secret = "";
const group ="";

// Workaround for double middleware call bug
if (req.hasOwnProperty("oidc") && req.oidc.isAuthenticated()) return next();
const { auth } = require("express-openid-connect");
const jose = require("jose");
const oidcAuth = auth({
issuerBaseURL: issuerBaseURL,
baseURL: baseURL,
clientID: clientID,
clientSecret: clientSecret,
secret: secret,
authorizationParams: {
response_type: "code",
scope: "openid security"
},
afterCallback: async (request, response, session) => {
const claims = jose.JWT.decode(session.id_token);
if (!(claims.hasOwnProperty("groups") && claims.groups.includes(group)))
return response.sendStatus(401);
return session;
}
});
oidcAuth(req, res, next);
}
}
```
2. Logon to the dashboard
3. Close browser tab and delete "appSession" cookie to simulate expired session
4. Try to logon to the dashboard again

### Environment

- Dashboard version: 1.24.2
- Node-RED version: 4.0.9
- Node.js version: 20.19.0
- npm version:
- Platform/OS: Linux 6.1.0-34-armmp arm LE
- Browser: Edge/Firefox

### Have you provided an initial effort estimate for this issue?

I am not a FlowFuse team member

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.