Skip to content

Commit 12ea725

Browse files
magnusg-kdabRalphSteinhagen
authored andcommitted
OAuth: Return assigned roles as part of the OAuth output
Signed-off-by: Magnus Groß <magnus.gross+github@kdab.com>
1 parent f0b6cef commit 12ea725

2 files changed

Lines changed: 41 additions & 8 deletions

File tree

src/services/include/services/OAuthClient.hpp

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ struct OAuthOutput {
2727
std::string secret;
2828
std::string accessToken;
2929
std::string refreshToken;
30+
std::string roles;
3031
};
3132
} // namespace opencmw
3233

3334
ENABLE_REFLECTION_FOR(opencmw::OAuthContext, secretToken)
3435
ENABLE_REFLECTION_FOR(opencmw::OAuthInput, scope, clientId, clientSecret, secret, publicKey)
35-
ENABLE_REFLECTION_FOR(opencmw::OAuthOutput, authorizationUri, secret, accessToken, refreshToken)
36+
ENABLE_REFLECTION_FOR(opencmw::OAuthOutput, authorizationUri, secret, accessToken, refreshToken, roles)
3637

3738
namespace opencmw {
3839

@@ -91,13 +92,14 @@ class OAuthClient {
9192
StrictUri _redirectUri;
9293
StrictUri _endpoint;
9394
StrictUri _tokenEndpoint;
95+
StrictUri _userinfoEndpoint;
9496
httplib::Server _srv;
9597
std::unique_ptr<std::thread> _thread;
9698
std::function<void(const std::string &code, const std::string &state)> _endpointCallback;
9799

98100
public:
99-
explicit OAuthClient(StrictUri redirectUri, StrictUri endpoint, StrictUri tokenEndpoint)
100-
: _redirectUri(redirectUri), _endpoint(endpoint), _tokenEndpoint(tokenEndpoint) {
101+
explicit OAuthClient(StrictUri redirectUri, StrictUri endpoint, StrictUri tokenEndpoint, StrictUri userinfoEndpoint = StrictUri(""))
102+
: _redirectUri(redirectUri), _endpoint(endpoint), _tokenEndpoint(tokenEndpoint), _userinfoEndpoint(userinfoEndpoint) {
101103
_srv.Get("/", [&](const httplib::Request req, httplib::Response &res) {
102104
std::string code, state, error;
103105
// response as per https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2
@@ -213,6 +215,33 @@ class OAuthClient {
213215
return getAccessToken({ { "grant_type", "refresh_token" }, { "refresh_token", refreshToken }, { "client_id", clientId } });
214216
}
215217

218+
std::string getAssignedRoles(const std::string &accessToken) {
219+
auto client = getClient(_userinfoEndpoint);
220+
if (!client) {
221+
return {};
222+
}
223+
224+
httplib::Headers headers{ { { "Authorization", "Bearer " + accessToken } } };
225+
auto res = client->Get(*_userinfoEndpoint.path(), headers);
226+
if (!res || res->status != 200) {
227+
return {};
228+
}
229+
std::string s{ res->body.c_str() };
230+
const std::string marker{ "\"account\":{\"roles\":[" };
231+
auto start = s.find(marker);
232+
if (start == std::string::npos) {
233+
return {};
234+
}
235+
start += marker.size();
236+
const auto end = s.find("]", start);
237+
if (end == std::string::npos) {
238+
return {};
239+
}
240+
std::string roles = s.substr(start, end - start);
241+
std::erase(roles, '\"');
242+
return roles;
243+
}
244+
216245
void stop() {
217246
_srv.stop();
218247
_thread->join();
@@ -246,11 +275,11 @@ using OAuthWorkerType = majordomo::Worker<"/oauth", OAuthContext, OAuthInput, OA
246275

247276
class OAuthWorker : public OAuthWorkerType {
248277
public:
249-
explicit OAuthWorker(StrictUri redirectUri, StrictUri endpoint, StrictUri tokenEndpoint, StrictUri brokerAddress, const zmq::Context &context, majordomo::Settings settings = {})
250-
: OAuthWorkerType(brokerAddress, {}, context, settings), _client(redirectUri, endpoint, tokenEndpoint), _keystore(brokerAddress, context, settings) { init(); };
278+
explicit OAuthWorker(StrictUri redirectUri, StrictUri endpoint, StrictUri tokenEndpoint, StrictUri userinfoEndpoint, StrictUri brokerAddress, const zmq::Context &context, majordomo::Settings settings = {})
279+
: OAuthWorkerType(brokerAddress, {}, context, settings), _client(redirectUri, endpoint, tokenEndpoint, userinfoEndpoint), _keystore(brokerAddress, context, settings) { init(); };
251280
template<typename BrokerType>
252-
explicit OAuthWorker(StrictUri redirecturi, StrictUri endpoint, StrictUri tokenEndpoint, const BrokerType &broker)
253-
: OAuthWorkerType(broker, {}), _client(redirecturi, endpoint, tokenEndpoint), _keystore(broker) { init(); };
281+
explicit OAuthWorker(StrictUri redirecturi, StrictUri endpoint, StrictUri tokenEndpoint, StrictUri userinfoEndpoint, const BrokerType &broker)
282+
: OAuthWorkerType(broker, {}), _client(redirecturi, endpoint, tokenEndpoint, userinfoEndpoint), _keystore(broker) { init(); };
254283
~OAuthWorker() {
255284
_keystore.shutdown();
256285
_keystoreThread.join();
@@ -292,6 +321,9 @@ class OAuthWorker : public OAuthWorkerType {
292321
const auto access = _client.requestToken(code, in.clientId);
293322
out.accessToken = access.accessToken._token;
294323
out.refreshToken = access.refreshToken._token;
324+
325+
// get RBAC roles
326+
out.roles = _client.getAssignedRoles(out.accessToken);
295327
}
296328
});
297329
_keystoreThread = std::thread([this] { _keystore.run(); });

src/services/test/OAuthClient_tests.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ TEST_CASE("Worker test", "[OAuth]") {
106106
opencmw::URI(redirectBase),
107107
opencmw::URI(kcBase + "/realms/testrealm/protocol/openid-connect/auth"),
108108
opencmw::URI(kcBase + "/realms/testrealm/protocol/openid-connect/token"),
109-
broker
109+
opencmw::URI(kcBase + "/realms/testrealm/protocol/openid-connect/userinfo"),
110+
broker
110111
};
111112

112113
REQUIRE(broker.bind(opencmw::URI<>("mds://127.0.0.1:12345")));

0 commit comments

Comments
 (0)