From bb80cdf5a6157ca1f3a276e12e9faae9a4739cb7 Mon Sep 17 00:00:00 2001
From: dh_ackergaul <dh_ackergaul@dh-software.de>
Date: Di, 23 Jun 2026 11:16:18 +0200
Subject: [PATCH] Update emvheya - 23.6.2026, 11:16:10 [JD]
---
manufacturer/_furnview/furnplan-web/api/services/OAuth2AuthenticationService.js | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 153 insertions(+), 0 deletions(-)
diff --git a/manufacturer/_furnview/furnplan-web/api/services/OAuth2AuthenticationService.js b/manufacturer/_furnview/furnplan-web/api/services/OAuth2AuthenticationService.js
new file mode 100644
index 0000000..e328e21
--- /dev/null
+++ b/manufacturer/_furnview/furnplan-web/api/services/OAuth2AuthenticationService.js
@@ -0,0 +1,153 @@
+const uuid = require("node-uuid").v4;
+
+const { BaseAuthenticationService } = require("./BaseAuthenticationService");
+
+module.exports.OAuth2AuthenticationService = class extends BaseAuthenticationService {
+ constructor() {
+ super();
+
+ this.discover();
+ }
+
+ async discover() {
+ try {
+ this.openId = await import("@dh-software/opus-x-openid-client-helper");
+
+ this.config = await this.openId.getConfig(sails.config.oauth, true);
+
+ console.log(`Discovered OAuth Service: ${this.config.serverMetadata().issuer}`);
+ }
+ catch (error) {
+ console.error(`Unable to discover OAuth Server at ${sails.config.oauth.issuer}. Retrying...`, error);
+
+ this.config = undefined;
+
+ setTimeout(() => this.discover(), 3000);
+ }
+ }
+
+ async login(req, res) {
+ try {
+ const { codeVerifier, state, url } = await this.openId.getAuthenticationAttempt(this.config, sails.config.oauth.redirectUri);
+
+ req.auth_cookie.auth = {
+ codeVerifier,
+ state,
+ originalUrl: req.query.oriReq || "/"
+ };
+
+ return res.redirect(url.href);
+ }
+ catch (e) {
+ Winston.error("OAuth login initiation failed:", e);
+
+ return res.serverError();
+ }
+ }
+
+ async logout(req, res) {
+ try {
+ const uri = await this.openId.buildLogoutURL(this.config, sails.config.oauth.postLogoutRedirectURIs[0], req.user.get("oauth.idToken"));
+
+ return res.json({ url: uri.toString() });
+ }
+ catch (error) {
+ console.error("Unable to logout:", error);
+
+ return res.serverError();
+ }
+ }
+
+ async callback (req, res) {
+ const oauthSession = req.auth_cookie.auth;
+
+ if (!oauthSession || req.query.state !== oauthSession.state) {
+ Winston.warn("OAuth callback state mismatch or missing session");
+ return res.redirect("/auth/login");
+ }
+
+ try {
+ const callbackUrl = new URL(
+ req.url,
+ sails.config.oauth.redirectUri
+ );
+
+ const { userInfo, tokenSet } = await this.openId.callback(this.config, oauthSession.codeVerifier, oauthSession.state, callbackUrl);
+
+ if (!userInfo.sub || !userInfo.customer_no) {
+ console.error("OAuth callback missing required userInfo 'sub' or 'customer_no':", userInfo);
+
+ delete req.auth_cookie.auth;
+
+ return res.redirect("/auth/login");
+ }
+
+ const opusSessionId = uuid();
+
+ const user = {
+ _id: opusSessionId,
+ permissions: ["anonymous", "basic", "dhp"],
+ canLogout: true,
+ isOpusUser: true,
+ canSeeEverything: false,
+ customerNo: userInfo.customer_no,
+ username: userInfo.username,
+ opusSessionId: opusSessionId,
+ data: {},
+ oauth: {
+ idToken: tokenSet.id_token,
+ userInfo: userInfo,
+ }
+ };
+
+ const configuration = await UseCaseConfiguration.findOne({
+ customerNo: user.customerNo,
+ externalConf: true
+ });
+
+ if (configuration) user.data.config = configuration.id;
+
+ await Session.update({ _id: req.session._id }, { $addToSet: { users: user } });
+
+ console.log("OAuth login granted for subject:", userInfo.sub, "username:", userInfo.username, "customerNo:", userInfo.customer_no);
+
+ const redirectTo = new URL("http://" + req.headers["host"] + req.auth_cookie.auth.originalUrl);
+
+ redirectTo.searchParams.set("session", user.opusSessionId);
+
+ return res.redirect(redirectTo.toString());
+ }
+ catch (e) {
+ console.error("OAuth login callback failed: ", e);
+
+ return res.redirect("/auth/login");
+ }
+ finally {
+ delete req.auth_cookie.auth;
+ }
+ }
+
+ async backchannelLogout (req, res) {
+ try {
+ const claims = await this.openId.validateLogoutToken(this.config, req.body.logout_token);
+ const session = await Session.findOne({ "users.oauth.userInfo.sub": claims.sub });
+ const user = session.users.find((user) => user?.get("oauth")?.userInfo?.sub === claims.sub);
+
+ const { userInfo } = user.get("oauth");
+
+ await Session.update({ _id: session._id }, { $pull: { users: { "oauth.userInfo.sub": claims.sub } } });
+
+ if (req.session) {
+ // delete temporary session which was created as a fallback (config/http.js) when the OAuth server called the logout callback
+ await Session.deleteOne({ _id: req.session._id });
+ }
+
+ console.log("OAuth logout granted for subject:", userInfo.sub, "username:", userInfo.username, "customerNo:", userInfo.customer_no);
+ }
+ catch (error) {
+ console.warn("Unable to single sign off:", error);
+ }
+
+ return res.send("ok");
+ }
+};
--
Gitblit v1.9.3