From 39f7972b28bebf192aaf6145a78ecaac7bd24246 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 21 May 2025 11:40:30 +0200 Subject: [PATCH] [client,common] add common GetCommonAccessToken If client-common is build with WITH_SSO_MIB inject a callback that first tries to retrieve a token from sso-mib library and only if that fails falls back to a client provided callback. --- client/common/client.c | 62 ++--------------------- client/common/sso_mib_tokens.c | 89 ++++++++++++++++++++++++++++++---- client/common/sso_mib_tokens.h | 7 ++- 3 files changed, 88 insertions(+), 70 deletions(-) diff --git a/client/common/client.c b/client/common/client.c index e79ff3ade..b56ac8b9e 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -209,6 +209,10 @@ int freerdp_client_start(rdpContext* context) client_context->mibClientWrapper = NULL; return ERROR_INTERNAL_ERROR; } + client_context->mibClientWrapper->GetCommonAccessToken = + freerdp_get_common_access_token(context); + if (!freerdp_set_common_access_token(context, sso_mib_get_access_token)) + return ERROR_INTERNAL_ERROR; client_context->mibClientWrapper->state = SSO_MIB_STATE_INIT; #endif @@ -1126,27 +1130,6 @@ static BOOL client_cli_get_avd_access_token(freerdp* instance, char** token) *token = NULL; -#ifdef WITH_SSO_MIB - rdpClientContext* client_context = (rdpClientContext*)instance->context; - if (client_context->mibClientWrapper->state == SSO_MIB_STATE_INIT || - client_context->mibClientWrapper->state == SSO_MIB_STATE_SUCCESS) - { - rc = sso_mib_get_avd_access_token(instance, token); - if (rc) - { - client_context->mibClientWrapper->state = SSO_MIB_STATE_SUCCESS; - return rc; - } - else - { - WLog_WARN(TAG, "Getting AVD token from identity broker failed, falling back to " - "browser-based authentication."); - client_context->mibClientWrapper->state = SSO_MIB_STATE_FAILED; - // Fall through to regular avd access token retrieval - } - } -#endif - const char* client_id = freerdp_settings_get_string(instance->context->settings, FreeRDP_GatewayAvdClientID); const char* base = freerdp_settings_get_string(instance->context->settings, @@ -1227,42 +1210,7 @@ BOOL client_cli_get_access_token(freerdp* instance, AccessTokenType tokenType, c va_start(ap, count); const char* scope = va_arg(ap, const char*); const char* req_cnf = va_arg(ap, const char*); - BOOL rc = FALSE; - -#ifdef WITH_SSO_MIB - rdpClientContext* client_context = (rdpClientContext*)instance->context; - if (client_context->mibClientWrapper->state == SSO_MIB_STATE_INIT || - client_context->mibClientWrapper->state == SSO_MIB_STATE_SUCCESS) - { - // Setup scope without URL encoding for sso-mib - char* scope_copy = winpr_str_url_decode(scope, strlen(scope)); - if (!scope_copy) - { - WLog_ERR(TAG, "Failed to decode scope"); - va_end(ap); - return FALSE; - } - - rc = sso_mib_get_rdsaad_access_token(instance, scope_copy, req_cnf, token); - free(scope_copy); - if (rc) - { - client_context->mibClientWrapper->state = SSO_MIB_STATE_SUCCESS; - va_end(ap); - return rc; - } - else - { - WLog_WARN(TAG, "Getting RDS token from identity broker failed, falling back to " - "browser-based authentication."); - client_context->mibClientWrapper->state = SSO_MIB_STATE_FAILED; - // Fall through to regular rdsaad access token retrieval - } - } -#endif // WITH_SSO_MIB - - rc = client_cli_get_rdsaad_access_token(instance, scope, req_cnf, token); - + BOOL rc = client_cli_get_rdsaad_access_token(instance, scope, req_cnf, token); va_end(ap); return rc; } diff --git a/client/common/sso_mib_tokens.c b/client/common/sso_mib_tokens.c index 5e9ad9fc5..22ec3f973 100644 --- a/client/common/sso_mib_tokens.c +++ b/client/common/sso_mib_tokens.c @@ -9,11 +9,12 @@ #include "sso_mib_tokens.h" -BOOL sso_mib_get_avd_access_token(freerdp* instance, char** token) +#include +#define TAG CLIENT_TAG("common.sso") + +static BOOL sso_mib_get_avd_access_token(rdpClientContext* client_context, char** token) { - WINPR_ASSERT(instance); - WINPR_ASSERT(instance->context); - rdpClientContext* client_context = (rdpClientContext*)instance->context; + WINPR_ASSERT(client_context); WINPR_ASSERT(client_context->mibClientWrapper); WINPR_ASSERT(client_context->mibClientWrapper->app); WINPR_ASSERT(token); @@ -52,12 +53,10 @@ cleanup: return rc; } -BOOL sso_mib_get_rdsaad_access_token(freerdp* instance, const char* scope, const char* req_cnf, - char** token) +static BOOL sso_mib_get_rdsaad_access_token(rdpClientContext* client_context, const char* scope, + const char* req_cnf, char** token) { - WINPR_ASSERT(instance); - WINPR_ASSERT(instance->context); - rdpClientContext* client_context = (rdpClientContext*)instance->context; + WINPR_ASSERT(client_context); WINPR_ASSERT(client_context->mibClientWrapper); WINPR_ASSERT(client_context->mibClientWrapper->app); WINPR_ASSERT(scope); @@ -117,3 +116,75 @@ cleanup: g_slist_free_full(scopes, g_free); return rc; } + +BOOL sso_mib_get_access_token(rdpContext* context, AccessTokenType tokenType, char** token, + size_t count, ...) +{ + BOOL rc = FALSE; + rdpClientContext* client_context = (rdpClientContext*)context; + WINPR_ASSERT(client_context); + + const char* scope = NULL; + const char* req_cnf = NULL; + + va_list ap; + va_start(ap, count); + + if (tokenType == ACCESS_TOKEN_TYPE_AAD) + { + scope = va_arg(ap, const char*); + req_cnf = va_arg(ap, const char*); + } + + if ((client_context->mibClientWrapper->state == SSO_MIB_STATE_INIT) || + (client_context->mibClientWrapper->state == SSO_MIB_STATE_SUCCESS)) + { + switch (tokenType) + { + case ACCESS_TOKEN_TYPE_AVD: + { + rc = sso_mib_get_avd_access_token(client_context, token); + if (rc) + client_context->mibClientWrapper->state = SSO_MIB_STATE_SUCCESS; + else + { + WLog_WARN(TAG, "Getting AVD token from identity broker failed, falling back to " + "browser-based authentication."); + client_context->mibClientWrapper->state = SSO_MIB_STATE_FAILED; + } + } + break; + case ACCESS_TOKEN_TYPE_AAD: + { + // Setup scope without URL encoding for sso-mib + char* scope_copy = winpr_str_url_decode(scope, strlen(scope)); + if (!scope_copy) + WLog_ERR(TAG, "Failed to decode scope"); + else + { + rc = + sso_mib_get_rdsaad_access_token(client_context, scope_copy, req_cnf, token); + free(scope_copy); + if (rc) + client_context->mibClientWrapper->state = SSO_MIB_STATE_SUCCESS; + else + { + WLog_WARN(TAG, + "Getting RDS token from identity broker failed, falling back to " + "browser-based authentication."); + client_context->mibClientWrapper->state = SSO_MIB_STATE_FAILED; + } + } + } + break; + default: + break; + } + } + if (!rc && client_context->mibClientWrapper->GetCommonAccessToken) + rc = client_context->mibClientWrapper->GetCommonAccessToken(context, tokenType, token, + count, scope, req_cnf); + va_end(ap); + + return rc; +} diff --git a/client/common/sso_mib_tokens.h b/client/common/sso_mib_tokens.h index 69fab3815..d538931a4 100644 --- a/client/common/sso_mib_tokens.h +++ b/client/common/sso_mib_tokens.h @@ -20,11 +20,10 @@ struct MIBClientWrapper { MIBClientApp* app; enum sso_mib_state state; + pGetCommonAccessToken GetCommonAccessToken; }; -BOOL sso_mib_get_avd_access_token(freerdp* instance, char** token); - -BOOL sso_mib_get_rdsaad_access_token(freerdp* instance, const char* scope, const char* req_cnf, - char** token); +BOOL sso_mib_get_access_token(rdpContext* context, AccessTokenType tokenType, char** token, + size_t count, ...); #endif /* FREERDP_CLIENT_COMMON_SSO_MIB_TOKENS_H */