From eefc7e5f3e490e2755b149e943bad51e6df44bbe Mon Sep 17 00:00:00 2001 From: Nicolas Werner <nicolas.werner@hotmail.de> Date: Sat, 9 May 2020 15:58:14 +0200 Subject: [PATCH] Add SSO endpoints --- include/mtx/responses/login.hpp | 17 +++++++++++++++++ include/mtx/user_interactive.hpp | 4 ++++ include/mtxclient/http/client.hpp | 7 +++++++ lib/http/client.cpp | 19 +++++++++++++++++++ lib/structs/responses/login.cpp | 11 +++++++++++ lib/structs/user_interactive.cpp | 1 + tests/client_api.cpp | 13 +++++++++++++ 7 files changed, 72 insertions(+) diff --git a/include/mtx/responses/login.hpp b/include/mtx/responses/login.hpp index b218f7b55..e38f30e9e 100644 --- a/include/mtx/responses/login.hpp +++ b/include/mtx/responses/login.hpp @@ -10,6 +10,7 @@ #endif #include "mtx/identifiers.hpp" +#include "mtx/user_interactive.hpp" #include "well-known.hpp" namespace mtx { @@ -35,5 +36,21 @@ struct Login void from_json(const nlohmann::json &obj, Login &response); + +struct LoginFlow +{ + mtx::user_interactive::AuthType type; +}; +void +from_json(const nlohmann::json &obj, LoginFlow &response); + +//! Response from the `GET /_matrix/client/r0/login` endpoint. +struct LoginFlows +{ + std::vector<LoginFlow> flows; +}; + +void +from_json(const nlohmann::json &obj, LoginFlows &response); } } diff --git a/include/mtx/user_interactive.hpp b/include/mtx/user_interactive.hpp index 7245a159b..fde1360d0 100644 --- a/include/mtx/user_interactive.hpp +++ b/include/mtx/user_interactive.hpp @@ -18,6 +18,7 @@ constexpr std::string_view oauth2 = "m.login.oauth2"; constexpr std::string_view email_identity = "m.login.email.identity"; constexpr std::string_view msisdn = "m.login.msisdn"; constexpr std::string_view token = "m.login.token"; +constexpr std::string_view sso = "m.login.sso"; // needed for /login at least constexpr std::string_view dummy = "m.login.dummy"; constexpr std::string_view terms = "m.login.terms"; // see MSC1692 } @@ -141,6 +142,8 @@ struct OAuth2 {}; struct Terms {}; +struct SSO +{}; struct Dummy {}; struct Fallback @@ -159,6 +162,7 @@ struct Auth auth::MSISDN, auth::OAuth2, auth::Terms, + auth::SSO, auth::Dummy, auth::Fallback> content; diff --git a/include/mtxclient/http/client.hpp b/include/mtxclient/http/client.hpp index 7df7b7873..5f02ee091 100644 --- a/include/mtxclient/http/client.hpp +++ b/include/mtxclient/http/client.hpp @@ -51,6 +51,7 @@ struct GroupProfile; struct JoinedGroups; struct KeyChanges; struct Login; +struct LoginFlows; struct Messages; struct Notifications; struct Profile; @@ -193,6 +194,12 @@ public: const std::string &device_name, Callback<mtx::responses::Login> cb); void login(const mtx::requests::Login &req, Callback<mtx::responses::Login> cb); + + //! Get the supported login flows + void get_login(Callback<mtx::responses::LoginFlows> cb); + //! Get url to navigate to for sso login flow + //! Open this in a browser + std::string login_sso_redirect(std::string redirectUrl); //! Lookup real server to connect to. //! Call set_server with the returned homeserver url after this void well_known(Callback<mtx::responses::WellKnown> cb); diff --git a/lib/http/client.cpp b/lib/http/client.cpp index 79547914e..9624e9282 100644 --- a/lib/http/client.cpp +++ b/lib/http/client.cpp @@ -291,6 +291,25 @@ Client::login(const mtx::requests::Login &req, Callback<mtx::responses::Login> c false); } +void +Client::get_login(Callback<mtx::responses::LoginFlows> cb) +{ + get<mtx::responses::LoginFlows>( + "/client/r0/login", + [cb](const mtx::responses::LoginFlows &res, HeaderFields, RequestErr err) { + cb(res, err); + }, + false); +} + +std::string +Client::login_sso_redirect(std::string redirectUrl) +{ + return "https://" + server() + ":" + std::to_string(port()) + + "/_matrix/client/r0/login/sso/redirect?" + + mtx::client::utils::query_params({{"redirectUrl", redirectUrl}}); +} + void Client::well_known(Callback<mtx::responses::WellKnown> callback) { diff --git a/lib/structs/responses/login.cpp b/lib/structs/responses/login.cpp index 894fd261d..5ed8bfa8c 100644 --- a/lib/structs/responses/login.cpp +++ b/lib/structs/responses/login.cpp @@ -19,5 +19,16 @@ from_json(const nlohmann::json &obj, Login &response) if (obj.count("well_known") != 0) response.well_known = obj.at("well_known").get<WellKnown>(); } + +void +from_json(const nlohmann::json &obj, LoginFlow &response) +{ + response.type = obj.at("type").get<std::string>(); +} +void +from_json(const nlohmann::json &obj, LoginFlows &response) +{ + response.flows = obj.at("flows").get<std::vector<LoginFlow>>(); +} } } diff --git a/lib/structs/user_interactive.cpp b/lib/structs/user_interactive.cpp index 7e148ba57..703261a37 100644 --- a/lib/structs/user_interactive.cpp +++ b/lib/structs/user_interactive.cpp @@ -116,6 +116,7 @@ to_json(nlohmann::json &obj, const Auth &auth) obj["threepidCreds"] = id.threepidCreds; }, [&obj](const auth::OAuth2 &) { obj["type"] = auth_types::oauth2; }, + [&obj](const auth::SSO &) { obj["type"] = auth_types::sso; }, [&obj](const auth::Terms &) { obj["type"] = auth_types::terms; }, [&obj](const auth::Dummy &) { obj["type"] = auth_types::dummy; }, [](const auth::Fallback &) {}, diff --git a/tests/client_api.cpp b/tests/client_api.cpp index 8034a4bf5..c56a837c9 100644 --- a/tests/client_api.cpp +++ b/tests/client_api.cpp @@ -113,6 +113,19 @@ TEST(ClientAPI, LoginWrongUsername) mtx_client->close(); } +TEST(ClientAPI, LoginFlows) +{ + std::shared_ptr<Client> mtx_client = std::make_shared<Client>("localhost"); + + mtx_client->get_login([](const mtx::responses::LoginFlows &res, RequestErr err) { + ASSERT_FALSE(err); + + EXPECT_EQ(res.flows[0].type, mtx::user_interactive::auth_types::password); + }); + + mtx_client->close(); +} + TEST(ClientAPI, EmptyUserAvatar) { auto alice = std::make_shared<Client>("localhost"); -- GitLab