From 3464fa9814a637c6af2bb0df06679f68dd144b4d Mon Sep 17 00:00:00 2001 From: Elia Zammuto Date: Sun, 10 Mar 2024 22:04:24 +0100 Subject: [PATCH 1/9] First Working Draft of JWT Login System --- .gitmodules | 3 + cmake/compile_definitions/common.cmake | 1 + src/confighttp.cpp | 128 +++++++++++++++--- src_assets/common/assets/web/LoginForm.vue | 61 +++++++++ src_assets/common/assets/web/Navbar.vue | 55 +++++++- src_assets/common/assets/web/apps.html | 1 + src_assets/common/assets/web/config.html | 1 + src_assets/common/assets/web/fetch.js | 9 ++ src_assets/common/assets/web/index.html | 1 + src_assets/common/assets/web/login.html | 52 +++++++ src_assets/common/assets/web/password.html | 1 + src_assets/common/assets/web/pin.html | 1 + .../common/assets/web/troubleshooting.html | 1 + src_assets/common/assets/web/welcome.html | 1 + third-party/jwt-cpp | 1 + vite.config.js | 1 + 16 files changed, 299 insertions(+), 19 deletions(-) create mode 100644 src_assets/common/assets/web/LoginForm.vue create mode 100644 src_assets/common/assets/web/fetch.js create mode 100644 src_assets/common/assets/web/login.html create mode 160000 third-party/jwt-cpp diff --git a/.gitmodules b/.gitmodules index 88198314dd0..6363904df51 100644 --- a/.gitmodules +++ b/.gitmodules @@ -58,3 +58,6 @@ path = third-party/wlr-protocols url = https://gitlab.freedesktop.org/wlroots/wlr-protocols.git branch = master +[submodule "third-party/jwt-cpp"] + path = third-party/jwt-cpp + url = https://github.com/Thalhammer/jwt-cpp.git diff --git a/cmake/compile_definitions/common.cmake b/cmake/compile_definitions/common.cmake index a2260595c9a..fa03e984009 100644 --- a/cmake/compile_definitions/common.cmake +++ b/cmake/compile_definitions/common.cmake @@ -132,6 +132,7 @@ include_directories( "${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/enet/include" "${CMAKE_SOURCE_DIR}/third-party/nanors" "${CMAKE_SOURCE_DIR}/third-party/nanors/deps/obl" + "${CMAKE_SOURCE_DIR}/third-party/jwt-cpp/include" ${FFMPEG_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} # has to be the last, or we get runtime error on macOS ffmpeg encoder ) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 6d80220612c..0d6358e7bf1 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -31,6 +31,7 @@ #include "file_handler.h" #include "globals.h" #include "httpcommon.h" +#include "jwt-cpp/jwt.h" #include "logging.h" #include "network.h" #include "nvhttp.h" @@ -45,6 +46,8 @@ using namespace std::literals; namespace confighttp { namespace fs = std::filesystem; namespace pt = boost::property_tree; + + std::string jwt_key; using https_server_t = SimpleWeb::Server; @@ -63,7 +66,7 @@ namespace confighttp { BOOST_LOG(debug) << "DESTINATION :: "sv << request->path; for (auto &[name, val] : request->header) { - BOOST_LOG(debug) << name << " -- " << (name == "Authorization" ? "CREDENTIALS REDACTED" : val); + BOOST_LOG(debug) << name << " -- " << (name == "Cookie" ? "COOKIES REDACTED" : val); } BOOST_LOG(debug) << " [--] "sv; @@ -79,9 +82,7 @@ namespace confighttp { send_unauthorized(resp_https_t response, req_https_t request) { auto address = net::addr_to_normalized_string(request->remote_endpoint().address()); BOOST_LOG(info) << "Web UI: ["sv << address << "] -- not authorized"sv; - const SimpleWeb::CaseInsensitiveMultimap headers { - { "WWW-Authenticate", R"(Basic realm="Sunshine Gamestream Host", charset="UTF-8")" } - }; + const SimpleWeb::CaseInsensitiveMultimap headers {}; response->write(SimpleWeb::StatusCode::client_error_unauthorized, headers); } @@ -113,29 +114,48 @@ namespace confighttp { } auto fg = util::fail_guard([&]() { - send_unauthorized(response, request); + BOOST_LOG(info) << request->path; + std::string apiPrefix = "/api"; + if (request->path.compare(0, apiPrefix.length(), apiPrefix) == 0) { + send_unauthorized(response, request); + } + else { + send_redirect(response, request, "/login"); + } }); - auto auth = request->header.find("authorization"); + auto auth = request->header.find("cookie"); if (auth == request->header.end()) { return false; } auto &rawAuth = auth->second; - auto authData = SimpleWeb::Crypto::Base64::decode(rawAuth.substr("Basic "sv.length())); - - int index = authData.find(':'); - if (index >= authData.size() - 1) { - return false; + std::istringstream iss(rawAuth); + std::string token, cookie_name = "sunshine_session=", cookie_value = ""; + + while (std::getline(iss, token, ';')) { + BOOST_LOG(info) << token; + // Left Trim Cookie + token.erase(token.begin(), std::find_if(token.begin(), token.end(), [](unsigned char ch) { + return !std::isspace(ch); + })); + // Compare that the cookie name is sunshine_session + if (token.compare(0, cookie_name.length(), cookie_name) == 0) { + cookie_value = token.substr(cookie_name.length()); + BOOST_LOG(info) << cookie_value; + break; + } } - auto username = authData.substr(0, index); - auto password = authData.substr(index + 1); - auto hash = util::hex(crypto::hash(password + config::sunshine.salt)).to_string(); + if (cookie_value.length() == 0) return false; + BOOST_LOG(info) << "JWT: " << cookie_value; + auto decoded = jwt::decode(cookie_value); + auto verifier = jwt::verify() + .with_issuer("sunshine-" + http::unique_id) + .with_claim("sub", jwt::claim(std::string(config::sunshine.username))) + .allow_algorithm(jwt::algorithm::hs256 { jwt_key }); - if (!boost::iequals(username, config::sunshine.username) || hash != config::sunshine.password) { - return false; - } + verifier.verify(decoded); fg.disable(); return true; @@ -182,6 +202,16 @@ namespace confighttp { response->write(content, headers); } + void + getLoginPage(resp_https_t response, req_https_t request) { + print_req(request); + + std::string content = file_handler::read_file(WEB_DIR "login.html"); + SimpleWeb::CaseInsensitiveMultimap headers; + headers.emplace("Content-Type", "text/html; charset=utf-8"); + response->write(content, headers); + } + void getAppsPage(resp_https_t response, req_https_t request) { if (!authenticate(response, request)) return; @@ -796,16 +826,79 @@ namespace confighttp { outputTree.put("status", true); } + void + login(resp_https_t response, req_https_t request) { + auto address = net::addr_to_normalized_string(request->remote_endpoint().address()); + auto ip_type = net::from_address(address); + + if (ip_type > http::origin_web_ui_allowed) { + BOOST_LOG(info) << "Web UI: ["sv << address << "] -- denied"sv; + response->write(SimpleWeb::StatusCode::client_error_forbidden); + return; + } + + std::stringstream ss; + ss << request->content.rdbuf(); + + pt::ptree inputTree, outputTree; + auto g = util::fail_guard([&]() { + std::ostringstream data; + + pt::write_json(data, outputTree); + response->write(data.str()); + }); + + try { + // TODO: Input Validation + pt::read_json(ss, inputTree); + auto username = inputTree.get("username"); + auto password = inputTree.get("password"); + auto hash = util::hex(crypto::hash(password + config::sunshine.salt)).to_string(); + + if (!boost::iequals(username, config::sunshine.username) || hash != config::sunshine.password) { + outputTree.put("status", "false"); + return; + } + outputTree.put("status", "true"); + auto token = jwt::create().set_type("JWS").set_issued_now().set_expires_in(std::chrono::seconds { 3600 }).set_issuer("sunshine-" + http::unique_id).set_payload_claim("sub", jwt::claim(std::string(config::sunshine.username))).sign(jwt::algorithm::hs256 { jwt_key }); + std::stringstream cookie_stream; + cookie_stream << "sunshine_session="; + cookie_stream << token; + cookie_stream << "; Secure; HttpOnly; SameSite=Strict; Path=/"; + const SimpleWeb::CaseInsensitiveMultimap headers { + { "Set-Cookie", cookie_stream.str() } + }; + std::ostringstream data; + pt::write_json(data, outputTree); + response->write(SimpleWeb::StatusCode::success_ok, data.str(), headers); + g.disable(); + return; + } + catch (std::exception &e) { + BOOST_LOG(warning) << "SaveApp: "sv << e.what(); + + outputTree.put("status", "false"); + outputTree.put("error", "Invalid Input JSON"); + return; + } + + outputTree.put("status", "true"); + } + void start() { auto shutdown_event = mail::man->event(mail::shutdown); + //On each server start, create a randomized jwt_key + jwt_key = crypto::rand_alphabet(64); + auto port_https = net::map_port(PORT_HTTPS); auto address_family = net::af_from_enum_string(config::sunshine.address_family); https_server_t server { config::nvhttp.cert, config::nvhttp.pkey }; server.default_resource["GET"] = not_found; server.resource["^/$"]["GET"] = getIndexPage; + server.resource["^/login/?$"]["GET"] = getLoginPage; server.resource["^/pin/?$"]["GET"] = getPinPage; server.resource["^/apps/?$"]["GET"] = getAppsPage; server.resource["^/clients/?$"]["GET"] = getClientsPage; @@ -828,6 +921,7 @@ namespace confighttp { server.resource["^/api/clients/unpair$"]["POST"] = unpair; server.resource["^/api/apps/close$"]["POST"] = closeApp; server.resource["^/api/covers/upload$"]["POST"] = uploadCover; + server.resource["^/api/login$"]["POST"] = login; server.resource["^/images/sunshine.ico$"]["GET"] = getFaviconImage; server.resource["^/images/logo-sunshine-45.png$"]["GET"] = getSunshineLogoImage; server.resource["^/assets\\/.+$"]["GET"] = getNodeModules; diff --git a/src_assets/common/assets/web/LoginForm.vue b/src_assets/common/assets/web/LoginForm.vue new file mode 100644 index 00000000000..e1877580aa8 --- /dev/null +++ b/src_assets/common/assets/web/LoginForm.vue @@ -0,0 +1,61 @@ + + + diff --git a/src_assets/common/assets/web/Navbar.vue b/src_assets/common/assets/web/Navbar.vue index 838c630f45a..1eb174852ff 100644 --- a/src_assets/common/assets/web/Navbar.vue +++ b/src_assets/common/assets/web/Navbar.vue @@ -35,22 +35,73 @@ + + diff --git a/src_assets/common/assets/web/apps.html b/src_assets/common/assets/web/apps.html index 9a8c65d16ae..f4bdc3dfa7e 100644 --- a/src_assets/common/assets/web/apps.html +++ b/src_assets/common/assets/web/apps.html @@ -359,6 +359,7 @@

