matrix_coro.hpp (5875B)
1 #pragma once 2 #include "json.hpp" 3 #include "utils.hpp" 4 5 #include "cppcoro/task.hpp" 6 #include <cthash/sha2/sha256.hpp> 7 #include <spdlog/spdlog.h> 8 9 10 class BaseClient { 11 public: 12 std::string user_agent = "MatrixCoro SDK/0.1.0"; 13 }; 14 15 class LoggedInClient : public BaseClient { 16 TokenResponse token_data; 17 WellKnownResponse well_known; 18 19 [[nodiscard]] cppcoro::task<Json::Value> get(const std::string &url) const; 20 21 public: 22 LoggedInClient(TokenResponse token_data, WellKnownResponse well_known): token_data(std::move(token_data)), 23 well_known(std::move(well_known)) { 24 } 25 26 [[nodiscard]] cppcoro::task<WhoamiResponse> whoami() const; 27 }; 28 29 class Client : public BaseClient { 30 friend class ClientTest; // Declare the test class as a friend 31 32 public: 33 [[nodiscard]] cppcoro::task<std::string> get_auth_url(std::string homeserver, std::string redirect_url, 34 std::string state, std::string code_verifier, 35 const ClientRegistrationData ®istration_data); 36 37 [[nodiscard]] cppcoro::task<LoggedInClient> exchange_token(const std::string &code, 38 const std::string &redirect_url) const; 39 40 private: 41 WellKnownResponse well_known; 42 AuthIssuerResponse auth_issuer; 43 ClientRegistrationResponse client_registration; 44 OpenIDConfiguration openid_configuration; 45 std::string state; 46 std::string code_verifier; 47 48 [[nodiscard]] cppcoro::task<Json::Value> get(const std::string &url) const; 49 50 [[nodiscard]] cppcoro::task<Json::Value> post(const std::string &url, const std::string &data, 51 bool form_data = false) const; 52 53 /** 54 * \brief Fetches the well-known configuration from the specified homeserver. 55 * 56 * This function sends a request to the given homeserver to retrieve the well-known configuration. 57 * 58 * \param homeserver The URL of the homeserver from which to fetch the well-known configuration. 59 * \return A cppcoro::task that resolves to a WellKnownResponse containing the well-known configuration. 60 */ 61 [[nodiscard]] cppcoro::task<WellKnownResponse> fetch_wellknown(std::string homeserver); 62 63 /** 64 * \brief Fetches the authentication issuer information from the specified client-server endpoint. 65 * 66 * This function sends a request to the given client-server endpoint to retrieve the authentication issuer information. 67 * 68 * \param cs_endpoint The URL of the client-server endpoint from which to fetch the authentication issuer information. 69 * \return A cppcoro::task that resolves to an AuthIssuerResponse containing the authentication issuer information. 70 */ 71 [[nodiscard]] cppcoro::task<AuthIssuerResponse> fetch_auth_issuer(std::string cs_endpoint); 72 73 /** 74 * \brief Registers a client with the specified authentication endpoint (MSC2966). 75 * 76 * This function sends a registration request to the given authentication endpoint using the provided registration data. 77 * It allows the client to be registered as an OAuth2 client on the OIDC server side, enabling the client to let people log in. 78 * 79 * \param registration_endpoint The URL of the registration endpoint to register the client which can be optained from the openid-configuration. 80 * \param registration_data The data required for client registration. 81 * \return A cppcoro::task that resolves to a ClientRegistrationResponse containing the registration result. 82 */ 83 [[nodiscard]] cppcoro::task<ClientRegistrationResponse> register_client(std::string registration_endpoint, 84 const ClientRegistrationData & 85 registration_data); 86 87 88 // ReSharper disable once CppMemberFunctionMayBeStatic 89 // NOLINTNEXTLINE(*-convert-member-functions-to-static) 90 [[nodiscard]] constexpr std::string generate_authorize_url(const std::string &auth_endpoint, 91 const ClientRegistrationResponse &auth_data, 92 const std::string &redirect_url, 93 const std::string &state, 94 const std::string &code_verifier) const { 95 spdlog::debug("Code verifier: {}", code_verifier); 96 // URL encode the redirect URL 97 const auto url_encoded_redirect_url = url_encode(redirect_url); 98 99 // Calculate the code challenge from the code_verifier by doing `BASE64URL(SHA256(code_verifier))` 100 const auto sha256_code_verifier = cthash::simple<cthash::sha256>(code_verifier); 101 const auto code_challenge = cthash::base64url_encode(sha256_code_verifier).to_string(); 102 103 return auth_endpoint + "?response_type=code&response_mode=fragment&client_id=" + 104 auth_data.client_id + "&redirect_uri=" + url_encoded_redirect_url + 105 "&scope=urn%3Amatrix%3Aorg.matrix.msc2967.client%3Aapi%3A*%20urn%3Amatrix%3Aorg.matrix.msc2967.client%3Adevice%3AABCDEFGHIJKL&state=" 106 + state + "&code_challenge_method=S256" + "&code_challenge=" + code_challenge; 107 } 108 109 [[nodiscard]] cppcoro::task<TokenResponse> exchange_code_for_token( 110 std::string token_endpoint, 111 const std::string &code, 112 const std::string &code_verifier, 113 const std::string &client_id, 114 const std::string &redirect_url) const; 115 116 [[nodiscard]] cppcoro::task<OpenIDConfiguration> fetch_openid_configuration( 117 std::string auth_endpoint); 118 };