6#include <sso-mib/sso-mib.h>
7#include <freerdp/crypto/crypto.h>
10#include "sso_mib_tokens.h"
12#include <freerdp/log.h>
13#define TAG CLIENT_TAG("common.sso")
17 SSO_MIB_STATE_INIT = 0,
18 SSO_MIB_STATE_FAILED = 1,
19 SSO_MIB_STATE_SUCCESS = 2,
22struct MIBClientWrapper
25 enum sso_mib_state state;
26 pGetCommonAccessToken GetCommonAccessToken;
29static BOOL sso_mib_get_avd_access_token(rdpClientContext* client_context,
char** token)
31 WINPR_ASSERT(client_context);
32 WINPR_ASSERT(client_context->mibClientWrapper);
33 WINPR_ASSERT(client_context->mibClientWrapper->app);
36 MIBAccount* account = NULL;
37 GSList* scopes = NULL;
42 account = mib_client_app_get_account_by_upn(client_context->mibClientWrapper->app, NULL);
48 scopes = g_slist_append(scopes, g_strdup(
"https://www.wvd.microsoft.com/.default"));
50 MIBPrt* prt = mib_client_app_acquire_token_silent(client_context->mibClientWrapper->app,
51 account, scopes, NULL, NULL, NULL);
54 const char* access_token = mib_prt_get_access_token(prt);
57 *token = strdup(access_token);
62 rc = TRUE && *token != NULL;
65 g_object_unref(account);
66 g_slist_free_full(scopes, g_free);
70static BOOL sso_mib_get_rdsaad_access_token(rdpClientContext* client_context,
const char* scope,
71 const char* req_cnf,
char** token)
73 WINPR_ASSERT(client_context);
74 WINPR_ASSERT(client_context->mibClientWrapper);
75 WINPR_ASSERT(client_context->mibClientWrapper->app);
78 WINPR_ASSERT(req_cnf);
80 GSList* scopes = NULL;
81 WINPR_JSON* json = NULL;
82 MIBPopParams* params = NULL;
86 BYTE* req_cnf_dec = NULL;
87 size_t req_cnf_dec_len = 0;
89 scopes = g_slist_append(scopes, g_strdup(scope));
92 crypto_base64_decode(req_cnf, strlen(req_cnf) + 1, &req_cnf_dec, &req_cnf_dec_len);
114 params = mib_pop_params_new(MIB_AUTH_SCHEME_POP, MIB_REQUEST_METHOD_GET,
"");
115 mib_pop_params_set_kid(params, kid);
116 MIBPrt* prt = mib_client_app_acquire_token_interactive(
117 client_context->mibClientWrapper->app, scopes, MIB_PROMPT_NONE, NULL, NULL, NULL, params);
120 *token = strdup(mib_prt_get_access_token(prt));
127 g_object_unref(params);
130 g_slist_free_full(scopes, g_free);
134static BOOL sso_mib_get_access_token(rdpContext* context, AccessTokenType tokenType,
char** token,
138 rdpClientContext* client_context = (rdpClientContext*)context;
139 WINPR_ASSERT(client_context);
140 WINPR_ASSERT(client_context->mibClientWrapper);
142 if (!client_context->mibClientWrapper->app)
144 const char* client_id =
146 client_context->mibClientWrapper->app =
147 mib_public_client_app_new(client_id, MIB_AUTHORITY_COMMON, NULL, NULL);
150 if (!client_context->mibClientWrapper->app)
153 const char* scope = NULL;
154 const char* req_cnf = NULL;
159 if (tokenType == ACCESS_TOKEN_TYPE_AAD)
161 scope = va_arg(ap,
const char*);
162 req_cnf = va_arg(ap,
const char*);
165 if ((client_context->mibClientWrapper->state == SSO_MIB_STATE_INIT) ||
166 (client_context->mibClientWrapper->state == SSO_MIB_STATE_SUCCESS))
170 case ACCESS_TOKEN_TYPE_AVD:
172 rc = sso_mib_get_avd_access_token(client_context, token);
174 client_context->mibClientWrapper->state = SSO_MIB_STATE_SUCCESS;
177 WLog_WARN(TAG,
"Getting AVD token from identity broker failed, falling back to "
178 "browser-based authentication.");
179 client_context->mibClientWrapper->state = SSO_MIB_STATE_FAILED;
183 case ACCESS_TOKEN_TYPE_AAD:
186 char* scope_copy = winpr_str_url_decode(scope, strlen(scope));
188 WLog_ERR(TAG,
"Failed to decode scope");
192 sso_mib_get_rdsaad_access_token(client_context, scope_copy, req_cnf, token);
195 client_context->mibClientWrapper->state = SSO_MIB_STATE_SUCCESS;
199 "Getting RDS token from identity broker failed, falling back to "
200 "browser-based authentication.");
201 client_context->mibClientWrapper->state = SSO_MIB_STATE_FAILED;
210 if (!rc && client_context->mibClientWrapper->GetCommonAccessToken)
211 rc = client_context->mibClientWrapper->GetCommonAccessToken(context, tokenType, token,
212 count, scope, req_cnf);
218MIBClientWrapper* sso_mib_new(rdpContext* context)
221 MIBClientWrapper* mibClientWrapper = (MIBClientWrapper*)calloc(1,
sizeof(MIBClientWrapper));
222 if (!mibClientWrapper)
225 mibClientWrapper->GetCommonAccessToken = freerdp_get_common_access_token(context);
226 if (!freerdp_set_common_access_token(context, sso_mib_get_access_token))
228 sso_mib_free(mibClientWrapper);
231 mibClientWrapper->state = SSO_MIB_STATE_INIT;
232 return mibClientWrapper;
235void sso_mib_free(MIBClientWrapper* sso)
241 g_object_unref(sso->app);
WINPR_API WINPR_JSON * WINPR_JSON_GetObjectItem(const WINPR_JSON *object, const char *string)
Return a pointer to an JSON object item.
WINPR_API const char * WINPR_JSON_GetStringValue(WINPR_JSON *item)
Return the String value of a JSON item.
WINPR_API void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.
WINPR_API WINPR_JSON * WINPR_JSON_Parse(const char *value)
Parse a '\0' terminated JSON string.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.