Add oauth2_proxy and use for calibre

oauth2_proxy is a service that allows adding authentication via proxy
headers to arbitrary web applications. As calibre doesn't support OIDC
directly, we can configure oauth2_proxy with nginx to lock users out of
calibre until they authenticate with keycloak, and then provide the
username to calibre to authenticate without a password

Change-Id: I933a6df20143ac2bd25513a4bcd2817cf6228191
Reviewed-on: https://git.clicks.codes/c/Clicks/NixFiles/+/203
Tested-by: Skyler Grey <minion@clicks.codes>
Reviewed-by: Samuel Shuert <coded@clicks.codes>
diff --git a/modules/common/calibre.nix b/modules/common/calibre.nix
index c11d0a8..88df2c2 100644
--- a/modules/common/calibre.nix
+++ b/modules/common/calibre.nix
@@ -29,9 +29,9 @@
       calibreLibrary = "${config.services.nextcloud.datadir}/data/clicks-services/files/calibre";
 
       reverseProxyAuth = {
-        enable = false;
-        header = "keycloak_oidc";
-      }; # TODO: setup keycloak auth with oauth2_proxy
+        enable = true;
+        header = "X-User";
+      };
     };
   };
 }
\ No newline at end of file
diff --git a/modules/common/oauth2_proxy.nix b/modules/common/oauth2_proxy.nix
new file mode 100644
index 0000000..17d9cd0
--- /dev/null
+++ b/modules/common/oauth2_proxy.nix
@@ -0,0 +1,44 @@
+{config, ...}: {
+
+  sops.secrets.OAUTH2_PROXY_CLIENT_SECRET = {
+    mode = "0400";
+    owner = config.users.users.root.name;
+    group = config.users.users.root.group;
+    sopsFile = ../../secrets/oauth2_proxy.env.bin;
+    format = "binary";
+  };
+
+  services.oauth2_proxy = {
+    enable = true;
+
+    keyFile = config.sops.secrets.OAUTH2_PROXY_CLIENT_SECRET.path;
+
+    httpAddress = "http://127.0.0.255:1034";
+    nginx.virtualHosts = [ "calibre.coded.codes" ];
+    reverseProxy = true;
+
+    provider = "keycloak-oidc";
+    clientID = "oauth2_proxy";
+
+    setXauthrequest = true;
+
+    email.domains = [ "*" ];
+
+    extraConfig = {
+      oidc-issuer-url = "https://login.clicks.codes/realms/master";
+      code-challenge-method = "S256";
+      redis-connection-url = "unix://${config.services.redis.servers.oauth2_proxy.unixSocket}";
+      session-store-type = "redis";
+      cookie-csrf-per-request = "true";
+      cookie-secure = "true";
+      cookie-csrf-expire = "5m";
+      whitelist-domain = ".clicks.codes,.coded.codes,.thecoded.prof,.starrysky.fyi,.crawling.us";
+      skip-provider-button = "true";
+    };
+  };
+
+  services.redis.servers.oauth2_proxy = {
+    enable = true;
+    user = "oauth2_proxy";
+  };
+}