Skip to content

Instantly share code, notes, and snippets.

@pminiszewski
Created November 24, 2021 17:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pminiszewski/cd6d388b356ade1ba097bfc14f71984a to your computer and use it in GitHub Desktop.
Save pminiszewski/cd6d388b356ade1ba097bfc14f71984a to your computer and use it in GitHub Desktop.
// The algorithm
// 1. Create http request
// 2. Attach the access token to the http request headers
// 3. If there is no access token stored in memory:
// 3.1 Notify user that username/password must be provided
// 2.2 On User input create another request to the authentication server, retrieve access token and store it in memory.
// 4. Attach token, execute request and return results
// This is a GUI app, so user will be presented with some modal window asking for login and password.
//How http requests are constructed?
rxcpp::observable<messages::account::TestAccount> Account::get_account_info()
{
rxcpp::observable<>::just<SessionPtr>(cpr::Url{"https://api.example.com/account"}) //prepare request object
.subscribe_on(rxcpp::observe_on_new_thread())
.lift<http::SessionPtr>(operators::auth::AttachJwtToSession(registry_)) // attach token header
.lift<cpr::Response>(http::get(registry_)) // Execute request
.lift<TestAccount>(http::parse_body<TestAccount>()) // convert response to object
.observe_on(registry_.ctx<core::RuntimeContext>().rx_run_loop)
;
}
//GLOBAL DEFINES
std::string jwt_string_;
rx::subjects::subject<bool> event_login_requested;
rx::subjects::subject<messages::auth0::Auth0TokenResponse> event_login_succeeded;
rx::subjects::subject<sdk::api::UserCredentialsLoginPassword> event_credentials_received;
//The operator implementation
rx::subscriber<http::SessionPtr> AttachJwtToSession::operator()(rx::subscriber<http::SessionPtr> _session_sub) const
{
std::string jwt_string = jwt_string_;
return rx::make_subscriber<http::SessionPtr>(
[=](http::SessionPtr _session)
{
if (verify_valid_jwt(jwt_string))
{
_session->UpdateHeader({{"Authorization", "Bearer " + jwt_string}});
_session_sub.on_next(_session);
}
else
{
event_login_requested.get_subscriber().on_next(true); //bring up the login modal window
std::string u, p;
// This is called by user upon providing login/password via login popup.
event_credentials_received.get_observable().
as_blocking().
subscribe([&u, &p](sdk::api::UserCredentialsLoginPassword _creds){
u = _creds.login;
p = _creds.password;
});
cpr::Response _response = cpr::Post(
cpr::Url{"https://auth.example.com/oauth/token"},
cpr::Payload{
{"username",u.c_str()},
{"password", p.c_str()}});
if (_response.status_code == 200)
{
using namespace messages::auth0;
using namespace google::protobuf::util;
Auth0TokenResponse res_msg;
if (JsonStringToMessage(_response.text, &res_msg).ok()) //Authentication succeeed
{
jwt_string_ = res_msg.access_token();
event_login_succeeded.get_subscriber().on_next(res_msg);
_session->UpdateHeader({{"Authorization", "Bearer " + res_msg.access_token()}});
_session_sub.on_next(_session);
}
}
// Some error handling goes here
}
},
[=](const rxu::error_ptr &_err)
{ _session_sub.on_error(_err); },
[=]()
{ _session_sub.on_completed(); });
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment