From 8c96305b2c179b2f26b9b625621c725f7364f946 Mon Sep 17 00:00:00 2001
From: Dominik Hebeler <dominik@hebeler.club>
Date: Sun, 1 Jan 2023 21:42:12 +0100
Subject: [PATCH] finished oidc connect integration with keycloak

---
 pass/routes/authentication.js | 80 ++++++++++++++++++-----------------
 1 file changed, 41 insertions(+), 39 deletions(-)

diff --git a/pass/routes/authentication.js b/pass/routes/authentication.js
index e905945..7b24307 100644
--- a/pass/routes/authentication.js
+++ b/pass/routes/authentication.js
@@ -2,72 +2,74 @@ var express = require("express");
 var router = express.Router();
 const config = require("config");
 const jose = require("jose");
-const { auth, requiresAuth, Session } = require("express-openid-connect");
-const dayjs = require("dayjs");
+const { auth, requiresAuth, claimCheck } = require("express-openid-connect");
 
-const auth_session_expiration_minutes = 1;
-
-const access_keys_redis_key = "accesskeys";
+const auth_session_expiration_seconds = 60;
 
 /**
- * Authorization is done using Oauth2 via any GitLab Instance
+ * Authorization is done using Oauth2 via any Openid Provider
  * The Instance to be used can be configured in the config.
  *
- * The authenticated user needs to be member of the group defined in the config
- *
  * You can call any url with the parameter moderation=true to trigger a login with
  * redirect to the same URL after successfull authentication or 401 error on
  * failed authentication.
- *
- * Create an application in your Gitlab Instances Group with openid,profile,email permissions
- * and set the callback URL to this applications base url and the path /callback
- *
  */
 router.use(
+  // General Optional authorization for every page
+  // It will not require login or start a session by default
+  // Only when a route uses the middleware requireAuth
   auth({
     issuerBaseURL: `${config.get("app.openid_auth.url")}`,
     baseURL: config.get("app.url"),
     clientID: config.get("app.openid_auth.app_id"),
     clientSecret: config.get("app.openid_auth.app_secret"),
     secret: config.get("app.secret"),
-    idpLogout: true,
     session: {
-      absoluteDuration: 1,
-    },
-    afterCallback: (req, res, session, decodedState) => {
-      let access_token = session.access_token;
-      console.log(session);
-      return session;
+      rollingDuration: auth_session_expiration_seconds,
+      signSessionStoreCookie: true,
     },
     authRequired: false,
-    authorizationParams: {
-      response_type: "code",
-    },
   }),
+  /**
+   * If the user is already authenticated this middleware will check
+   * if the user inherits the required role in his oidc token to use this app
+   */
   (req, res, next) => {
-    if (req.query.moderation) {
-      requiresAuth()(req, res, next);
+    if (req.data === undefined) {
+      req.data = { admin: false };
     } else {
-      next("route");
+      req.data.admin = false;
+    }
+    if (req.oidc.isAuthenticated()) {
+      claimCheck((req, claims) => {
+        if (req.oidc.isAuthenticated()) {
+          if (
+            claims.resource_access !== undefined &&
+            claims.resource_access["metager-key"] !== undefined &&
+            claims.resource_access["metager-key"].roles !== undefined &&
+            claims.resource_access["metager-key"].roles.includes("metager-key")
+          ) {
+            req.data.admin = true;
+          }
+          return true;
+        }
+      })(req, res, next);
+    } else {
+      next();
     }
   },
+  // Require authorization for every route with moderation request parameter set
+  // Or when the user already is authenticated
   (req, res, next) => {
-    if (req.data) {
-      req.data.admin = false;
+    if (req.query.moderation || req.data.admin) {
+      requiresAuth()(req, res, next);
     } else {
-      req.data = {
-        admin: false,
-      };
-    }
-    if (Object.keys(req.appSession).length > 0) {
-      let claims = jose.decodeJwt(req.appSession.id_token);
-      if (
-        claims.groups_direct.includes(config.get("app.gitlab.required_group"))
-      ) {
-        req.data.admin = true;
-      }
+      next("route");
     }
-
+  },
+  // Redirect the user to the same URL without moderation URL Parameter after
+  // successful auth. Show him a 401 if he does not inherit required role
+  (req, res, next) => {
     if (req.query.moderation) {
       if (!req.data.admin) {
         res.locals.error = { status: 401 };
-- 
GitLab