FreeRDP
sdl_webview.cpp
1 
20 #include <string>
21 #include <sstream>
22 #include <cstdlib>
23 #include <winpr/string.h>
24 #include <freerdp/log.h>
25 #include <freerdp/utils/aad.h>
26 
27 #include "sdl_webview.hpp"
28 #include "webview_impl.hpp"
29 
30 #define TAG CLIENT_TAG("SDL.webview")
31 
32 static std::string from_settings(const rdpSettings* settings, FreeRDP_Settings_Keys_String id)
33 {
34  auto val = freerdp_settings_get_string(settings, id);
35  if (!val)
36  {
37  WLog_WARN(TAG, "Settings key %s is NULL", freerdp_settings_get_name_for_key(id));
38  return "";
39  }
40  return val;
41 }
42 
43 static std::string from_aad_wellknown(rdpContext* context, AAD_WELLKNOWN_VALUES which)
44 {
45  auto val = freerdp_utils_aad_get_wellknown_string(context, which);
46 
47  if (!val)
48  {
49  WLog_WARN(TAG, "[wellknown] key %s is NULL", freerdp_utils_aad_wellknwon_value_name(which));
50  return "";
51  }
52  return val;
53 }
54 
55 static BOOL sdl_webview_get_rdsaad_access_token(freerdp* instance, const char* scope,
56  const char* req_cnf, char** token)
57 {
58  WINPR_ASSERT(instance);
59  WINPR_ASSERT(scope);
60  WINPR_ASSERT(req_cnf);
61  WINPR_ASSERT(token);
62 
63  WINPR_UNUSED(instance);
64  WINPR_UNUSED(instance->context);
65 
66  auto client_id = from_settings(instance->context->settings, FreeRDP_GatewayAvdClientID);
67  std::string redirect_uri = "ms-appx-web%3a%2f%2fMicrosoft.AAD.BrokerPlugin%2f" + client_id;
68 
69  *token = nullptr;
70 
71  auto ep = from_aad_wellknown(instance->context, AAD_WELLKNOWN_authorization_endpoint);
72  auto url = ep + "?client_id=" + client_id + "&response_type=code&scope=" + scope +
73  "&redirect_uri=" + redirect_uri;
74 
75  const std::string title = "FreeRDP WebView - AAD access token";
76  std::string code;
77  auto rc = webview_impl_run(title, url, code);
78  if (!rc || code.empty())
79  return FALSE;
80 
81  auto token_request = "grant_type=authorization_code&code=" + code + "&client_id=" + client_id +
82  "&scope=" + scope + "&redirect_uri=" + redirect_uri +
83  "&req_cnf=" + req_cnf;
84  return client_common_get_access_token(instance, token_request.c_str(), token);
85 }
86 
87 static BOOL sdl_webview_get_avd_access_token(freerdp* instance, char** token)
88 {
89  WINPR_ASSERT(token);
90  WINPR_ASSERT(instance);
91  WINPR_ASSERT(instance->context);
92 
93  auto client_id = from_settings(instance->context->settings, FreeRDP_GatewayAvdClientID);
94  std::string redirect_uri = "ms-appx-web%3a%2f%2fMicrosoft.AAD.BrokerPlugin%2f" + client_id;
95  std::string scope = "https%3A%2F%2Fwww.wvd.microsoft.com%2F.default";
96 
97  *token = nullptr;
98 
99  auto ep = from_aad_wellknown(instance->context, AAD_WELLKNOWN_authorization_endpoint);
100  auto url = ep + "?client_id=" + client_id + "&response_type=code&scope=" + scope +
101  "&redirect_uri=" + redirect_uri;
102  const std::string title = "FreeRDP WebView - AVD access token";
103  std::string code;
104  auto rc = webview_impl_run(title, url, code);
105  if (!rc || code.empty())
106  return FALSE;
107 
108  auto token_request = "grant_type=authorization_code&code=" + code + "&client_id=" + client_id +
109  "&scope=" + scope + "&redirect_uri=" + redirect_uri;
110  return client_common_get_access_token(instance, token_request.c_str(), token);
111 }
112 
113 BOOL sdl_webview_get_access_token(freerdp* instance, AccessTokenType tokenType, char** token,
114  size_t count, ...)
115 {
116  WINPR_ASSERT(instance);
117  WINPR_ASSERT(token);
118  switch (tokenType)
119  {
120  case ACCESS_TOKEN_TYPE_AAD:
121  {
122  if (count < 2)
123  {
124  WLog_ERR(TAG,
125  "ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
126  ", aborting",
127  count);
128  return FALSE;
129  }
130  else if (count > 2)
131  WLog_WARN(TAG,
132  "ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
133  ", ignoring",
134  count);
135  va_list ap = {};
136  va_start(ap, count);
137  const char* scope = va_arg(ap, const char*);
138  const char* req_cnf = va_arg(ap, const char*);
139  const BOOL rc = sdl_webview_get_rdsaad_access_token(instance, scope, req_cnf, token);
140  va_end(ap);
141  return rc;
142  }
143  case ACCESS_TOKEN_TYPE_AVD:
144  if (count != 0)
145  WLog_WARN(TAG,
146  "ACCESS_TOKEN_TYPE_AVD expected 0 additional arguments, but got %" PRIuz
147  ", ignoring",
148  count);
149  return sdl_webview_get_avd_access_token(instance, token);
150  default:
151  WLog_ERR(TAG, "Unexpected value for AccessTokenType [%" PRIuz "], aborting", tokenType);
152  return FALSE;
153  }
154 }
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
FREERDP_API const char * freerdp_settings_get_name_for_key(SSIZE_T key)
Returns the type name for a key.
Definition: settings_str.c:418