91eb5afd0b
Note: For GCC there are still a huge number of `-Warray-bounds` warnings coming from `externals/dynarmic`. I could have added a workaround in `externals/CMakeLists.txt` similar to what this PR does for other externals, but given Dynarmic's close affiliation with Yuzu, it would be better to fix it upstream. Besides that, on my machine, this makes the build warning-free except for some warnings from glslangValidator and AutoMoc. Details: - Disable some warnings in externals. - Disable `-Wnullability-completeness`, which is a Clang warning triggered by the Vulkan SDK where if any pointers in the header are marked _Nullable, it wants all pointers to be marked _Nullable or _Nonnull. Most of them are, but some aren't. Who knows why. - `src/web_service/verify_user_jwt.cpp`: Disable another warning when including `jwt.hpp`. - `src/input_common/input_poller.cpp`: Add missing `override` specifiers. - src/common/swap.h: Remove redundant `operator&`. In general, this file declares three overloads of each operator. Using `+` as an example, the overloads are: - a member function for `swapped_t + integer` - a member function for `swapped_t + swapped_t` - a free function for `integer + swapped_t` But for `operator&`, there was an additional free function for `swapped_t + integer`, which was redundant with the member function. This caused a GCC warning saying "ISO C++ says that these are ambiguous".
70 lines
2.8 KiB
C++
70 lines
2.8 KiB
C++
// SPDX-FileCopyrightText: Copyright 2018 Citra Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // for deprecated OpenSSL functions
|
|
#endif
|
|
#include <jwt/jwt.hpp>
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
#include <system_error>
|
|
#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;
|
|
|
|
// We use the Citra backend so the issuer is citra-core
|
|
auto decoded =
|
|
jwt::decode(token, algorithms({"rs256"}), error, secret(pub_key), issuer("citra-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
|