diff options
author | FearlessTobi <thm.frey@gmail.com> | 2022-07-15 19:45:35 +0200 |
---|---|---|
committer | FearlessTobi <thm.frey@gmail.com> | 2022-07-25 21:59:30 +0200 |
commit | 6c8e45618578de1406c0bf4a7f976bd4903c339c (patch) | |
tree | 25b959db6f30fe75bf5c6fa667ed92af71117986 /src/web_service | |
parent | ec407bd3f1988c6f5d147307c662703c7bc94751 (diff) |
Address first part of review comments
Diffstat (limited to 'src/web_service')
-rw-r--r-- | src/web_service/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/web_service/verify_user_jwt.cpp | 60 | ||||
-rw-r--r-- | src/web_service/verify_user_jwt.h | 25 |
3 files changed, 88 insertions, 1 deletions
diff --git a/src/web_service/CMakeLists.txt b/src/web_service/CMakeLists.txt index aff81f26d..753fb6e7a 100644 --- a/src/web_service/CMakeLists.txt +++ b/src/web_service/CMakeLists.txt @@ -5,10 +5,12 @@ add_library(web_service STATIC telemetry_json.h verify_login.cpp verify_login.h + verify_user_jwt.cpp + verify_user_jwt.h web_backend.cpp web_backend.h web_result.h ) create_target_directory_groups(web_service) -target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann_json httplib) +target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann_json httplib cpp-jwt) diff --git a/src/web_service/verify_user_jwt.cpp b/src/web_service/verify_user_jwt.cpp new file mode 100644 index 000000000..78fe7bed5 --- /dev/null +++ b/src/web_service/verify_user_jwt.cpp @@ -0,0 +1,60 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <system_error> +#include <jwt/jwt.hpp> +#include "common/logging/log.h" +#include "web_service/verify_user_jwt.h" +#include "web_service/web_backend.h" +#include "web_service/web_result.h" + +namespace WebService { + +static std::string public_key; +std::string GetPublicKey(const std::string& host) { + if (public_key.empty()) { + Client client(host, "", ""); // no need for credentials here + public_key = client.GetPlain("/jwt/external/key.pem", true).returned_data; + if (public_key.empty()) { + LOG_ERROR(WebService, "Could not fetch external JWT public key, verification may fail"); + } else { + LOG_INFO(WebService, "Fetched external JWT public key (size={})", public_key.size()); + } + } + return public_key; +} + +VerifyUserJWT::VerifyUserJWT(const std::string& host) : pub_key(GetPublicKey(host)) {} + +Network::VerifyUser::UserData VerifyUserJWT::LoadUserData(const std::string& verify_UID, + const std::string& token) { + const std::string audience = fmt::format("external-{}", verify_UID); + using namespace jwt::params; + std::error_code error; + auto decoded = + jwt::decode(token, algorithms({"rs256"}), error, secret(pub_key), issuer("yuzu-core"), + aud(audience), validate_iat(true), validate_jti(true)); + if (error) { + LOG_INFO(WebService, "Verification failed: category={}, code={}, message={}", + error.category().name(), error.value(), error.message()); + return {}; + } + Network::VerifyUser::UserData user_data{}; + if (decoded.payload().has_claim("username")) { + user_data.username = decoded.payload().get_claim_value<std::string>("username"); + } + if (decoded.payload().has_claim("displayName")) { + user_data.display_name = decoded.payload().get_claim_value<std::string>("displayName"); + } + if (decoded.payload().has_claim("avatarUrl")) { + user_data.avatar_url = decoded.payload().get_claim_value<std::string>("avatarUrl"); + } + if (decoded.payload().has_claim("roles")) { + auto roles = decoded.payload().get_claim_value<std::vector<std::string>>("roles"); + user_data.moderator = std::find(roles.begin(), roles.end(), "moderator") != roles.end(); + } + return user_data; +} + +} // namespace WebService diff --git a/src/web_service/verify_user_jwt.h b/src/web_service/verify_user_jwt.h new file mode 100644 index 000000000..826e01eed --- /dev/null +++ b/src/web_service/verify_user_jwt.h @@ -0,0 +1,25 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <fmt/format.h> +#include "network/verify_user.h" +#include "web_service/web_backend.h" + +namespace WebService { + +class VerifyUserJWT final : public Network::VerifyUser::Backend { +public: + VerifyUserJWT(const std::string& host); + ~VerifyUserJWT() = default; + + Network::VerifyUser::UserData LoadUserData(const std::string& verify_UID, + const std::string& token) override; + +private: + std::string pub_key; +}; + +} // namespace WebService |