{{ $t('apps.env_vars_about') }}

import { initApp } from './init' import Navbar from './Navbar.vue' import { Dropdown } from 'bootstrap/dist/js/bootstrap' + import fetch from './fetch.js' const app = createApp({ components: { diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index 8386dbd3673..14d9f059e4c 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -107,6 +107,7 @@

{{ $t('config.configuration') }}

import AudioVideo from './configs/tabs/AudioVideo.vue' import ContainerEncoders from './configs/tabs/ContainerEncoders.vue' import {$tp, usePlatformI18n} from './platform-i18n' + import fetch from './fetch.js' const app = createApp({ components: { diff --git a/src_assets/common/assets/web/fetch.js b/src_assets/common/assets/web/fetch.js new file mode 100644 index 00000000000..9b4ed9cd811 --- /dev/null +++ b/src_assets/common/assets/web/fetch.js @@ -0,0 +1,9 @@ +export default async (url, config) => { + const response = await fetch(url, config); + console.log(response); + if (response.status === 401) { + const event = new Event("sunshine:session_expire"); + window.dispatchEvent(event); + } + return response; +}; \ No newline at end of file diff --git a/src_assets/common/assets/web/index.html b/src_assets/common/assets/web/index.html index 9eccf9e1eca..ce53949f4c2 100644 --- a/src_assets/common/assets/web/index.html +++ b/src_assets/common/assets/web/index.html @@ -79,6 +79,7 @@

{{githubVersion.release.name}}

import Navbar from './Navbar.vue' import ResourceCard from './ResourceCard.vue' import SunshineVersion from './sunshine_version' + import fetch from './fetch.js' console.log("Hello, Sunshine!") let app = createApp({ diff --git a/src_assets/common/assets/web/login.html b/src_assets/common/assets/web/login.html new file mode 100644 index 00000000000..efc828ed87d --- /dev/null +++ b/src_assets/common/assets/web/login.html @@ -0,0 +1,52 @@ + + + + + <%- header %> + + + +
+
+
+
+

+ + Welcome to Sunshine! +

+
+ + +
+
+
+ + + \ No newline at end of file diff --git a/src_assets/common/assets/web/password.html b/src_assets/common/assets/web/password.html index 639c82b7401..90dd6b766b6 100644 --- a/src_assets/common/assets/web/password.html +++ b/src_assets/common/assets/web/password.html @@ -69,6 +69,7 @@

{{ $t('password.new_creds') }}

import { createApp } from 'vue' import { initApp } from './init' import Navbar from './Navbar.vue' + import fetch from './fetch.js' const app = createApp({ components: { diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index d8ce1da5496..f06a6b67323 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -27,6 +27,7 @@

{{ $t('pin.pin_pairing') }}

import { createApp } from 'vue' import { initApp } from './init' import Navbar from './Navbar.vue' + import fetch from './fetch.js' let app = createApp({ components: { diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 2a41666054a..16a2c116c85 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -131,6 +131,7 @@

{{ $t('troubleshooting.logs') }}

import { createApp } from 'vue' import { initApp } from './init' import Navbar from './Navbar.vue' + import fetch from './fetch.js' const app = createApp({ components: { diff --git a/src_assets/common/assets/web/welcome.html b/src_assets/common/assets/web/welcome.html index 18c67b2ee79..281533a4a19 100644 --- a/src_assets/common/assets/web/welcome.html +++ b/src_assets/common/assets/web/welcome.html @@ -55,6 +55,7 @@

import { createApp } from "vue" import ResourceCard from './ResourceCard.vue' import { initApp } from './init' + import fetch from './fetch.js' let app = createApp({ components: { diff --git a/third-party/jwt-cpp b/third-party/jwt-cpp new file mode 160000 index 00000000000..364a5572f4b --- /dev/null +++ b/third-party/jwt-cpp @@ -0,0 +1 @@ +Subproject commit 364a5572f4b46bb9f4304cb1c92acec8ddb2c620 diff --git a/vite.config.js b/vite.config.js index 8732f1a08c7..2f55ec99833 100644 --- a/vite.config.js +++ b/vite.config.js @@ -47,6 +47,7 @@ export default defineConfig({ input: { apps: resolve(assetsSrcPath, 'apps.html'), config: resolve(assetsSrcPath, 'config.html'), + login: resolve(assetsSrcPath, 'login.html'), index: resolve(assetsSrcPath, 'index.html'), password: resolve(assetsSrcPath, 'password.html'), pin: resolve(assetsSrcPath, 'pin.html'), From 6936a0efdb19b020af72d23572cf17a2bdd38ffe Mon Sep 17 00:00:00 2001 From: Elia Zammuto Date: Wed, 13 Mar 2024 21:29:18 +0100 Subject: [PATCH 2/9] Logout --- src/confighttp.cpp | 48 +++++++++++++++++++++---- src_assets/common/assets/web/Navbar.vue | 10 ++++++ src_assets/common/assets/web/login.html | 8 +++-- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 0d6358e7bf1..88c7ca752fe 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -46,7 +46,7 @@ using namespace std::literals; namespace confighttp { namespace fs = std::filesystem; namespace pt = boost::property_tree; - + std::string jwt_key; using https_server_t = SimpleWeb::Server; @@ -66,7 +66,7 @@ namespace confighttp { BOOST_LOG(debug) << "DESTINATION :: "sv << request->path; for (auto &[name, val] : request->header) { - BOOST_LOG(debug) << name << " -- " << (name == "Cookie" ? "COOKIES REDACTED" : val); + BOOST_LOG(debug) << name << " -- " << (name == "Cookie" || name == "Authorization" ? "SENSIBLE HEADER REDACTED" : val); } BOOST_LOG(debug) << " [--] "sv; @@ -119,7 +119,8 @@ namespace confighttp { if (request->path.compare(0, apiPrefix.length(), apiPrefix) == 0) { send_unauthorized(response, request); } - else { + // Redirect to login, but only once + else if (request->path.compare("/login") != 0) { send_redirect(response, request, "/login"); } }); @@ -134,7 +135,6 @@ namespace confighttp { std::string token, cookie_name = "sunshine_session=", cookie_value = ""; while (std::getline(iss, token, ';')) { - BOOST_LOG(info) << token; // Left Trim Cookie token.erase(token.begin(), std::find_if(token.begin(), token.end(), [](unsigned char ch) { return !std::isspace(ch); @@ -142,13 +142,11 @@ namespace confighttp { // Compare that the cookie name is sunshine_session if (token.compare(0, cookie_name.length(), cookie_name) == 0) { cookie_value = token.substr(cookie_name.length()); - BOOST_LOG(info) << cookie_value; break; } } if (cookie_value.length() == 0) return false; - BOOST_LOG(info) << "JWT: " << cookie_value; auto decoded = jwt::decode(cookie_value); auto verifier = jwt::verify() .with_issuer("sunshine-" + http::unique_id) @@ -688,6 +686,8 @@ namespace confighttp { else { http::save_user_creds(config::sunshine.credentials_file, newUsername, newPassword); http::reload_user_creds(config::sunshine.credentials_file); + // Regen the JWT Key to invalidate sessions + jwt_key = crypto::rand_alphabet(64); outputTree.put("status", true); } } @@ -885,11 +885,44 @@ namespace confighttp { outputTree.put("status", "true"); } + void + logout(resp_https_t response, req_https_t request) { + pt::ptree outputTree; + try { + if (!authenticate(response, request)) return; + + print_req(request); + + auto g = util::fail_guard([&]() { + std::ostringstream data; + pt::write_json(data, outputTree); + response->write(data.str()); + }); + + const SimpleWeb::CaseInsensitiveMultimap headers { + { "Set-Cookie", "sunshine_session=redacted; expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly; SameSite=Strict; Path=/" } + }; + std::ostringstream data; + outputTree.put("status", true); + pt::write_json(data, outputTree); + + response->write(SimpleWeb::StatusCode::success_ok, data.str(), headers); + g.disable(); + } + catch (std::exception &e) { + BOOST_LOG(warning) << "SaveApp: "sv << e.what(); + + outputTree.put("status", "false"); + outputTree.put("error", "Invalid Input JSON"); + return; + } + } + void start() { auto shutdown_event = mail::man->event(mail::shutdown); - //On each server start, create a randomized jwt_key + // On each server start, create a randomized jwt_key jwt_key = crypto::rand_alphabet(64); auto port_https = net::map_port(PORT_HTTPS); @@ -921,6 +954,7 @@ namespace confighttp { server.resource["^/api/clients/unpair$"]["POST"] = unpair; server.resource["^/api/apps/close$"]["POST"] = closeApp; server.resource["^/api/covers/upload$"]["POST"] = uploadCover; + server.resource["^/api/logout$"]["POST"] = logout; server.resource["^/api/login$"]["POST"] = login; server.resource["^/images/sunshine.ico$"]["GET"] = getFaviconImage; server.resource["^/images/logo-sunshine-45.png$"]["GET"] = getSunshineLogoImage; diff --git a/src_assets/common/assets/web/Navbar.vue b/src_assets/common/assets/web/Navbar.vue index 1eb174852ff..49541bffc7b 100644 --- a/src_assets/common/assets/web/Navbar.vue +++ b/src_assets/common/assets/web/Navbar.vue @@ -32,6 +32,11 @@ + @@ -102,6 +107,11 @@ export default { onLogin(){ this.modal.toggle(); }, + logout() { + fetch("/api/logout", { method: "POST" }).then(r => { + document.location.href = '/'; + }) + } } } diff --git a/src_assets/common/assets/web/login.html b/src_assets/common/assets/web/login.html index efc828ed87d..cb401a6da24 100644 --- a/src_assets/common/assets/web/login.html +++ b/src_assets/common/assets/web/login.html @@ -8,14 +8,16 @@
-
+
-

+

- Welcome to Sunshine! + Hello, Sunshine!

+
+
From 5a0881ad4b3fe3eceb60057bb8a07ab39a762558 Mon Sep 17 00:00:00 2001 From: Elia Zammuto Date: Sat, 16 Mar 2024 15:02:26 +0100 Subject: [PATCH 3/9] Migrated jwt-cpp to stable release, style fixes --- .gitmodules | 7 ++++--- src/confighttp.cpp | 9 +++++++-- src_assets/common/assets/web/fetch.js | 2 +- src_assets/common/assets/web/login.html | 10 +--------- third-party/jwt-cpp | 2 +- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/.gitmodules b/.gitmodules index 6363904df51..3386d5068ca 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,6 +18,10 @@ path = third-party/inputtino url = https://github.com/games-on-whales/inputtino.git branch = stable +[submodule "third-party/jwt-cpp"] + path = third-party/jwt-cpp + url = https://github.com/Thalhammer/jwt-cpp.git + branch = master [submodule "third-party/moonlight-common-c"] path = third-party/moonlight-common-c url = https://github.com/moonlight-stream/moonlight-common-c.git @@ -58,6 +62,3 @@ path = third-party/wlr-protocols url = https://gitlab.freedesktop.org/wlroots/wlr-protocols.git branch = master -[submodule "third-party/jwt-cpp"] - path = third-party/jwt-cpp - url = https://github.com/Thalhammer/jwt-cpp.git diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 88c7ca752fe..23fb145f379 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "config.h" #include "confighttp.h" @@ -31,7 +32,6 @@ #include "file_handler.h" #include "globals.h" #include "httpcommon.h" -#include "jwt-cpp/jwt.h" #include "logging.h" #include "network.h" #include "nvhttp.h" @@ -860,7 +860,12 @@ namespace confighttp { return; } outputTree.put("status", "true"); - auto token = jwt::create().set_type("JWS").set_issued_now().set_expires_in(std::chrono::seconds { 3600 }).set_issuer("sunshine-" + http::unique_id).set_payload_claim("sub", jwt::claim(std::string(config::sunshine.username))).sign(jwt::algorithm::hs256 { jwt_key }); + auto token = jwt::create().set_type("JWT") + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600}) + .set_issuer("sunshine-" + http::unique_id) + .set_payload_claim("sub", jwt::claim(std::string(config::sunshine.username))) + .sign(jwt::algorithm::hs256 { jwt_key }); std::stringstream cookie_stream; cookie_stream << "sunshine_session="; cookie_stream << token; diff --git a/src_assets/common/assets/web/fetch.js b/src_assets/common/assets/web/fetch.js index 9b4ed9cd811..349bcf887ee 100644 --- a/src_assets/common/assets/web/fetch.js +++ b/src_assets/common/assets/web/fetch.js @@ -6,4 +6,4 @@ export default async (url, config) => { window.dispatchEvent(event); } return response; -}; \ No newline at end of file +}; diff --git a/src_assets/common/assets/web/login.html b/src_assets/common/assets/web/login.html index cb401a6da24..a5a0a6b1d93 100644 --- a/src_assets/common/assets/web/login.html +++ b/src_assets/common/assets/web/login.html @@ -35,14 +35,6 @@

'ResourceCard': ResourceCard, 'LoginForm': LoginForm }, - data() { - return { - a: 1 - } - }, - mounted() { - console.log("Ciao!", this.$el) - }, methods: { onLogin() { document.location.href = '/'; @@ -51,4 +43,4 @@

}); initApp(app); - \ No newline at end of file + diff --git a/third-party/jwt-cpp b/third-party/jwt-cpp index 364a5572f4b..08bcf77a687 160000 --- a/third-party/jwt-cpp +++ b/third-party/jwt-cpp @@ -1 +1 @@ -Subproject commit 364a5572f4b46bb9f4304cb1c92acec8ddb2c620 +Subproject commit 08bcf77a687fb06e34138e9e9fa12a4ecbe12332 From 151364705cc98a77a345827b317f8634c1536dff Mon Sep 17 00:00:00 2001 From: Elia Zammuto Date: Sat, 16 Mar 2024 15:08:50 +0100 Subject: [PATCH 4/9] Made C++ format Happy --- src/confighttp.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 23fb145f379..a0b81db5c7c 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -860,12 +860,7 @@ namespace confighttp { return; } outputTree.put("status", "true"); - auto token = jwt::create().set_type("JWT") - .set_issued_at(std::chrono::system_clock::now()) - .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600}) - .set_issuer("sunshine-" + http::unique_id) - .set_payload_claim("sub", jwt::claim(std::string(config::sunshine.username))) - .sign(jwt::algorithm::hs256 { jwt_key }); + auto token = jwt::create().set_type("JWT").set_issued_at(std::chrono::system_clock::now()).set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds { 3600 }).set_issuer("sunshine-" + http::unique_id).set_payload_claim("sub", jwt::claim(std::string(config::sunshine.username))).sign(jwt::algorithm::hs256 { jwt_key }); std::stringstream cookie_stream; cookie_stream << "sunshine_session="; cookie_stream << token; From 5a83c2281844a4c51f43b0e2a1c12d2796f4a77b Mon Sep 17 00:00:00 2001 From: Vithorio Polten Date: Fri, 9 Aug 2024 03:58:28 -0300 Subject: [PATCH 5/9] fix(ui): theme and navbar behavior --- src_assets/common/assets/web/Navbar.vue | 13 +++++++++++-- src_assets/common/assets/web/login.html | 13 ++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src_assets/common/assets/web/Navbar.vue b/src_assets/common/assets/web/Navbar.vue index 49541bffc7b..7c47093fd21 100644 --- a/src_assets/common/assets/web/Navbar.vue +++ b/src_assets/common/assets/web/Navbar.vue @@ -32,7 +32,7 @@ -